|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // X68030 のメイン空間 ($000000-$FFFFFF) 担当
9: //
10:
11: #include "x68kio.h"
12: #include "adpcm.h"
13: #include "areaset.h"
14: #include "busio.h"
15: #include "config.h"
16: #include "crtc.h"
17: #include "dmac.h"
18: #include "fdc.h"
19: #include "gvram.h"
20: #include "mainram.h"
21: #include "mfp.h"
22: #include "opm.h"
23: #include "pedec.h"
24: #include "pio.h"
25: #include "pluto.h"
26: #include "printer.h"
27: #include "romemu_x68k.h"
28: #include "romimg_x68k.h"
29: #include "rp5c15.h"
30: #include "scc.h"
31: #include "spc.h"
32: #include "sprite.h"
33: #include "sram.h"
34: #include "sysport.h"
35: #include "tvram.h"
36: #include "videoctlr.h"
37: #include "vm.h"
38:
39: // コンストラクタ
40: X68kIODevice::X68kIODevice()
41: : inherited(OBJ_X68KIO)
42: {
43: #define ADD_DEVICE(NAME, ADDR, LEN) \
44: AddDevice(__CONCAT(p,NAME).get(), ADDR, LEN)
45:
46: #define N(NAME, NEW_CTOR, ADDR, LEN) do { \
47: NEWDV(NAME, NEW_CTOR); \
48: ADD_DEVICE(NAME, ADDR, LEN); \
49: } while (0)
50:
51: // デバイスクラス作成。
52: // 初期化順の制約がない限りアドレス順。
53: // 開始アドレス 長さ
54: N(GVRAM, new GVRAMDevice(), 0xc00000,0x200000);
55: N(PlaneVRAM, new TVRAMDevice(), 0xe00000, 0x80000);
56: N(CRTC, new BusIO_W<CRTCDevice>(), 0xe80000, 0x2000);
57: N(VideoCtlr, new VideoCtlrDevice(), 0xe82000, 0x2000);
58: N(DMAC, new DMACDevice(), 0xe84000, 0x2000);
59: N(AreaSet, new AreaSetDevice(), 0xe86000, 0x2000);
60: N(MFP, new BusIO_EB<MFPDevice>(), 0xe88000, 0x2000);
61: N(RTC, new BusIO_EB<RP5C15Device>(), 0xe8a000, 0x2000);
62: N(Printer, new PrinterDevice(), 0xe8c000, 0x2000);
63: N(Sysport,new BusIO_FB<SysportDevice>(), 0xe8e000, 0x2000);
64: N(OPM, new BusIO_EB<OPMDevice>(), 0xe90000, 0x2000);
65: N(ADPCM, new BusIO_EB<ADPCMDevice>(), 0xe92000, 0x2000);
66: N(FDC, new BusIO_EB<FDCDevice>(), 0xe94000, 0x2000);
67: N(SPC, new BusIO_X68kSPC<SPCDevice>(), 0xe96000, 0x2000);
68: N(SCC, new BusIO_EB<SCCDevice>(), 0xe98000, 0x2000);
69: N(PPI, new BusIO_EB<PPIDevice>(), 0xe9a000, 0x2000);
70: N(PEDEC, new BusIO_EB<PEDECDevice>(), 0xe9c000, 0x2000);
71: N(Pluto, new PlutoDevice(), 0xeac000, 0x2000);
72: N(Sprite, new SpriteDevice(), 0xeb0000, 0x10000);
73: N(SRAM, new SRAMDevice(), 0xed0000, 0x4000);
74: N(CGROM, new CGROMDevice(), 0xf00000, 0xc0000);
75: if (gConfig->Find("iplrom2-image").AsString().empty()) {
76: NEWDV(IPLROM2, new ROM30EmuDevice());
77: } else {
78: NEWDV(IPLROM2, new IPLROM2Device());
79: }
80: ADD_DEVICE(IPLROM2, 0xfc0000, 0x20000);
81: N(IPLROM1, new IPLROM1Device(), 0xfe0000, 0x20000);
82: }
83:
84: // デストラクタ
85: X68kIODevice::~X68kIODevice()
86: {
87: }
88:
89: // 初期化
90: bool
91: X68kIODevice::Init()
92: {
93: if (inherited::Init() == false) {
94: return false;
95: }
96:
97: auto buserr = GetBusErrDevice();
98: auto mainram = GetMainRAMDevice();
99:
100: // RAM のみ RamDevice::Init() で ram_size が決定してから行う。
101: for (int i = 0; i < mainram->GetSize() / 8192; i++) {
102: table[i] = mainram;
103: }
104:
105: // 必要なデバイスは全部埋めたので、この時点で nullptr なエントリを
106: // BusErr に差し替える。
107: for (auto&& d : table) {
108: if (d == nullptr) {
109: d = buserr;
110: }
111: }
112:
113: // デバッグ表示
114: if (0) {
115: for (int i = 1536; i < table.size(); i++) {
116: printf("[%3d] $%06x ", i, i * 8192);
117: assert(table[i]);
118: printf("%s\n", table[i]->GetName().c_str());
119: }
120: }
121:
122: return true;
123: }
124:
125: // デバイステーブルに dev を追加する。
126: void
127: X68kIODevice::AddDevice(IODevice *dev, uint devaddr, uint devlen)
128: {
129: int idx = devaddr / 8192;
130: for (int i = idx; i < idx + (devlen + 8191) / 8192; i++) {
131: // 重複するケースは未対応
132: assertmsg(table[i] == nullptr, "X68kIODevice.AddDevice '%s'",
133: table[i]->GetName().c_str());
134:
135: table[i] = dev;
136: }
137: }
138:
139: // アドレス addr に対応する IODevice* を返す。
140: // addr は事前に 24bit マスクしてあるもの。
141: inline IODevice *
142: X68kIODevice::SearchDevice(uint32 addr) const
143: {
144: uint idx = addr / 8192;
145: __assume(idx < 2048);
146: return table[idx];
147: }
148:
149: uint64
150: X68kIODevice::Read8(uint32 addr)
151: {
152: addr &= 0x00ffffff;
153: IODevice *d = SearchDevice(addr);
154: return d->Read8(addr);
155: }
156:
157: uint64
158: X68kIODevice::Read16(uint32 addr)
159: {
160: addr &= 0x00ffffff;
161: IODevice *d = SearchDevice(addr);
162: return d->Read16(addr);
163: }
164:
165: uint64
166: X68kIODevice::Read32(uint32 addr)
167: {
168: addr &= 0x00ffffff;
169: IODevice *d = SearchDevice(addr);
170: return d->Read32(addr);
171: }
172:
173: uint64
174: X68kIODevice::Write8(uint32 addr, uint32 data)
175: {
176: addr &= 0x00ffffff;
177: IODevice *d = SearchDevice(addr);
178: return d->Write8(addr, data);
179: }
180:
181: uint64
182: X68kIODevice::Write16(uint32 addr, uint32 data)
183: {
184: addr &= 0x00ffffff;
185: IODevice *d = SearchDevice(addr);
186: return d->Write16(addr, data);
187: }
188:
189: uint64
190: X68kIODevice::Write32(uint32 addr, uint32 data)
191: {
192: addr &= 0x00ffffff;
193: IODevice *d = SearchDevice(addr);
194: return d->Write32(addr, data);
195: }
196:
197: uint64
198: X68kIODevice::Peek8(uint32 addr)
199: {
200: addr &= 0x00ffffff;
201: IODevice *d = SearchDevice(addr);
202: return d->Peek8(addr);
203: }
204:
205: // このアドレスを担当する次段の IODevice を返す (IOContainerDevice 用)
206: IODevice *
207: X68kIODevice::GetDevice(uint32 addr) const
208: {
209: return SearchDevice(addr & 0x00ffffff);
210: }
211:
212: // ブートページを切り替える。
213: // (VM_X68030::SwitchBootPage() の下請け)
214: void
215: X68kIODevice::SwitchBootPage(bool isrom)
216: {
217: IODevice *ram;
218: IODevice *rom;
219:
220: if (isrom) {
221: // 0x000000 からの 64KB ( 8エントリ)、
222: // 0xfe0000 からの 128KB (16エントリ) のどちらも IPLROM0 が担当する。
223: ram = GetIPLROM0Device();
224: rom = GetIPLROM0Device();
225: } else {
226: // 0x000000 からの 64KB ( 8エントリ) に RAM を見せる。
227: // 0xfe0000 からの 128KB (16エントリ) に IPLROM1 を見せる。
228: ram = GetMainRAMDevice();
229: rom = GetIPLROM1Device();
230: }
231:
232: for (int i = 0; i < 8; i++) {
233: table[i] = ram;
234: }
235: for (int i = 0; i < 16; i++) {
236: table[table.size() - 16 + i] = rom;
237: }
238: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.