--- nono/vm/crtc.cpp 2026/04/29 17:05:09 1.1.1.8 +++ nono/vm/crtc.cpp 2026/04/29 17:05:13 1.1.1.9 @@ -35,10 +35,16 @@ CRTCDevice::CRTCDevice() hsync_event.func = ToEventCallback(&CRTCDevice::HSyncCallback); hsync_event.Regist("CRTC H-Sync"); vdisp_event.func = ToEventCallback(&CRTCDevice::VDispCallback); - vdisp_event.Regist("CRTC V-DISP"); + vdisp_event.Regist("CRTC V-Disp"); + + // ラスターコピーにかかる時間は最小 190nsec * 2 らしいので + // とりあえず 400nsec としておく。 + raster_event.func = ToEventCallback(&CRTCDevice::RasterCallback); + raster_event.time = 400_nsec; + raster_event.Regist("CRTC Raster Copy"); monitor.func = ToMonitorCallback(&CRTCDevice::MonitorUpdate); - monitor.SetSize(60, 5); + monitor.SetSize(62, 14); monitor.Regist(ID_MONITOR_CRTC); } @@ -167,11 +173,48 @@ CRTCDevice::MonitorUpdate(Monitor *, Tex uint16 val; screen.Clear(); - y = 0; + + screen.Print(0, y++, "R00:$%04x (V.Total)", crtc.r[0]); + screen.Print(0, y++, "R01:$%04x (V.Sync End)", crtc.r[1]); + screen.Print(0, y++, "R02:$%04x (V.Disp Start)", crtc.r[2]); + screen.Print(0, y++, "R02:$%04x (V.Disp End)", crtc.r[3]); + + screen.Print(0, y++, "R04:$%04x (H.Total)", crtc.r[4]); + screen.Print(0, y++, "R05:$%04x (H.Sync End)", crtc.r[5]); + screen.Print(0, y++, "R06:$%04x (H.Disp Start)", crtc.r[6]); + screen.Print(0, y++, "R07:$%04x (H.Disp End)", crtc.r[7]); + screen.Print(0, y++, "R10:$%04x (Text ScrollX)", crtc.r[10]); screen.Print(0, y++, "R11:$%04x (Text ScrollY)", crtc.r[11]); + val = crtc.r[20]; + screen.Print(0, y, "R20:$%04x (Mode)", val); + screen.Print(29, y, TA::OnOff(val & CRTC::R20_MEM), "MEM"); + static const char * const r20col_str[] = { + "16", + "256", + "undef", + "65536", + }; + screen.Print(33, y, "COL=%s", r20col_str[(val >> 8) & 3]); + screen.Print(43, y, TA::OnOff(val & CRTC::R20_HF), "HF"); + static const char * const r20vd_str[] = { + "256", + "512", + "1024", + "undef", + }; + screen.Print(46, y, "VD=%s", r20vd_str[(val >> 2) & 3]); + static const char * const r20hd_str[] = { + "256", + "512", + "768", + "50MHz", + }; + screen.Print(55, y, "HD=%s", r20hd_str[val & 3]); + y++; + val = crtc.r[21]; screen.Print(0, y, "R21:$%04x (Text Plane)", val); screen.Print(29, y, "MEN=%c SA=%c AP=%%%c%c%c%c CP=%%%c%c%c%c", @@ -224,7 +267,7 @@ CRTCDevice::SetReg(uint32 reg, uint32 da gTVRAM->SetAccessMask(crtc.r[23]); break; default: - putlog(2, "R%02d <- $%04x (未実装)", reg, data); + putlog(2, "R%02d <- $%04x (NOT IMPLEMENTED)", reg, data); break; } } @@ -236,7 +279,7 @@ CRTCDevice::WriteOp(uint32 data) uint16 oldop = crtc.op; crtc.op = data & 0x0b; - putlog(2, "$E80480.W <- $%04x", crtc.op); + putlog(2, "$e80480.W <- $%04x", crtc.op); uint16 change = oldop ^ crtc.op; @@ -244,55 +287,74 @@ CRTCDevice::WriteOp(uint32 data) // テキスト画面ラスターコピー if ((crtc.op & CRTC::OP_RC)) { // 0->1 開始 - StartRasterCopy(); - - // XXX 本当は終わったら 0 にするはず - crtc.op &= ~CRTC::OP_RC; + raster_copy = true; + putlog(3, "ラスターコピー指示"); } else { - // 1->0 停止 - // XXX 今の所一瞬で終わるので… - //StopRasterCopy(); + // 1->0 は停止じゃなくキャンセル? + raster_copy = false; + putlog(3, "ラスターコピーキャンセル"); } } if ((change & 0x03)) { - putlog(0, "動作ポート $%02x->$%02x 未実装", + putlog(0, "動作ポート $%02x <- $%02x (NOT IMPLEMENTED)", oldop & 0x03, crtc.op & 0x03); } } -// テキスト画面のラスターコピー開始 -void -CRTCDevice::StartRasterCopy() -{ - int src = (crtc.r[22] >> 8) * 4; - int dst = (crtc.r[22] & 0xff) * 4; - - gTVRAM->RasterCopy(src, dst); -} - // 水平同期イベント void CRTCDevice::HSyncCallback(Event& ev) { - int hsync = ev.code; - - // GPIP の状態を更新 - gMFP->SetHSync(hsync); + switch (ev.code) { + case 0: // フロントポーチ + // フロントポーチ + ev.time = 2.07_usec; + ev.code++; + break; - // 次のタイミングを計算 - if (hsync) { + case 1: // 水平同期パルス // 水平同期期間 ev.time = 3.45_usec; + ev.code++; + + // GPIP の状態を更新 + gMFP->SetHSync(true); + + // ラスターコピーが指示されていたら実行 + if (raster_copy) { + raster_copy = false; + + int src = (crtc.r[22] >> 8) * 4; + int dst = (crtc.r[22] & 0xff) * 4; + gTVRAM->RasterCopy(src, dst); + + // 所定時間後に完了させる + gScheduler->RestartEvent(raster_event); + } + break; + + case 2: // バックポーチ + 表示期間 + // バックポーチ + Hdisp + ev.time = 4.14_usec + 22.09_usec; ev.code = 0; - } else { - // - ev.time = 22.09_usec + 4.14_usec + 2.07_usec; - ev.code = 1; + + // GPIP の状態を更新 + gMFP->SetHSync(false); + break; } + gScheduler->StartEvent(ev); } +// ラスターコピー完了イベント +void +CRTCDevice::RasterCallback(Event& ev) +{ + // 終わったら動作ポートの RC ビットを %0 にする? + crtc.op &= ~CRTC::OP_RC; +} + // 垂直表示・帰線イベント // ev.code が 1 なら表示期間開始(V-disp)、0 なら帰線期間開始(V-blank)。 void