|
|
nono 1.6.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// CRTC-II (HD6445)
//
#include "crtc2.h"
#include "event.h"
#include "lunafb.h"
#include "renderer.h"
#include "scheduler.h"
// コンストラクタ
CRTC2Device::CRTC2Device()
: inherited(OBJ_CRTC2)
{
}
// デストラクタ
CRTC2Device::~CRTC2Device()
{
}
// 初期化
bool
CRTC2Device::Init()
{
lunafb = GetLunafbDevice();
renderer = GetVideoRenderer();
auto evman = GetEventManager();
vdisp_event = evman->Regist(this,
ToEventCallback(&CRTC2Device::VDispCallback),
"CRTC2 V-DISP");
return true;
}
// リセット
void
CRTC2Device::ResetHard(bool poweron)
{
// リセット信号で初期化されるレジスタ (他は維持)
reg[30] = 0;
reg[31] = 0;
reg[32] = 0;
// 未確認
ar = 0;
// XXX 適当
// すぐに垂直帰線期間を開始する
vdisp_state = 1;
vdisp_event->time = 0;
scheduler->RestartEvent(vdisp_event);
}
busdata
CRTC2Device::ReadPort(uint32 offset)
{
busdata data;
switch (offset) {
case 0: // アドレスレジスタ
// アドレスレジスタは書き込み専用
// XXX 何が読めるか
data = 0xff;
putlog(1, "Read write-only register AR");
break;
case 1: // データレジスタ
switch (ar) {
case 12 ... 25: // 読み出し可能
case 28 ... 31:
case 33:
case 36 ... 39:
data = reg[ar];
putlog(2, "R%02u -> $%02x", ar, data.Data());
break;
case 40 ... 63: // 範囲外
// 未使用レジスタの読み出しは $00 (p.17)
data = 0;
putlog(1, "Read unused register R%02u", ar);
break;
default: // 書き込み専用レジスタ
// 読み出しは 0 になる (p.112)
data = 0;
putlog(1, "Read write-only register R%02u", ar);
break;
}
break;
default:
VMPANIC("corrupted offset=%u", offset);
}
// XXX wait?
data |= BusData::Size1;
return data;
}
busdata
CRTC2Device::WritePort(uint32 offset, uint32 data)
{
switch (offset) {
case 0: // アドレスレジスタ
ar = data & 0x3f;
putlog(3, "Address Register <- $%02x", ar);
break;
case 1: // データレジスタ
switch (ar) {
case 16 ... 17: // 読み出し専用レジスタ
case 28:
putlog(1, "Write read-only register R%02u <- $%02x", ar, data);
break;
case 40 ... 63: // 範囲外
putlog(1, "Write unused register R%02u <- $%02x", ar, data);
break;
default: // 書き込み可能レジスタ
reg[ar] = data;
putlog(2, "R%02u <- $%02x", ar, data);
break;
}
break;
default:
VMPANIC("corrupted offset=%u", offset);
break;
}
// XXX wait?
busdata r = BusData::Size1;
return r;
}
busdata
CRTC2Device::PeekPort(uint32 offset)
{
switch (offset) {
case 0: // アドレスレジスタ
return ar;
case 1: // データレジスタ
return reg[ar];
default:
return 0xff;
}
}
bool
CRTC2Device::PokePort(uint32 offset, uint32 data)
{
return false;
}
// 垂直表示・帰線イベント
// vdisp_state が 1 なら表示期間開始(V-disp)、0 なら帰線期間開始(V-blank)。
void
CRTC2Device::VDispCallback(Event *ev)
{
// 今はここで1画面まるごと作成
if (vdisp_state) {
// 更新の必要があれば Render に作画指示。
if (lunafb->Snap()) {
renderer->NotifyRender();
}
}
// 次のタイミングを計算
// XXX まだ CRTC から計算していない
if (vdisp_state) {
// 垂直表示期間
ev->time = 16234.496_usec; // 1024*Ht
vdisp_state = 0;
} else {
// 垂直帰線期間
ev->time = 507.328_usec; // 32*Ht
vdisp_state = 1;
}
scheduler->StartEvent(ev);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.