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

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: 
1.1.1.8   root        7: //
                      8: // CRTC
                      9: //
1.1       root       10: 
1.1.1.4   root       11: // e80000..e803ff 内は $40 バイトでミラー。
                     12: // e80400..e807ff 内は 256 バイトでミラーになっており、このうち
                     13: // +$00..+$7f はバスエラー、
                     14: // +$80..+$ff は何かが読める。
                     15: // 仕様は $e80480.w に1ポートあるので、これがワードで全域にミラーされている?
                     16: // 全体としては この $800 バイトずつが繰り返して見える。
1.1.1.12  root       17: //
                     18: // CRTC はデバイスの配置としては BusIO_B 相当で、バイトアクセスも行えるが、
                     19: // 内部はバイトレジスタではなくワード単位を基本構造としている。そのため
                     20: // BusIO は使わず自力で処理する。ログの観点からもこのほうが都合がいい。
1.1.1.4   root       21: 
1.1.1.8   root       22: #include "crtc.h"
1.1.1.15! root       23: #include "event.h"
1.1.1.8   root       24: #include "mfp.h"
1.1.1.13  root       25: #include "monitor.h"
1.1.1.8   root       26: #include "scheduler.h"
                     27: #include "tvram.h"
1.1.1.13  root       28: #include "videoctlr.h"
1.1.1.8   root       29: 
1.1.1.11  root       30: // InsideOut p.135
1.1.1.15! root       31: /*static*/ const busdata
        !            32: CRTCDevice::wait = busdata::Wait(9 * 40_nsec);
1.1.1.11  root       33: 
1.1.1.8   root       34: // コンストラクタ
1.1       root       35: CRTCDevice::CRTCDevice()
1.1.1.10  root       36:        : inherited(OBJ_CRTC)
1.1       root       37: {
1.1.1.13  root       38:        monitor = gMonitorManager->Regist(ID_MONITOR_CRTC, this);
                     39:        monitor->func = ToMonitorCallback(&CRTCDevice::MonitorUpdate);
1.1.1.15! root       40:        monitor->SetSize(79, 27);
1.1       root       41: }
                     42: 
1.1.1.8   root       43: // デストラクタ
1.1       root       44: CRTCDevice::~CRTCDevice()
                     45: {
1.1.1.10  root       46: }
                     47: 
                     48: // 初期化
                     49: bool
                     50: CRTCDevice::Init()
                     51: {
                     52:        mfp = GetMFPDevice();
                     53:        tvram = GetTVRAMDevice();
1.1.1.13  root       54:        videoctlr = GetVideoCtlrDevice();
1.1.1.10  root       55: 
1.1.1.15! root       56:        auto evman = GetEventManager();
        !            57:        hsync_event = evman->Regist(this,
        !            58:                ToEventCallback(&CRTCDevice::HSyncCallback),
        !            59:                "CRTC H-Sync");
        !            60:        vdisp_event = evman->Regist(this,
        !            61:                ToEventCallback(&CRTCDevice::VDispCallback),
        !            62:                "CRTC V-Disp");
1.1.1.12  root       63: 
                     64:        // ラスターコピーは実際には CRTC の機能ではなく TVRAM (VRAM チップ) の
                     65:        // 機能だが、イベントの時間管理が発生するのは CRTC 側なのでここで管理。
                     66:        // X68030 搭載の VRAM チップは HM514402A だが、ここでは X68000 XVI 搭載の
                     67:        // HM53461 の値を使用し、これが最小 190nsec * 2 らしいので
                     68:        // とりあえず 400nsec としておく。
1.1.1.15! root       69:        raster_event = evman->Regist(this,
        !            70:                ToEventCallback(&CRTCDevice::RasterCallback),
        !            71:                "CRTC Raster Copy");
        !            72:        raster_event->time = 400_nsec;
1.1.1.12  root       73: 
1.1.1.10  root       74:        return true;
1.1       root       75: }
                     76: 
1.1.1.8   root       77: // リセット
1.1       root       78: void
1.1.1.8   root       79: CRTCDevice::ResetHard(bool poweron)
1.1       root       80: {
                     81:        // XXX 初期値適当
                     82:        crtc.r[20] = 0x0016;
                     83: 
                     84:        // XXX 適当
1.1.1.8   root       85:        // すぐに水平同期と垂直帰線期間を開始する
1.1.1.15! root       86:        hsync_state = 1;
        !            87:        hsync_event->time = 0;
1.1.1.10  root       88:        scheduler->RestartEvent(hsync_event);
1.1.1.15! root       89:        vdisp_state = 1;
        !            90:        vdisp_event->time = 0;
1.1.1.10  root       91:        scheduler->RestartEvent(vdisp_event);
1.1       root       92: }
                     93: 
