--- nono/vm/sprite.cpp 2026/04/29 17:04:28 1.1 +++ nono/vm/sprite.cpp 2026/04/29 17:05:25 1.1.1.11 @@ -1,97 +1,137 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// スプライトコントローラ // #include "sprite.h" -#include +#include "mpu.h" +// InsideOut p.135 +// 書き込みは VRAM とレジスタで異なる。 +// 読み込みは VRAM、レジスタとも 17 ウェイト。 +const busdata vram_wait = busdata::Wait(18 * 40_nsec); +const busdata reg_wait = busdata::Wait(20 * 40_nsec); +const busdata read_wait = busdata::Wait(17 * 40_nsec); + +// コンストラクタ SpriteDevice::SpriteDevice() + : inherited(OBJ_SPRITE) { - logname = "sprite"; - devname = "Sprite"; - devaddr = baseaddr; - devlen = 0x010000; - - mem = (uint8 *)malloc(4 * 8192); + mem.reset(new uint8[4 * 8192]); } +// デストラクタ SpriteDevice::~SpriteDevice() { - free(mem); } -uint64 +// XXX ResetHard() 未調査 + +busdata SpriteDevice::Read8(uint32 addr) { + busdata data; + if (addr >= 0xeb8000) { - return mem[HB(addr - 0xeb8000)]; + data = mem[HB(addr - 0xeb8000)]; + } else { + VMPANIC("not impl"); } - PANIC("not impl"); + + data |= read_wait; + return data; } -uint64 +busdata SpriteDevice::Read16(uint32 addr) { + busdata data; + if (addr >= 0xeb8000) { - return *(uint16 *)&mem[addr - 0xeb8000]; - } - if (addr < 0xeb0400) { + data = *(uint16 *)&mem[addr - 0xeb8000]; + + } else if (addr < 0xeb0400) { int n = (addr - 0xeb0000) / 8; switch (addr % 8) { case 0: - return reg.sprite[n].xpos; + data = reg.sprite[n].xpos; + break; case 2: - return reg.sprite[n].ypos; + data = reg.sprite[n].ypos; + break; case 4: - return reg.sprite[n].col; + data = reg.sprite[n].col; + break; case 6: - return reg.sprite[n].prw; + data = reg.sprite[n].prw; + break; + default: + __unreachable(); } - } - if (0xeb0800 <= addr && addr < 0xeb0812) { + } else if (0xeb0800 <= addr && addr < 0xeb0812) { switch (addr) { case 0xeb0800: - return reg.bg0x; + data = reg.bg0x; + break; case 0xeb0802: - return reg.bg0y; + data = reg.bg0y; + break; case 0xeb0804: - return reg.bg1x; + data = reg.bg1x; + break; case 0xeb0806: - return reg.bg1y; + data = reg.bg1y; + break; case 0xeb0808: - return reg.bgctrl; + data = reg.bgctrl; + break; case 0xeb080a: - return reg.htotal; + data = reg.htotal; + break; case 0xeb080c: - return reg.hdisp; + data = reg.hdisp; + break; case 0xeb080e: - return reg.vdisp; + data = reg.vdisp; + break; case 0xeb0810: - return reg.res; + data = reg.res; + break; + default: + __unreachable(); } + } else { + data.SetBusErr(); } - return (uint64)-1; + data |= read_wait; + return data; } -uint64 +busdata SpriteDevice::Write8(uint32 addr, uint32 data) { if (addr >= 0xeb8000) { mem[HB(addr - 0xeb8000)] = data; - return 0; + return vram_wait; + } else { + VMPANIC("not impl"); + return reg_wait; } - PANIC("not impl"); } -uint64 +busdata SpriteDevice::Write16(uint32 addr, uint32 data) { - putlog(2, "Write16 $%06x <- $%04x", addr, data); + putlog(2, "$%06x <- $%04x", addr, data); if (addr >= 0xeb8000) { *(uint16 *)&mem[addr - 0xeb8000] = data; - return 0; + return vram_wait; } if (addr < 0xeb0400) { int n = (addr - 0xeb0000) / 8; @@ -109,7 +149,7 @@ SpriteDevice::Write16(uint32 addr, uint3 reg.sprite[n].prw = data & 0x3; break; } - return 0; + return reg_wait; } if (0xeb0800 <= addr && addr < 0xeb0812) { switch (addr) { @@ -141,13 +181,15 @@ SpriteDevice::Write16(uint32 addr, uint3 reg.res = data & 0x1f; break; } - return 0; + return reg_wait; } - return (uint64)-1; + busdata r = reg_wait; // ? + r.SetBusErr(); + return r; } -uint64 +busdata SpriteDevice::Peek8(uint32 addr) { if (addr >= 0xeb8000) { @@ -189,5 +231,5 @@ SpriteDevice::Peek8(uint32 addr) } } - return (uint64)-1; + return busdata::BusErr; }