--- nono/vm/tvram.cpp 2026/04/29 17:05:25 1.1.1.10 +++ nono/vm/tvram.cpp 2026/04/29 17:05:43 1.1.1.14 @@ -12,7 +12,7 @@ // バイトアクセス時は HLB()、ワードアクセス時は HLW() マクロを使用のこと。 #include "tvram.h" -#include "mpu.h" +#include "textscreen.h" #include "videoctlr.h" // InsideOut p.135 @@ -26,12 +26,8 @@ TVRAMDevice::TVRAMDevice() ClearAlias(); AddAlias("TVRAM"); - uint devlen = 512 * 1024; - // プレーン数は4枚固定 nplane = NPLANE; - - mem.reset(new uint8[devlen]); } // デストラクタ @@ -47,8 +43,14 @@ TVRAMDevice::Init() return false; } - renderer = GetRenderer(); - auto videoctlr = GetVideoCtlrDevice(); + constexpr uint devlen = 512 * 1024; + mem.reset(new(std::nothrow) uint8[devlen]); + if ((bool)mem == false) { + warnx("Cannot allocate %u bytes at %s", devlen, __method__); + return false; + } + + videoctlr = GetVideoCtlrDevice(); // 加工済みパレットを取得 palette = &(videoctlr->GetHostPalette())[0]; @@ -63,115 +65,108 @@ TVRAMDevice::Decoder(uint32 addr) const } busdata -TVRAMDevice::Read8(uint32 addr) +TVRAMDevice::Read(busaddr addr) { busdata data; - uint32 offset = Decoder(addr); - data = mem[HLB(offset)]; + uint32 offset = Decoder(addr.Addr()); + data = *(uint32 *)&mem[offset & ~3U]; data |= wait; + data |= BusData::Size4; return data; } busdata -TVRAMDevice::Read16(uint32 addr) +TVRAMDevice::Write(busaddr addr, uint32 data) { - busdata data; - uint32 offset = Decoder(addr); - data = *(uint16 *)&mem[HLW(offset)]; - data |= wait; - return data; -} - -busdata -TVRAMDevice::Write8(uint32 addr, uint32 data) -{ - uint32 offset = Decoder(addr); - uint8 *ptr; - uint8 mask8; - - // XXX とりあえずね - putlog(3, "Write $%06x.B <- $%02x", addr, data); + uint32 offset = Decoder(addr.Addr()); + uint32 reqsize = addr.GetSize(); + uint32 datasize = std::min(2 - (offset & 1U), reqsize); + data >>= (reqsize - datasize) * 8; + uint32 mask; if (tvram.men) { - if ((addr & 1) == 0) { - mask8 = tvram.mask >> 8; + if (datasize == 1) { + if ((offset & 1U) == 0) { + mask = tvram.mask >> 8; + } else { + mask = tvram.mask & 0xff; + } } else { - mask8 = tvram.mask; + mask = tvram.mask; } } else { - mask8 = 0; + mask = 0; } uint32 poffset = offset & 0x1ffff; - if (tvram.sa) { - // 同時アクセス - for (int plane = 0; plane < 4; plane++) { - if (tvram.ap[plane]) { - ptr = &mem[HLB(0x20000 * plane + poffset)]; - *ptr = (data & ~mask8) | (*ptr & mask8); - } - } + if (datasize == 1) { + Set8(offset, poffset, data, mask); } else { - // 通常アクセス - ptr = &mem[HLB(offset)]; - *ptr = (data & ~mask8) | (*ptr & mask8); + Set16(offset, poffset, data, mask); } SetDirty(poffset); - return wait; + + busdata r = wait; + r |= busdata::Size(datasize); + return r; } busdata -TVRAMDevice::Write16(uint32 addr, uint32 data) +TVRAMDevice::Peek1(uint32 addr) { uint32 offset = Decoder(addr); - uint16 *ptr; - uint16 mask16; - - // XXX とりあえずね - putlog(3, "Write $%06x.W <- $%04x", addr, data); + return mem[HLB(offset)]; +} - if (tvram.men) { - mask16 = tvram.mask; - } else { - mask16 = 0; +bool +TVRAMDevice::Poke1(uint32 addr, uint32 data) +{ + if ((int32)data >= 0) { + uint32 offset = Decoder(addr); + uint32 poffset = offset & 0x1ffff; + mem[HLB(offset)] = data; + // この場合も画面を更新する + SetDirty(poffset); } + return true; +} - uint32 poffset = offset & 0x1ffff; +// マスクと同時アクセスを含むバイト書き込み。 +void +TVRAMDevice::Set8(uint32 offset, uint32 poffset, uint32 data, uint32 mask) +{ if (tvram.sa) { // 同時アクセス for (int plane = 0; plane < 4; plane++) { if (tvram.ap[plane]) { - ptr = (uint16 *)&mem[HLW(0x20000 * plane + poffset)]; - *ptr = (data & ~mask16) | (*ptr & mask16); + uint8 *p = &mem[HLB(0x20000 * plane + poffset)]; + *p = (data & ~mask) | (*p & mask); } } } else { // 通常アクセス - ptr = (uint16 *)&mem[HLW(offset)]; - *ptr = (data & ~mask16) | (*ptr & mask16); + uint8 *p = &mem[HLB(offset)]; + *p = (data & ~mask) | (*p & mask); } - SetDirty(poffset); - return wait; -} - -busdata -TVRAMDevice::Peek8(uint32 addr) -{ - uint32 offset = Decoder(addr); - return mem[HLB(offset)]; } -bool -TVRAMDevice::Poke8(uint32 addr, uint32 data) +// マスクと同時アクセスを含むワード書き込み。 +void +TVRAMDevice::Set16(uint32 offset, uint32 poffset, uint32 data, uint32 mask) { - if ((int32)data >= 0) { - uint32 offset = Decoder(addr); - uint32 poffset = offset & 0x1ffff; - mem[HLB(offset)] = data; - // この場合も画面を更新する - SetDirty(poffset); + if (tvram.sa) { + // 同時アクセス + for (int plane = 0; plane < 4; plane++) { + if (tvram.ap[plane]) { + uint16 *p = (uint16 *)&mem[HLW(0x20000 * plane + poffset)]; + *p = (data & ~mask) | (*p & mask); + } + } + } else { + // 通常アクセス + uint16 *p = (uint16 *)&mem[HLW(offset)]; + *p = (data & ~mask) | (*p & mask); } - return true; } // offset の位置に対応する更新フラグを立てる。 @@ -193,8 +188,8 @@ TVRAMDevice::SetDirty(uint32 offset) // 9 8 7 6 5 4 3 2 1 0 // 更新フラグはラスタ単位 - int y = offset >> 7; - dirty[y] = 1; + uint y = offset >> 7; + dirty.line[y] = true; } // X 方向にはみ出したときに対応する仮想画面の Y 座標を返す。 @@ -217,7 +212,7 @@ void TVRAMDevice::SetScrollY(int y) { yscroll = y; - renderer->Invalidate2(); + Invalidate2(); } // CRTC R21 での同時アクセス設定を反映する。 @@ -260,7 +255,7 @@ TVRAMDevice::SetAccessMask(uint16 data) // ラスターコピーを開始する。 // src_ras, dst_ras はライン番号 (レジスタ設定値を4倍したもの)。 void -TVRAMDevice::RasterCopy(int src_ras, int dst_ras) +TVRAMDevice::RasterCopy(uint src_ras, uint dst_ras) { for (int plane = 0; plane < 4; plane++) { if (tvram.cp[plane]) { @@ -288,7 +283,7 @@ TVRAMDevice::UpdateInfo(TextScreen& scre screen.Puts(0, 0, "X= Y="); for (int i = 0; i < nplane; i++) { - screen.Print(15, i, "(P%d)", i); + screen.Print(15, i, "(P%u)", i); } // カーソルが範囲外ならここまで。 @@ -307,7 +302,7 @@ TVRAMDevice::UpdateInfo(TextScreen& scre uint32 totaloffset = 0x20000 * i + planeoffset; uint8 data = mem[HLB(totaloffset)]; - screen.Print(15, i, "(P%d) $%06x: $%02x (%%", + screen.Print(15, i, "(P%u) $%06x: $%02x (%%", i, baseaddr + totaloffset, data); // ビットパターン