1.1.1.12  root       94: /*static*/ inline uint32
                     95: CRTCDevice::Decoder(uint32 addr)
1.1       root       96: {
1.1.1.12  root       97:        return addr & 0x7ff;
1.1.1.11  root       98: }
                     99: 
                    100: busdata
1.1.1.12  root      101: CRTCDevice::Read(busaddr addr)
1.1.1.11  root      102: {
1.1.1.12  root      103:        uint32 offset = Decoder(addr.Addr());
                    104:        busdata data = Peek2(offset);
                    105: 
                    106:        uint32 reqsize = addr.GetSize();
                    107:        if (reqsize == 1) {
                    108:                if ((offset & 1) == 0) {
                    109:                        data >>= 8;
                    110:                } else {
                    111:                        data &= 0xff;
                    112:                }
                    113:                data |= BusData::Size1;
                    114:        } else {
                    115:                data |= BusData::Size2;
                    116:        }
1.1.1.11  root      117: 
                    118:        if (__predict_false(loglevel >= 2)) {
                    119:                if (offset < 0x400) {
                    120:                        // CRTC レジスタは 0x40 バイトでミラー
1.1.1.12  root      121:                        uint32 regno = (offset >> 1) & 0x1f;
                    122:                        if (regno < countof(crtc.r)) {
                    123:                                // R20, R21 のみ読み出し可能だが、
                    124:                                // R21 へのアクセスは多いのでログレベルを上げておく。
                    125:                                int lv = (regno == 21) ? 3 : 2;
                    126:                                if (reqsize == 1) {
                    127:                                        putlog(lv, "R%02u.%c -> $%02x", regno,
                    128:                                                (((offset & 1) == 0) ? 'H' : 'L'), data.Data());
                    129:                                } else {
                    130:                                        putlog(lv, "R%02u -> $%04x", regno, data.Data());
                    131:                                }
1.1.1.11  root      132:                        } else {
1.1.1.12  root      133:                                putlog(3, "$%06x -> $%0*x", addr.Addr(),
                    134:                                        reqsize * 2, data.Data());
1.1.1.11  root      135:                        }
1.1       root      136:                }
                    137:        }
                    138: 
1.1.1.11  root      139:        data |= wait;
1.1       root      140:        return data;
                    141: }
                    142: 
1.1.1.11  root      143: busdata
1.1.1.12  root      144: CRTCDevice::Write(busaddr addr, uint32 data)
1.1       root      145: {
1.1.1.11  root      146:        busdata r;
1.1.1.12  root      147:        uint32 offset = Decoder(addr.Addr());
                    148:        uint32 reqsize = addr.GetSize();
                    149:        uint32 datasize = std::min(2 - (offset & 1), reqsize);
                    150:        data >>= (reqsize - datasize) * 8;
1.1.1.5   root      151: 
1.1.1.11  root      152:        if (offset < 0x400) {
                    153:                // CRTC レジスタは 0x40 バイトでミラー
1.1.1.12  root      154:                uint32 regno = (offset >> 1) & 0x1f;
1.1.1.11  root      155:                if (regno < countof(crtc.r)) {
1.1.1.12  root      156:                        if (datasize == 1) {
                    157:                                // バイト書き込み
                    158:                                if ((offset & 1) == 0) {
                    159:                                        data = (data << 8) | (crtc.r[regno] & 0xff);
                    160:                                } else {
                    161:                                        data = (crtc.r[regno] & 0xff00) | data;
                    162:                                }
1.1.1.11  root      163:                        } else {
1.1.1.12  root      164:                                // ワード書き込み
1.1.1.11  root      165:                        }
1.1.1.12  root      166:                        SetReg(regno, data);
1.1       root      167:                } else {
1.1.1.4   root      168:                        // ここ何がいるんだ?
1.1.1.12  root      169:                        putlog(2, "$%06x <- $%0*x", addr.Addr(), datasize * 2, data);
1.1       root      170:                }
1.1.1.11  root      171:        } else {
                    172:                // 動作ポート
                    173:                if ((offset & 0x80) == 0) {     // +$00..+$7f
                    174:                        r.SetBusErr();
1.1.1.4   root      175:                } else {
1.1.1.12  root      176:                        if (datasize == 1) {
                    177:                                // バイト書き込み
                    178:                                if ((offset & 1) == 0) {
                    179:                                        data = (data << 8) | crtc.op;
                    180:                                } else {
                    181:                                        data = (crtc.op & 0xff00) | data;
                    182:                                }
                    183:                        } else {
                    184:                                // ワード書き込み
                    185:                        }
1.1.1.8   root      186:                        WriteOp(data);
1.1       root      187:                }
                    188:        }
1.1.1.4   root      189: 
1.1.1.11  root      190:        r |= wait;
1.1.1.12  root      191:        r |= busdata::Size(datasize);
1.1.1.11  root      192:        return r;
1.1       root      193: }
                    194: 
