|
|
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: {
25: }
26:
1.1.1.8 root 27: // デストラクタ
1.1 root 28: SpriteDevice::~SpriteDevice()
29: {
30: }
31:
1.1.1.13 root 32: // 初期化
33: bool
34: SpriteDevice::Init()
35: {
1.1.1.14! root 36: constexpr size_t devlen = 4 * 8192;
1.1.1.13 root 37: mem.reset(new(std::nothrow) uint8[devlen]);
38: if ((bool)mem == false) {
1.1.1.14! root 39: warnx("Could not allocate %zu bytes at %s", devlen, __method__);
1.1.1.13 root 40: return false;
41: }
42:
43: return true;
44: }
45:
1.1.1.8 root 46: // XXX ResetHard() 未調査
1.1.1.6 root 47:
1.1.1.11 root 48: busdata
1.1.1.12 root 49: SpriteDevice::Read(busaddr addr)
1.1 root 50: {
1.1.1.11 root 51: busdata data;
52:
1.1.1.12 root 53: uint32 paddr2 = addr.Addr() & ~1U;
54: data = Get16(paddr2);
55: putlog(3, "$%06x -> $%04x", paddr2, data.Data());
56: data |= read_wait;
57: data |= BusData::Size2;
58: return data;
59: }
60:
61: busdata
62: SpriteDevice::Write(busaddr addr, uint32 data)
63: {
64: uint32 paddr = addr.Addr();
65: uint32 reqsize = addr.GetSize();
66: uint32 datasize = std::min(2 - (paddr & 1U), reqsize);
67: data >>= (reqsize - datasize) * 8;
68:
69: uint32 paddr2 = paddr & ~1U;
70: if (datasize == 1) {
71: putlog(2, "$%06x <- $%02x", paddr, data);
72: uint32 tmp = Get16(paddr2);
73: if ((paddr & 1U) == 0) {
74: data = (data << 8) | (tmp & 0xff);
75: } else {
76: data = (tmp & 0xff00) | (data & 0xff);
77: }
1.1.1.11 root 78: } else {
1.1.1.12 root 79: putlog(2, "$%06x <- $%04x", paddr, data);
1.1 root 80: }
1.1.1.11 root 81:
1.1.1.12 root 82: busdata r = Set16(paddr2, data);
83: r |= busdata::Size(datasize);
84: return r;
85: }
86:
87: busdata
88: SpriteDevice::Peek1(uint32 addr)
89: {
90: busdata data = Get16(addr & ~1U);
91: if ((addr & 1U) == 0) {
92: return data >> 8;
93: } else {
94: return data & 0xff;
95: }
1.1.1.11 root 96: return data;
1.1 root 97: }
98:
1.1.1.12 root 99: // 指定のアドレスの16ビット値を返す。
100: // addr は偶数アドレスを指定すること。
1.1.1.11 root 101: busdata
1.1.1.12 root 102: SpriteDevice::Get16(uint32 addr) const
1.1 root 103: {
1.1.1.12 root 104: assert((addr & 1U) == 0);
1.1.1.4 root 105:
1.1 root 106: if (addr >= 0xeb8000) {
1.1.1.12 root 107: return *(uint16 *)&mem[addr - 0xeb8000];
108: }
109: if (addr < 0xeb0400) {
110: uint n = (addr - 0xeb0000) / 8;
1.1 root 111: switch (addr % 8) {
112: case 0:
1.1.1.12 root 113: return reg.sprite[n].xpos;
1.1 root 114: case 2:
1.1.1.12 root 115: return reg.sprite[n].ypos;
1.1 root 116: case 4:
1.1.1.12 root 117: return reg.sprite[n].col;
1.1 root 118: case 6:
1.1.1.12 root 119: return reg.sprite[n].prw;
1.1.1.11 root 120: default:
121: __unreachable();
1.1 root 122: }
123: }
124:
1.1.1.12 root 125: switch (addr) {
126: case 0xeb0800:
127: return reg.bg0x;
128: case 0xeb0802:
129: return reg.bg0y;
130: case 0xeb0804:
131: return reg.bg1x;
132: case 0xeb0806:
133: return reg.bg1y;
134: case 0xeb0808:
135: return reg.bgctrl;
136: case 0xeb080a:
137: return reg.htotal;
138: case 0xeb080c:
139: return reg.hdisp;
140: case 0xeb080e:
141: return reg.vdisp;
142: case 0xeb0810:
143: return reg.res;
144: default:
145: break;
1.1 root 146: }
1.1.1.12 root 147:
148: return BusData::BusErr;
1.1 root 149: }
150:
1.1.1.12 root 151: // addr は偶数アドレスを指定すること。
152: // ウェイト値もしくは BusData::BusErr を返す。
1.1.1.11 root 153: busdata
1.1.1.12 root 154: SpriteDevice::Set16(uint32 addr, uint32 data)
1.1 root 155: {
1.1.1.12 root 156: assert((addr & 1U) == 0);
157:
1.1 root 158: if (addr >= 0xeb8000) {
159: *(uint16 *)&mem[addr - 0xeb8000] = data;
1.1.1.11 root 160: return vram_wait;
1.1 root 161: }
162: if (addr < 0xeb0400) {
1.1.1.12 root 163: uint n = (addr - 0xeb0000) / 8;
1.1 root 164: switch (addr % 8) {
165: case 0:
166: reg.sprite[n].xpos = data & 0x3ff;
167: break;
168: case 2:
169: reg.sprite[n].ypos = data & 0x3ff;
170: break;
171: case 4:
172: reg.sprite[n].col = data & 0xcfff;
173: break;
174: case 6:
175: reg.sprite[n].prw = data & 0x3;
176: break;
1.1.1.12 root 177: default:
178: __unreachable();
1.1 root 179: }
1.1.1.11 root 180: return reg_wait;
1.1 root 181: }
182: if (0xeb0800 <= addr && addr < 0xeb0812) {
183: switch (addr) {
184: case 0xeb0800:
185: reg.bg0x = data & 0x3ff;
186: break;
187: case 0xeb0802:
188: reg.bg0y = data & 0x3ff;
189: break;
190: case 0xeb0804:
191: reg.bg1x = data & 0x3ff;
192: break;
193: case 0xeb0806:
194: reg.bg1y = data & 0x3ff;
195: break;
196: case 0xeb0808:
197: reg.bgctrl = data & 0x23f;
198: break;
199: case 0xeb080a:
200: reg.htotal = data & 0xff;
201: break;
202: case 0xeb080c:
203: reg.hdisp = data & 0x3f;
204: break;
205: case 0xeb080e:
206: reg.vdisp = data & 0xff;
207: break;
208: case 0xeb0810:
209: reg.res = data & 0x1f;
210: break;
1.1.1.12 root 211: default:
212: __unreachable();
1.1 root 213: }
1.1.1.11 root 214: return reg_wait;
1.1 root 215: }
216:
1.1.1.11 root 217: busdata r = reg_wait; // ?
218: r.SetBusErr();
219: return r;
1.1 root 220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.