--- nono/vm/bt454.cpp 2026/04/29 17:04:28 1.1 +++ nono/vm/bt454.cpp 2026/04/29 17:04:49 1.1.1.4 @@ -1,20 +1,23 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #include "bt454.h" #include "bitmap.h" +#include "renderer.h" -// XXX 仕様書には $c100_0000 と書いてあるが、PROM も NetBSD カーネルも -// $c110_0000 にアクセスしているので、とりあえず $c110_0000 にしておく -// というか $10_0000 で折り返して見せることにしておく。 -// 実機調査すること。 +// 仕様書には $c100_0000 と書いてあるが、PROM も NetBSD カーネルも +// $c110_0000 にアクセスしている。実際には 4バイトごとにミラーが見えて +// いるので問題はない。 +// LUNA88K でも1バイトずつ連続配置されている(BusIO_B)、LUNA88K の他の多くの +// デバイスのような BusIO_BFFF 配置でないので注意。 -// 下位ニブルのパターンは不明。とりあえず +// 下位ニブルは 0x0f が読めるようだ #define LOW_NIBBLE (0x0f) -BT454Device *gBT454; +std::unique_ptr gBT454; BT454Device::BT454Device() { @@ -37,155 +40,158 @@ BT454Device::Init() void BT454Device::ResetHard() { - reg.addr = 0; + reg.idx = 0; } /* static */ const char BT454Device::rgbstr[3] = { 'R', 'G', 'B' }; uint64 -BT454Device::Read8(uint32 addr) +BT454Device::Read(uint32 offset) { - uint32 an = (addr - devaddr) & 0x000fffff; uint32 data; - switch (an) { + 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; - default: - putlog(0, "未実装バイト読み込み $%08x", addr); + 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, "未実装 overlay レジスタ読み込み"); data = 0xff; break; + + default: + __unreachable(); } return data; } uint64 -BT454Device::Read16(uint32 addr) -{ - putlog(0, "未実装ワード読み込み $%08x", addr); - return 0xffff; -} - -uint64 -BT454Device::Read32(uint32 addr) +BT454Device::Write(uint32 offset, uint32 data) { - putlog(0, "未実装ロング読み込み $%08x", addr); - return 0xffffffff; -} - -uint64 -BT454Device::Write8(uint32 addr, uint32 data) -{ - uint32 an = (addr - devaddr) & 0x000fffff; - // 書き込みデータのうち有効なのは上位ニブルだけ - switch (an) { + 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; - default: - putlog(0, "未実装バイト書き込み $%08x <- %02x", addr, data); + case 2: + // ab カウンタを 0 にする? データは無視されるようだ + reg.idx = (reg.idx / 3) * 3; + putlog(2, "reset ab"); break; - } - return 0; -} -uint64 -BT454Device::Write16(uint32 addr, uint32 data) -{ - putlog(0, "未実装ワード書き込み $%08x <- %04x", addr, data); - return 0; -} + case 3: + putlog(0, "未実装 overlay レジスタ書き込み <- $%02x", data); + break; -uint64 -BT454Device::Write32(uint32 addr, uint32 data) -{ - putlog(0, "未実装ロング書き込み $%08x <- %08x", addr, data); + default: + __unreachable(); + } return 0; } uint64 -BT454Device::Peek8(uint32 addr) +BT454Device::Peek(uint32 offset) { - uint32 an = (addr - devaddr) & 0x000fffff; + uint8 data; - switch (an) { + 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: + // 未実装 + data = 0xff; + break; default: - return 0xff; + __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]; @@ -194,4 +200,7 @@ BT454Device::MakeHostColor(int addr) // 4bpp なら代入するだけ reg.hostcolor[col * 4 + idx] = reg.color[col * 3 + idx]; } + + // パレット変更が起きたことをレンダラに通知 + gRenderer->Invalidate(); }