1.1.1.11  root      195: busdata
1.1.1.12  root      196: CRTCDevice::Peek1(uint32 addr)
1.1       root      197: {
1.1.1.12  root      198:        busdata data = Peek2(addr);
1.1.1.11  root      199:        if (data.IsOK()) {
                    200:                if ((addr & 1) == 0) {
                    201:                        return data.Data() >> 8;
                    202:                } else {
                    203:                        return data.Data() & 0xff;
                    204:                }
                    205:        } else {
1.1.1.12  root      206:                return BusData::BusErr;
1.1.1.11  root      207:        }
                    208: }
1.1       root      209: 
1.1.1.11  root      210: // addr のワードとしての読み出し値を返す。
1.1.1.12  root      211: // これは内部用で Read() からも呼ばれるので、
                    212: // バスエラーなら BusData::BusErr を返す。
1.1.1.11  root      213: busdata
1.1.1.12  root      214: CRTCDevice::Peek2(uint32 addr) const
1.1.1.11  root      215: {
                    216:        busdata data;
                    217: 
1.1.1.12  root      218:        uint32 offset = Decoder(addr);
1.1.1.11  root      219:        if (offset < 0x400) {
                    220:                // CRTC レジスタは 0x40 バイトでミラー
                    221:                uint32 regno = (offset & 0x3f) / 2;
                    222:                if (regno == 20 || regno == 21) {
1.1.1.4   root      223:                        // R20, R21 のみ読み出し可能
1.1.1.11  root      224:                        data = crtc.r[regno];
1.1.1.4   root      225:                } else {
                    226:                        data = 0;
                    227:                }
1.1.1.11  root      228:        } else {
                    229:                // 動作ポート
                    230:                if ((offset & 0x80) == 0) {
                    231:                        data.SetBusErr();
1.1.1.4   root      232:                } else {
                    233:                        data = crtc.op;
                    234:                }
1.1       root      235:        }
1.1.1.4   root      236: 
                    237:        return data;
1.1       root      238: }
                    239: 
1.1.1.15! root      240: // 今の所、標準設定しかサポートしていないので、違う時だけログを出したりする。
        !           241: static const uint16 crtc_supported[] = {
        !           242:        0x0089, // R00
        !           243:        0x000e, // R01
        !           244:        0x001c, // R02
        !           245:        0x007c, // R03
        !           246:        0x0237, // R04
        !           247:        0x0005, // R05
        !           248:        0x0028, // R06
        !           249:        0x0228, // R07
        !           250:        0,              // R08
        !           251:        0,              // R09
        !           252:        0,              // R10
        !           253:        0,              // R11
        !           254:        0x0000, // R12
        !           255:        0x0000, // R13
        !           256:        0x0000, // R14
        !           257:        0x0000, // R15
        !           258:        0x0000, // R16
        !           259:        0x0000, // R17
        !           260:        0x0000, // R18
        !           261:        0x0000, // R19
        !           262: };
        !           263: 
