--- nono/vm/crtc2.cpp 2026/04/29 17:04:28 1.1 +++ nono/vm/crtc2.cpp 2026/04/29 17:05:14 1.1.1.9 @@ -1,28 +1,39 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// CRTC-II (HD6445) // #include "crtc2.h" #include "renderer.h" +#include "scheduler.h" +// グローバル参照用 +CRTC2Device *gCRTC2; + +// コンストラクタ CRTC2Device::CRTC2Device() + : inherited("CRTC2") { - logname = "crtc2"; - devname = "CRTC2"; devaddr = 0xd1000000; - vdisp_event.dev = this; - vdisp_event.func = (DeviceCallback_t)&CRTC2Device::VDispCallback; - vdisp_event.name = "CRTC2 V-DISP"; + vdisp_event.func = ToEventCallback(&CRTC2Device::VDispCallback); + vdisp_event.Regist("CRTC2 V-DISP"); } +// デストラクタ CRTC2Device::~CRTC2Device() { + gCRTC2 = NULL; } +// リセット void -CRTC2Device::ResetHard() +CRTC2Device::ResetHard(bool poweron) { // リセット信号で初期化されるレジスタ (他は維持) reg[30] = 0; @@ -36,21 +47,20 @@ CRTC2Device::ResetHard() // すぐに垂直帰線期間を開始する vdisp_event.time = 0; vdisp_event.code = 1; - gScheduler->AddEvent(&vdisp_event); + gScheduler->RestartEvent(vdisp_event); } uint64 -CRTC2Device::Read8(uint32 addr) +CRTC2Device::Read(uint32 offset) { - uint32 an = addr - devaddr; uint32 data; - switch (an) { + switch (offset) { case 0: // アドレスレジスタ // アドレスレジスタは書き込み専用 // XXX 何が読めるか data = 0xff; - putlog(1, "書き込み専用レジスタ AR の読み出し"); + putlog(1, "Read write-only register AR"); break; case 1: // データレジスタ @@ -66,59 +76,41 @@ CRTC2Device::Read8(uint32 addr) case 40 ... 63: // 範囲外 // 未使用レジスタの読み出しは $00 (p.17) data = 0; - putlog(1, "未使用レジスタ読み込み R%02d", ar); + putlog(1, "Read unused register R%02d", ar); break; default: // 書き込み専用レジスタ // 読み出しは 0 になる (p.112) data = 0; - putlog(1, "書き込み専用レジスタ R%02d の読み出し", ar); + putlog(1, "Read write-only register R%02d", ar); break; } break; default: - data = 0xff; - putlog(0, "未実装バイト読み込み $%08x", addr); - break; + __unreachable(); } return data; } uint64 -CRTC2Device::Read16(uint32 addr) -{ - putlog(0, "未実装ワード読み込み $%08x", addr); - return 0xffff; -} - -uint64 -CRTC2Device::Read32(uint32 addr) -{ - putlog(0, "未実装ロング読み込み $%08x", addr); - return 0xffffffff; -} - -uint64 -CRTC2Device::Write8(uint32 addr, uint32 data) +CRTC2Device::Write(uint32 offset, uint32 data) { - uint32 an = addr - devaddr; - switch (an) { + switch (offset) { case 0: // アドレスレジスタ ar = data & 0x3f; - putlog(3, "アドレスレジスタ <- $%02x", ar); + putlog(3, "Address Register <- $%02x", ar); return 0; case 1: // データレジスタ switch (ar) { case 16 ... 17: // 読み出し専用レジスタ case 28: - putlog(1, "読み出し専用レジスタへの書き込み R%02d <- $%02x", - ar, data); + putlog(1, "Write read-only register R%02d <- $%02x", ar, data); break; case 40 ... 63: // 範囲外 - putlog(1, "未使用レジスタ書き込み R%02d <- $%02x", ar, data); + putlog(1, "Write unused register R%02d <- $%02x", ar, data); break; default: // 書き込み可能レジスタ @@ -129,30 +121,14 @@ CRTC2Device::Write8(uint32 addr, uint32 return 0; default: - putlog(3, "未実装バイト書き込み $%08x <- %02x", addr, data); - return 0; + __unreachable(); } } uint64 -CRTC2Device::Write16(uint32 addr, uint32 data) -{ - putlog(0, "未実装ワード書き込み $%08x <- %04x", addr, data); - return 0; -} - -uint64 -CRTC2Device::Write32(uint32 addr, uint32 data) -{ - putlog(0, "未実装ロング書き込み $%08x <- %08x", addr, data); - return 0; -} - -uint64 -CRTC2Device::Peek8(uint32 addr) +CRTC2Device::Peek(uint32 offset) { - uint32 an = addr - devaddr; - switch (an) { + switch (offset) { case 0: // アドレスレジスタ return ar; @@ -160,30 +136,33 @@ CRTC2Device::Peek8(uint32 addr) return reg[ar]; default: - return 0xff; + __unreachable(); } } // 垂直表示・帰線イベント -// arg == 1 なら表示期間開始、arg == 0 なら帰線期間開始。 +// ev.code が 1 なら表示期間開始(V-disp)、0 なら帰線期間開始(V-blank)。 void -CRTC2Device::VDispCallback(int arg) +CRTC2Device::VDispCallback(Event& ev) { + int& vdisp = ev.code; + // 今はここで1画面まるごと作成 - if (arg) { + if (vdisp) { // Render に作画指示 gRenderer->Render(); } // 次のタイミングを計算 // XXX まだ CRTC から計算していない - if (arg) { + if (vdisp) { // 垂直表示期間 - vdisp_event.time = 16234.496_usec; // 1024*Ht + ev.time = 16234.496_usec; // 1024*Ht + ev.code = 0; } else { // 垂直帰線期間 - vdisp_event.time = 507.328_usec; // 32*Ht + ev.time = 507.328_usec; // 32*Ht + ev.code = 1; } - vdisp_event.code = 1 - arg; - gScheduler->AddEvent(&vdisp_event); + gScheduler->StartEvent(ev); }