|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.8 root 7: //
8: // スプライトコントローラ
9: //
10:
1.1 root 11: #include "sprite.h"
1.1.1.12! root 12: #include "event.h"
1.1 root 13:
1.1.1.11 root 14: // InsideOut p.135
15: // 書き込みは VRAM とレジスタで異なる。
16: // 読み込みは VRAM、レジスタとも 17 ウェイト。
17: const busdata vram_wait = busdata::Wait(18 * 40_nsec);
18: const busdata reg_wait = busdata::Wait(20 * 40_nsec);
19: const busdata read_wait = busdata::Wait(17 * 40_nsec);
20:
1.1.1.8 root 21: // コンストラクタ
1.1 root 22: SpriteDevice::SpriteDevice()
1.1.1.10 root 23: : inherited(OBJ_SPRITE)
1.1 root 24: {
1.1.1.2 root 25: mem.reset(new uint8[4 * 8192]);
1.1 root 26: }
27:
1.1.1.8 root 28: // デストラクタ
1.1 root 29: SpriteDevice::~SpriteDevice()
30: {
31: }
32:
1.1.1.8 root 33: // XXX ResetHard() 未調査
1.1.1.6 root 34:
1.1.1.11 root 35: busdata
1.1.1.12! root 36: SpriteDevice::Read(busaddr addr)
1.1 root 37: {
1.1.1.11 root 38: busdata data;
39:
1.1.1.12! root 40: uint32 paddr2 = addr.Addr() & ~1U;
! 41: data = Get16(paddr2);
! 42: putlog(3, "$%06x -> $%04x", paddr2, data.Data());
! 43: data |= read_wait;
! 44: data |= BusData::Size2;
! 45: return data;
! 46: }
! 47:
! 48: busdata
! 49: SpriteDevice::Write(busaddr addr, uint32 data)
! 50: {
! 51: uint32 paddr = addr.Addr();
! 52: uint32 reqsize = addr.GetSize();
! 53: uint32 datasize = std::min(2 - (paddr & 1U), reqsize);
! 54: data >>= (reqsize - datasize) * 8;
! 55:
! 56: uint32 paddr2 = paddr & ~1U;
! 57: if (datasize == 1) {
! 58: putlog(2, "$%06x <- $%02x", paddr, data);
! 59: uint32 tmp = Get16(paddr2);
! 60: if ((paddr & 1U) == 0) {
! 61: data = (data << 8) | (tmp & 0xff);
! 62: } else {
! 63: data = (tmp & 0xff00) | (data & 0xff);
! 64: }
1.1.1.11 root 65: } else {
1.1.1.12! root 66: putlog(2, "$%06x <- $%04x", paddr, data);
1.1 root 67: }
1.1.1.11 root 68:
1.1.1.12! root 69: busdata r = Set16(paddr2, data);
! 70: r |= busdata::Size(datasize);
! 71: return r;
! 72: }
! 73:
! 74: busdata
! 75: SpriteDevice::Peek1(uint32 addr)
! 76: {
! 77: busdata data = Get16(addr & ~1U);
! 78: if ((addr & 1U) == 0) {
! 79: return data >> 8;
! 80: } else {
! 81: return data & 0xff;
! 82: }
1.1.1.11 root 83: return data;
1.1 root 84: }
85:
1.1.1.12! root 86: // 指定のアドレスの16ビット値を返す。
! 87: // addr は偶数アドレスを指定すること。
1.1.1.11 root 88: busdata
1.1.1.12! root 89: SpriteDevice::Get16(uint32 addr) const
1.1 root 90: {
1.1.1.12! root 91: assert((addr & 1U) == 0);
1.1.1.4 root 92:
1.1 root 93: if (addr >= 0xeb8000) {
1.1.1.12! root 94: return *(uint16 *)&mem[addr - 0xeb8000];
! 95: }
! 96: if (addr < 0xeb0400) {
! 97: uint n = (addr - 0xeb0000) / 8;
1.1 root 98: switch (addr % 8) {
99: case 0:
1.1.1.12! root 100: return reg.sprite[n].xpos;
1.1 root 101: case 2:
1.1.1.12! root 102: return reg.sprite[n].ypos;
1.1 root 103: case 4:
1.1.1.12! root 104: return reg.sprite[n].col;
1.1 root 105: case 6:
1.1.1.12! root 106: return reg.sprite[n].prw;
1.1.1.11 root 107: default:
108: __unreachable();
1.1 root 109: }
110: }
111:
1.1.1.12! root 112: switch (addr) {
! 113: case 0xeb0800:
! 114: return reg.bg0x;
! 115: case 0xeb0802:
! 116: return reg.bg0y;
! 117: case 0xeb0804:
! 118: return reg.bg1x;
! 119: case 0xeb0806:
! 120: return reg.bg1y;
! 121: case 0xeb0808:
! 122: return reg.bgctrl;
! 123: case 0xeb080a:
! 124: return reg.htotal;
! 125: case 0xeb080c:
! 126: return reg.hdisp;
! 127: case 0xeb080e:
! 128: return reg.vdisp;
! 129: case 0xeb0810:
! 130: return reg.res;
! 131: default:
! 132: break;
1.1 root 133: }
1.1.1.12! root 134:
! 135: return BusData::BusErr;
1.1 root 136: }
137:
1.1.1.12! root 138: // addr は偶数アドレスを指定すること。
! 139: // ウェイト値もしくは BusData::BusErr を返す。
1.1.1.11 root 140: busdata
1.1.1.12! root 141: SpriteDevice::Set16(uint32 addr, uint32 data)
1.1 root 142: {
1.1.1.12! root 143: assert((addr & 1U) == 0);
! 144:
1.1 root 145: if (addr >= 0xeb8000) {
146: *(uint16 *)&mem[addr - 0xeb8000] = data;
1.1.1.11 root 147: return vram_wait;
1.1 root 148: }
149: if (addr < 0xeb0400) {
1.1.1.12! root 150: uint n = (addr - 0xeb0000) / 8;
1.1 root 151: switch (addr % 8) {
152: case 0:
153: reg.sprite[n].xpos = data & 0x3ff;
154: break;
155: case 2:
156: reg.sprite[n].ypos = data & 0x3ff;
157: break;
158: case 4:
159: reg.sprite[n].col = data & 0xcfff;
160: break;
161: case 6:
162: reg.sprite[n].prw = data & 0x3;
163: break;
1.1.1.12! root 164: default:
! 165: __unreachable();
1.1 root 166: }
1.1.1.11 root 167: return reg_wait;
1.1 root 168: }
169: if (0xeb0800 <= addr && addr < 0xeb0812) {
170: switch (addr) {
171: case 0xeb0800:
172: reg.bg0x = data & 0x3ff;
173: break;
174: case 0xeb0802:
175: reg.bg0y = data & 0x3ff;
176: break;
177: case 0xeb0804:
178: reg.bg1x = data & 0x3ff;
179: break;
180: case 0xeb0806:
181: reg.bg1y = data & 0x3ff;
182: break;
183: case 0xeb0808:
184: reg.bgctrl = data & 0x23f;
185: break;
186: case 0xeb080a:
187: reg.htotal = data & 0xff;
188: break;
189: case 0xeb080c:
190: reg.hdisp = data & 0x3f;
191: break;
192: case 0xeb080e:
193: reg.vdisp = data & 0xff;
194: break;
195: case 0xeb0810:
196: reg.res = data & 0x1f;
197: break;
1.1.1.12! root 198: default:
! 199: __unreachable();
1.1 root 200: }
1.1.1.11 root 201: return reg_wait;
1.1 root 202: }
203:
1.1.1.11 root 204: busdata r = reg_wait; // ?
205: r.SetBusErr();
206: return r;
1.1 root 207: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.