1.1.1.8   root      264: void
                    265: CRTCDevice::MonitorUpdate(Monitor *, TextScreen& screen)
                    266: {
                    267:        int y;
                    268:        uint16 val;
                    269: 
                    270:        screen.Clear();
                    271:        y = 0;
1.1.1.9   root      272: 
                    273:        screen.Print(0, y++, "R00:$%04x (V.Total)",      crtc.r[0]);
                    274:        screen.Print(0, y++, "R01:$%04x (V.Sync End)",   crtc.r[1]);
                    275:        screen.Print(0, y++, "R02:$%04x (V.Disp Start)", crtc.r[2]);
                    276:        screen.Print(0, y++, "R02:$%04x (V.Disp End)",   crtc.r[3]);
                    277: 
                    278:        screen.Print(0, y++, "R04:$%04x (H.Total)",      crtc.r[4]);
                    279:        screen.Print(0, y++, "R05:$%04x (H.Sync End)",   crtc.r[5]);
                    280:        screen.Print(0, y++, "R06:$%04x (H.Disp Start)", crtc.r[6]);
                    281:        screen.Print(0, y++, "R07:$%04x (H.Disp End)",   crtc.r[7]);
                    282: 
1.1.1.8   root      283:        screen.Print(0, y++, "R10:$%04x (Text ScrollX)", crtc.r[10]);
                    284:        screen.Print(0, y++, "R11:$%04x (Text ScrollY)", crtc.r[11]);
                    285: 
1.1.1.15! root      286:        screen.Print(0, y++, "R12:$%04x (Grp. Page0 X)", crtc.r[12]);
        !           287:        screen.Print(0, y++, "R13:$%04x (Grp. Page0 Y)", crtc.r[13]);
        !           288:        screen.Print(0, y++, "R14:$%04x (Grp. Page1 X)", crtc.r[14]);
        !           289:        screen.Print(0, y++, "R15:$%04x (Grp. Page1 Y)", crtc.r[15]);
        !           290:        screen.Print(0, y++, "R16:$%04x (Grp. Page2 X)", crtc.r[16]);
        !           291:        screen.Print(0, y++, "R17:$%04x (Grp. Page2 Y)", crtc.r[17]);
        !           292:        screen.Print(0, y++, "R18:$%04x (Grp. Page3 X)", crtc.r[18]);
        !           293:        screen.Print(0, y++, "R19:$%04x (Grp. Page3 Y)", crtc.r[19]);
        !           294: 
        !           295:        for (uint i = 0; i < countof(crtc_supported); i++) {
        !           296:                if (8 <= i && i < 12) {
        !           297:                        continue;
        !           298:                }
        !           299:                if (crtc.r[i] != crtc_supported[i]) {
        !           300:                        screen.Print(29, (i < 8 ? i : i - 2), TA::On,
        !           301:                                "(not supported value)");
        !           302:                }
        !           303:        }
        !           304: 
        !           305:        //  3         4         5         6         7
        !           306:        // 90123456789012345678901234567890123456789012345678
        !           307:        // SIZ=1024x1024 COL=65536 HF=31kHz VD=undef HD=50MHz
1.1.1.9   root      308:        val = crtc.r[20];
                    309:        screen.Print(0, y,   "R20:$%04x (Mode)", val);
1.1.1.15! root      310:        screen.Print(29, y, "SIZ=%s", VideoCtlrDevice::siz_str[(val >> 10) & 1]);
        !           311:        screen.Print(43, y, "COL=%s", VideoCtlrDevice::col_str[(val >>  8) & 3]);
        !           312:        screen.Print(53, y, "HF=%ukHz", 15 + (val & 0x10));
1.1.1.9   root      313:        static const char * const r20vd_str[] = {
                    314:                "256",
                    315:                "512",
                    316:                "1024",
                    317:                "undef",
                    318:        };
1.1.1.15! root      319:        screen.Print(62, y, "VD=%s", r20vd_str[(val >> 2) & 3]);
1.1.1.9   root      320:        static const char * const r20hd_str[] = {
                    321:                "256",
                    322:                "512",
                    323:                "768",
                    324:                "50MHz",
                    325:        };
1.1.1.15! root      326:        screen.Print(71, y, "HD=%s", r20hd_str[val & 3]);
1.1.1.9   root      327:        y++;
                    328: 
1.1.1.8   root      329:        val = crtc.r[21];
                    330:        screen.Print(0, y,   "R21:$%04x (Text Plane)", val);
                    331:        screen.Print(29, y,  "MEN=%c SA=%c AP=%%%c%c%c%c CP=%%%c%c%c%c",
                    332:                (val & 0x0200) ? '1' : '0',
                    333:                (val & 0x0100) ? '1' : '0',
                    334:                (val & 0x0080) ? '1' : '0',
                    335:                (val & 0x0040) ? '1' : '0',
                    336:                (val & 0x0020) ? '1' : '0',
                    337:                (val & 0x0010) ? '1' : '0',
                    338:                (val & 0x0008) ? '1' : '0',
                    339:                (val & 0x0004) ? '1' : '0',
                    340:                (val & 0x0002) ? '1' : '0',
                    341:                (val & 0x0001) ? '1' : '0');
                    342:        y++;
                    343: 
                    344:        val = crtc.r[22];
                    345:        screen.Print(0, y++, "R22:$%04x (Text Raster Copy) src=$%02x dst=$%02x",
                    346:                val, (val >> 8), (val & 0xff));
                    347: 
                    348:        screen.Print(0, y++, "R23:$%04x (Text Access Mask)", crtc.r[23]);
1.1.1.15! root      349: 
        !           350:        // ビデオコントローラもここに並べたほうが読みやすいか。
        !           351:        y++;
        !           352:        screen.Puts(0, y++, "<Video Controller>");
        !           353:        videoctlr->MonitorUpdate(screen, y, crtc.r[20]);
1.1.1.8   root      354: }
                    355: 
