--- nono/vm/tvram.cpp 2026/04/29 17:05:10 1.1.1.7 +++ nono/vm/tvram.cpp 2026/04/29 17:05:14 1.1.1.8 @@ -84,7 +84,7 @@ TVRAMDevice::Write8(uint32 addr, uint32 gMPU->AddCycle(9); // Inside/Out p.135 // XXX とりあえずね - putlog(3, "Write $%06x <- $%02x", addr, data); + putlog(3, "Write $%06x.B <- $%02x", addr, data); if (tvram.men) { if ((addr & 1) == 0) { @@ -124,7 +124,7 @@ TVRAMDevice::Write16(uint32 addr, uint32 gMPU->AddCycle(9); // Inside/Out p.135 // XXX とりあえずね - putlog(3, "Write $%06x <- $%04x", addr, data); + putlog(3, "Write $%06x.W <- $%04x", addr, data); if (tvram.men) { mask16 = tvram.mask; @@ -250,25 +250,36 @@ TVRAMDevice::SetAccessMask(uint16 data) } // ラスターコピーを開始する。 -// XXX 今の所コピー中という期間は存在せず一瞬で終わる // src_ras, dst_ras はライン番号 (レジスタ設定値を4倍したもの)。 void TVRAMDevice::RasterCopy(int src_ras, int dst_ras) { for (int plane = 0; plane < 4; plane++) { if (tvram.cp[plane]) { - uint8 *src = &mem[HLW(0x20000 * plane + src_ras * 128)]; - uint8 *dst = &mem[HLW(0x20000 * plane + dst_ras * 128)]; + uint8 *src = &mem[0x20000 * plane + src_ras * 128]; + uint8 *dst = &mem[0x20000 * plane + dst_ras * 128]; memcpy(dst, src, 128 * 4); } } - // dst からの4ラインを全部 dirty にする - for (int i = 0; i < 4; i++) { - int y = dst_ras + i; - // PERF_HIT の更新もあるので律儀に全ロングバイト分ループする - for (int x = 0; x < 128 / sizeof(uint32); x++) { - SetDirty(y * 128 + x * 4); + // dst からの4ラインを全部 dirty にする。 +#if !defined(PERF_HIT) + // dirty は、1ブロックが縦 16dot 収容しているので、4の倍数から始まる + // 4ラインは必ず1ブロックに収まる。横方向は1ブロックにつき 128dot 収容して + // いるので全部で8ブロック。 + // よって dirty を立てるだけなら 8回の呼び出しで済む。 + for (int x = 0; x < 8; x++) { + SetDirty(dst_ras * 128 + (x << 4)); + } +#else + // PERF_HIT の更新を行う場合は律儀に全プレーンの全ロングワード分ループする + for (int plane = 0; plane < 4; plane++) { + for (int i = 0; i < 4; i++) { + int y = dst_ras + i; + for (int x = 0; x < 128 / sizeof(uint32); x++) { + SetDirty(0x20000 * plane + y * 128 + x * sizeof(uint32)); + } } } +#endif }