|
|
nono 0.4.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// BT454
//
// 仕様書には $c100_0000 と書いてあるが、PROM も NetBSD カーネルも
// $c110_0000 にアクセスしている。実際には 4バイトごとにミラーが見えて
// いるので問題はない。
// LUNA88K でも1バイトずつ連続配置されている(BusIO_B)、LUNA88K の他の多くの
// デバイスのような BusIO_BFFF 配置でないので注意。
#include "bt454.h"
#include "planevram.h"
#include "renderer.h"
#include "uimessage.h"
// 下位ニブルは 0x0f が読めるようだ
#define LOW_NIBBLE (0x0f)
// グローバル参照用
BT454Device *gBT454;
// コンストラクタ
BT454Device::BT454Device()
: inherited("BT454")
{
devaddr = 0xc1000000;
}
// デストラクタ
BT454Device::~BT454Device()
{
gBT454 = NULL;
}
bool
BT454Device::Init()
{
nplane = gPlaneVRAM->GetPlaneCount();
assert(nplane >= 0);
return true;
}
// リセット
void
BT454Device::ResetHard(bool poweron)
{
reg.idx = 0;
// XXX BT454 のレジスタの初期値は不明なのでとりあえず全部黒にしておく
memset(reg.color, 0, countof(reg.color));
for (int i = 0; i < countof(reg.color); i++) {
MakeHostColor(i);
}
}
/* static */ const char
BT454Device::rgbstr[3] = { 'R', 'G', 'B' };
uint64
BT454Device::Read(uint32 offset)
{
uint32 data;
switch (offset) {
case 0: // アドレスレジスタ
// 今の(今からアクセスする)パレット番号を返す。
data = reg.idx / 3;
data = (data << 4) | LOW_NIBBLE;
putlog(2, "Address Register -> $%02x", data);
// アドレスレジスタアクセスで ab カウンタは 0 にリセットされる
reg.idx = (reg.idx / 3) * 3;
break;
case 1: // カラーパレットレジスタ
// reg.color[] は上位4ビットが有効なのでそのまま読み出せる。
data = reg.color[reg.idx] | LOW_NIBBLE;
putlog(2, "Color Palette $%x(%c) -> $%02x",
reg.idx / 3, rgbstr[reg.idx % 3], data);
// アクセスするたびにインクリメントする。
reg.idx++;
if (reg.idx >= countof(reg.color)) {
reg.idx = 0;
}
break;
case 2:
// ADDRa,b を 0 にする? D0-D3 は 0 になる??
// データシートが雑でよく分からん…
reg.idx = (reg.idx / 3) * 3;
data = 0x00 | LOW_NIBBLE;
putlog(2, "reset ab");
break;
case 3:
putlog(0, "Read Overlay Register (NOT IMPLEMENTED)");
data = 0xff;
break;
default:
__unreachable();
}
return data;
}
uint64
BT454Device::Write(uint32 offset, uint32 data)
{
// 書き込みデータのうち有効なのは上位ニブルだけ
switch (offset) {
case 0: // アドレスレジスタ
// 今からアクセスするパレット番号。
// アドレスレジスタアクセスで ab カウンタは 0 にリセットされる。
// data はパレット番号だが reg.idx は配列のインデックスなので 3倍。
putlog(2, "Address Register <- $%02x", data);
reg.idx = (data >> 4) * 3;
break;
case 1: // カラーパレットレジスタ
// reg.color[] は上位4ビットが有効なのでそのまま書き込む。
// 下位4ビットはどうするか。
reg.color[reg.idx] = (data & 0xf0);
if (loglevel == 1) {
// ログレベル1なら RGB が書き込まれた時点で表示。
// 大体はこれくらいの表示で構わないはず。
if (reg.idx % 3 == 2) {
putlogn("Color Palette $%x = (%x,%x,%x)",
reg.idx / 3,
reg.color[reg.idx - 2] >> 4,
reg.color[reg.idx - 1] >> 4,
reg.color[reg.idx ] >> 4);
}
} else if (loglevel >= 2) {
putlogn("Color Palette $%x(%c) <- $%02x",
reg.idx / 3, rgbstr[reg.idx % 3], data);
}
// ホストカラーを計算。
MakeHostColor(reg.idx);
// ホストカラー計算後にインクリメントする。
reg.idx++;
if (reg.idx >= countof(reg.color)) {
reg.idx = 0;
}
break;
case 2:
// ab カウンタを 0 にする? データは無視されるようだ
reg.idx = (reg.idx / 3) * 3;
putlog(2, "reset ab");
break;
case 3:
putlog(0, "Overlay Register <- $%02x (NOT IMPLEMENTED)", data);
break;
default:
__unreachable();
}
return 0;
}
uint64
BT454Device::Peek(uint32 offset)
{
uint8 data;
switch (offset) {
case 0: // アドレスレジスタ
data = (reg.idx / 3) << 4;
break;
case 1: // カラーパレットレジスタ
// 今読み出そうとしたら読み出せるやつ
data = reg.color[reg.idx];
break;
case 2:
data = 0;
break;
case 3:
// 未実装
data = 0xff;
break;
default:
__unreachable();
}
return data | LOW_NIBBLE;
}
// idx 番目のレジスタ値からホストパレットを作成。
void
BT454Device::MakeHostColor(int idx)
{
int col = idx / 3;
int ab = idx % 3;
if (nplane == 1) {
// 1bpp なら R,G,B のうち G の値だけを使用
if (ab == 1) {
reg.hostcolor[col].r = reg.color[col * 3 + 1];
reg.hostcolor[col].g = reg.color[col * 3 + 1];
reg.hostcolor[col].b = reg.color[col * 3 + 1];
}
} else {
// 4bpp なら代入するだけ
switch (ab) {
case 0:
reg.hostcolor[col].r = reg.color[col * 3 + ab];
break;
case 1:
reg.hostcolor[col].g = reg.color[col * 3 + ab];
break;
case 2:
reg.hostcolor[col].b = reg.color[col * 3 + ab];
break;
default:
__unreachable();
}
}
// パレット変更が起きたことをレンダラに通知
gRenderer->Invalidate2();
// UI にも通知
UIMessage::Post(UIMessage::PALETTE);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.