1.1.1.4   root      356: // CRTC レジスタへの書き込み。
                    357: // reg は CRTC::R00 .. CRTC::R23
1.1       root      358: void
1.1.1.4   root      359: CRTCDevice::SetReg(uint32 reg, uint32 data)
1.1       root      360: {
                    361:        crtc.r[reg] = data;
                    362: 
                    363:        switch (reg) {
1.1.1.15! root      364:         case CRTC::R00 ... CRTC::R07:
        !           365:         case CRTC::R12 ... CRTC::R19:
        !           366:                if (crtc.r[reg] == crtc_supported[reg]) {
        !           367:                        putlog(2, "R%02u <- $%04x", reg, data);
        !           368:                        return;
        !           369:                }
        !           370:                break;
1.1.1.4   root      371:         case CRTC::R10:
1.1.1.12  root      372:                putlog(2, "R%02u <- $%04x", reg, data);
1.1.1.10  root      373:                tvram->SetScrollX(crtc.r[10]);
1.1.1.15! root      374:                return;
1.1.1.4   root      375:         case CRTC::R11:
1.1.1.12  root      376:                putlog(2, "R%02u <- $%04x", reg, data);
1.1.1.10  root      377:                tvram->SetScrollY(crtc.r[11]);
1.1.1.15! root      378:                return;
1.1       root      379:         case CRTC::R21:
1.1.1.4   root      380:                // 頻度が高いのでログレベルを上げておく
1.1.1.12  root      381:                putlog(3, "R%02u <- $%04x", reg, data);
1.1.1.10  root      382:                tvram->SetAccessPlane(crtc.r[21]);
1.1.1.15! root      383:                return;
1.1.1.8   root      384:         case CRTC::R22:
1.1.1.12  root      385:                putlog(3, "R%02u <- $%04x", reg, data);
1.1.1.15! root      386:                return;
1.1.1.8   root      387:         case CRTC::R23:
                    388:                // 頻度が高いのでログレベルを上げておく
1.1.1.12  root      389:                putlog(3, "R%02u <- $%04x", reg, data);
1.1.1.10  root      390:                tvram->SetAccessMask(crtc.r[23]);
1.1.1.15! root      391:                return;
1.1       root      392:         default:
1.1.1.4   root      393:                break;
1.1       root      394:        }
1.1.1.15! root      395:        putlog(0, "R%02u <- $%04x (NOT IMPLEMENTED)", reg, data);
1.1       root      396: }
                    397: 
1.1.1.8   root      398: // 動作ポートへの書き込み。
                    399: void
                    400: CRTCDevice::WriteOp(uint32 data)
                    401: {
                    402:        uint16 oldop = crtc.op;
                    403: 
                    404:        crtc.op = data & 0x0b;
1.1.1.12  root      405:        putlog(2, "OP <- $%04x", crtc.op);
1.1.1.8   root      406: 
                    407:        uint16 change = oldop ^ crtc.op;
                    408: 
                    409:        if ((change & CRTC::OP_RC)) {
                    410:                // テキスト画面ラスターコピー
                    411:                if ((crtc.op & CRTC::OP_RC)) {
                    412:                        // 0->1 開始
1.1.1.9   root      413:                        raster_copy = true;
1.1.1.12  root      414:                        putlog(3, "Start Raster copy (ラスターコピー指示");
1.1.1.8   root      415:                } else {
1.1.1.9   root      416:                        // 1->0 は停止じゃなくキャンセル?
                    417:                        raster_copy = false;
1.1.1.12  root      418:                        putlog(3, "Cancel Raster copy (ラスターコピーキャンセル)");
1.1.1.8   root      419:                }
                    420:        }
                    421: 
                    422:        if ((change & 0x03)) {
1.1.1.12  root      423:                putlog(0, "OP (動作ポート) $%02x <- $%02x (NOT IMPLEMENTED)",
1.1.1.8   root      424:                        oldop & 0x03, crtc.op & 0x03);
                    425:        }
                    426: }
                    427: 
                    428: // 水平同期イベント
                    429: void
