--- nono/vm/bt454.cpp 2026/04/29 17:04:31 1.1.1.2 +++ nono/vm/bt454.cpp 2026/04/29 17:04:52 1.1.1.5 @@ -1,15 +1,18 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #include "bt454.h" #include "bitmap.h" -#include "mpu.h" +#include "renderer.h" // 仕様書には $c100_0000 と書いてあるが、PROM も NetBSD カーネルも // $c110_0000 にアクセスしている。実際には 4バイトごとにミラーが見えて // いるので問題はない。 +// LUNA88K でも1バイトずつ連続配置されている(BusIO_B)、LUNA88K の他の多くの +// デバイスのような BusIO_BFFF 配置でないので注意。 // 下位ニブルは 0x0f が読めるようだ #define LOW_NIBBLE (0x0f) @@ -37,41 +40,55 @@ BT454Device::Init() void BT454Device::ResetHard() { - reg.addr = 0; + 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 addr) +BT454Device::Read(uint32 offset) { uint32 data; - switch (addr) { + switch (offset) { case 0: // アドレスレジスタ - // 今の(今からアクセスする)パレット番号 - data = reg.addr / 3; + // 今の(今からアクセスする)パレット番号を返す。 + data = reg.idx / 3; data = (data << 4) | LOW_NIBBLE; - putlog(2, "アドレスレジスタ -> $%02x", data); + putlog(2, "Address Register -> $%02x", data); + // アドレスレジスタアクセスで ab カウンタは 0 にリセットされる + reg.idx = (reg.idx / 3) * 3; break; - case 1: // カラーマップレジスタ + case 1: // カラーパレットレジスタ // reg.color[] は上位4ビットが有効なのでそのまま読み出せる。 - data = reg.color[reg.addr]; - data |= LOW_NIBBLE; - putlog(2, "カラーマップ $%x(%c) -> $%02x", - reg.addr / 3, rgbstr[reg.addr % 3], data); + data = reg.color[reg.idx] | LOW_NIBBLE; + putlog(2, "Color Palette $%x(%c) -> $%02x", + reg.idx / 3, rgbstr[reg.idx % 3], data); // アクセスするたびにインクリメントする。 - reg.addr++; - if (reg.addr >= countof(reg.color)) { - reg.addr = 0; + 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, "未実装バイト読み込み $%08x", gMPU->GetPaddr()); + putlog(0, "未実装 overlay レジスタ読み込み"); data = 0xff; break; @@ -83,49 +100,55 @@ BT454Device::Read(uint32 addr) } uint64 -BT454Device::Write(uint32 addr, uint32 data) +BT454Device::Write(uint32 offset, uint32 data) { // 書き込みデータのうち有効なのは上位ニブルだけ - switch (addr) { + switch (offset) { case 0: // アドレスレジスタ - // 今からアクセスするパレット番号 - // data はパレット番号だが reg.addr は配列のインデックスなので 3倍。 - putlog(2, "アドレスレジスタ <- $%02x", data); - reg.addr = (data >> 4) * 3; + // 今からアクセスするパレット番号。 + // アドレスレジスタアクセスで ab カウンタは 0 にリセットされる。 + // data はパレット番号だが reg.idx は配列のインデックスなので 3倍。 + putlog(2, "Address Register <- $%02x", data); + reg.idx = (data >> 4) * 3; break; - case 1: // カラーマップレジスタ + case 1: // カラーパレットレジスタ // reg.color[] は上位4ビットが有効なのでそのまま書き込む。 // 下位4ビットはどうするか。 - reg.color[reg.addr] = (data & 0xf0); + reg.color[reg.idx] = (data & 0xf0); if (loglevel == 1) { // ログレベル1なら RGB が書き込まれた時点で表示。 // 大体はこれくらいの表示で構わないはず。 - if (reg.addr % 3 == 2) { - putlog("カラーマップ $%x = (%x,%x,%x)", - reg.addr / 3, - reg.color[reg.addr - 2] >> 4, - reg.color[reg.addr - 1] >> 4, - reg.color[reg.addr ] >> 4); + 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) { - putlog("カラーマップ $%x(%c) <- $%02x", - reg.addr / 3, rgbstr[reg.addr % 3], data); + putlogn("Color Palette $%x(%c) <- $%02x", + reg.idx / 3, rgbstr[reg.idx % 3], data); } // ホストカラーを計算。 - MakeHostColor(reg.addr); + MakeHostColor(reg.idx); // ホストカラー計算後にインクリメントする。 - reg.addr++; - if (reg.addr >= countof(reg.color)) { - reg.addr = 0; + 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, "未実装バイト書き込み $%08x <- %02x", gMPU->GetPaddr(), data); + putlog(0, "未実装 overlay レジスタ書き込み <- $%02x", data); break; default: @@ -135,37 +158,46 @@ BT454Device::Write(uint32 addr, uint32 d } uint64 -BT454Device::Peek(uint32 addr) +BT454Device::Peek(uint32 offset) { - switch (addr) { + uint8 data; + + switch (offset) { case 0: // アドレスレジスタ - // XXX 下位ニブルは? - return ((reg.addr / 3) << 4) | LOW_NIBBLE; + data = (reg.idx / 3) << 4; + break; - case 1: // カラーマップレジスタ + case 1: // カラーパレットレジスタ // 今読み出そうとしたら読み出せるやつ - return reg.color[reg.addr] | LOW_NIBBLE; + data = reg.color[reg.idx]; + break; case 2: + data = 0; + break; + case 3: // 未実装 - return 0xff; + data = 0xff; + break; default: __unreachable(); } + + return data | LOW_NIBBLE; } -// addr 番目のレジスタ値からホストパレットを作成。 +// idx 番目のレジスタ値からホストパレットを作成。 void -BT454Device::MakeHostColor(int addr) +BT454Device::MakeHostColor(int idx) { - int col = addr / 3; - int idx = addr % 3; + int col = idx / 3; + int ab = idx % 3; if (nplane == 1) { // 1bpp なら R,G,B のうち G の値だけを使用 - if (idx == 1) { + if (ab == 1) { reg.hostcolor[col * 4 + 0] = reg.color[col * 3 + 1]; reg.hostcolor[col * 4 + 1] = reg.color[col * 3 + 1]; reg.hostcolor[col * 4 + 2] = reg.color[col * 3 + 1]; @@ -174,4 +206,7 @@ BT454Device::MakeHostColor(int addr) // 4bpp なら代入するだけ reg.hostcolor[col * 4 + idx] = reg.color[col * 3 + idx]; } + + // パレット変更が起きたことをレンダラに通知 + gRenderer->Invalidate(); }