1.1.1.15! root      430: CRTCDevice::HSyncCallback(Event *ev)
1.1.1.8   root      431: {
1.1.1.15! root      432:        switch (hsync_state) {
1.1.1.9   root      433:         case 0:        // フロントポーチ
                    434:                // フロントポーチ
1.1.1.15! root      435:                ev->time = 2.07_usec;
        !           436:                hsync_state++;
1.1.1.9   root      437:                break;
1.1.1.8   root      438: 
1.1.1.9   root      439:         case 1:        // 水平同期パルス
1.1.1.8   root      440:                // 水平同期期間
1.1.1.15! root      441:                ev->time = 3.45_usec;
        !           442:                hsync_state++;
1.1.1.9   root      443: 
                    444:                // GPIP の状態を更新
1.1.1.10  root      445:                mfp->SetHSync(true);
1.1.1.9   root      446: 
                    447:                // ラスターコピーが指示されていたら実行
                    448:                if (raster_copy) {
                    449:                        raster_copy = false;
                    450: 
1.1.1.12  root      451:                        uint src = (crtc.r[22] >> 8)   * 4;
                    452:                        uint dst = (crtc.r[22] & 0xff) * 4;
1.1.1.10  root      453:                        tvram->RasterCopy(src, dst);
1.1.1.9   root      454: 
                    455:                        // 所定時間後に完了させる
1.1.1.10  root      456:                        scheduler->RestartEvent(raster_event);
1.1.1.9   root      457:                }
                    458:                break;
                    459: 
                    460:         case 2:        // バックポーチ + 表示期間
                    461:                // バックポーチ + Hdisp
1.1.1.15! root      462:                ev->time = 4.14_usec + 22.09_usec;
        !           463:                hsync_state = 0;
1.1.1.9   root      464: 
                    465:                // GPIP の状態を更新
1.1.1.10  root      466:                mfp->SetHSync(false);
1.1.1.9   root      467:                break;
1.1.1.15! root      468: 
        !           469:         default:
        !           470:                __unreachable();
1.1.1.8   root      471:        }
1.1.1.9   root      472: 
1.1.1.10  root      473:        scheduler->StartEvent(ev);
1.1.1.8   root      474: }
                    475: 
1.1.1.9   root      476: // ラスターコピー完了イベント
                    477: void
1.1.1.15! root      478: CRTCDevice::RasterCallback(Event *ev)
1.1.1.9   root      479: {
                    480:        // 終わったら動作ポートの RC ビットを %0 にする?
                    481:        crtc.op &= ~CRTC::OP_RC;
                    482: }
                    483: 
1.1       root      484: // 垂直表示・帰線イベント
1.1.1.15! root      485: // vdisp_state が 1 なら表示期間開始(V-disp)、0 なら帰線期間開始(V-blank)。
1.1       root      486: void
1.1.1.15! root      487: CRTCDevice::VDispCallback(Event *ev)
1.1       root      488: {
                    489:        // GPIP の状態を更新
1.1.1.15! root      490:        mfp->SetVDisp(vdisp_state);
1.1       root      491: 
                    492:        // 今はここで1画面まるごと作成
1.1.1.15! root      493:        if (vdisp_state) {
1.1.1.13  root      494:                videoctlr->VDisp();
1.1       root      495:        }
                    496: 
                    497:        // 次のタイミングを計算
                    498:        // XXX まだ CRTC から計算していない
1.1.1.15! root      499:        if (vdisp_state) {
1.1       root      500:                // 垂直表示期間
1.1.1.15! root      501:                ev->time = 16250_usec;
        !           502:                vdisp_state = 0;
1.1       root      503:        } else {
                    504:                // 垂直帰線期間
1.1.1.15! root      505:                ev->time = 191_usec + 1111_usec + 476_usec;
        !           506:                vdisp_state = 1;
1.1       root      507:        }
1.1.1.10  root      508:        scheduler->StartEvent(ev);
1.1       root      509: }

unix.superglobalmegacorp.com

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