|
|
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"
1.1.1.2 ! root 20: #include "mainbus.h"
1.1 root 21: #include "mainram.h"
22: #include "mfp.h"
1.1.1.2 ! root 23: #include "nereid.h"
1.1 root 24: #include "opm.h"
25: #include "pedec.h"
26: #include "pio.h"
27: #include "pluto.h"
28: #include "printer.h"
29: #include "romemu_x68k.h"
30: #include "romimg_x68k.h"
31: #include "rp5c15.h"
32: #include "scc.h"
33: #include "spc.h"
34: #include "sprite.h"
35: #include "sram.h"
36: #include "sysport.h"
37: #include "tvram.h"
38: #include "videoctlr.h"
39: #include "vm.h"
40:
41: // コンストラクタ
42: X68kIODevice::X68kIODevice()
43: : inherited(OBJ_X68KIO)
44: {
1.1.1.2 ! root 45: monitor.func = ToMonitorCallback(&X68kIODevice::MonitorUpdate);
! 46: monitor.SetSize(73, 1 + 32);
! 47: monitor.SetMaxHeight(1 + 256);
! 48: monitor.Regist(ID_SUBWIN_X68KIO);
! 49:
1.1 root 50: #define ADD_DEVICE(NAME, ADDR, LEN) \
51: AddDevice(__CONCAT(p,NAME).get(), ADDR, LEN)
52:
53: #define N(NAME, NEW_CTOR, ADDR, LEN) do { \
54: NEWDV(NAME, NEW_CTOR); \
55: ADD_DEVICE(NAME, ADDR, LEN); \
56: } while (0)
57:
58: // デバイスクラス作成。
59: // 初期化順の制約がない限りアドレス順。
60: // 開始アドレス 長さ
61: N(GVRAM, new GVRAMDevice(), 0xc00000,0x200000);
62: N(PlaneVRAM, new TVRAMDevice(), 0xe00000, 0x80000);
63: N(CRTC, new BusIO_W<CRTCDevice>(), 0xe80000, 0x2000);
64: N(VideoCtlr, new VideoCtlrDevice(), 0xe82000, 0x2000);
65: N(DMAC, new DMACDevice(), 0xe84000, 0x2000);
66: N(AreaSet, new AreaSetDevice(), 0xe86000, 0x2000);
67: N(MFP, new BusIO_EB<MFPDevice>(), 0xe88000, 0x2000);
68: N(RTC, new BusIO_EB<RP5C15Device>(), 0xe8a000, 0x2000);
69: N(Printer, new PrinterDevice(), 0xe8c000, 0x2000);
70: N(Sysport,new BusIO_FB<SysportDevice>(), 0xe8e000, 0x2000);
71: N(OPM, new BusIO_EB<OPMDevice>(), 0xe90000, 0x2000);
72: N(ADPCM, new BusIO_EB<ADPCMDevice>(), 0xe92000, 0x2000);
73: N(FDC, new BusIO_EB<FDCDevice>(), 0xe94000, 0x2000);
74: N(SPC, new BusIO_X68kSPC<SPCDevice>(), 0xe96000, 0x2000);
75: N(SCC, new BusIO_EB<SCCDevice>(), 0xe98000, 0x2000);
76: N(PPI, new BusIO_EB<PPIDevice>(), 0xe9a000, 0x2000);
77: N(PEDEC, new BusIO_EB<PEDECDevice>(), 0xe9c000, 0x2000);
78: N(Pluto, new PlutoDevice(), 0xeac000, 0x2000);
79: N(Sprite, new SpriteDevice(), 0xeb0000, 0x10000);
1.1.1.2 ! root 80: // Nereid はこの時点ではデバイスの追加のみ。Init() 参照。
! 81: NEWDV(Nereid, new NereidDevice()); // 0xece000, 0x2000
1.1 root 82: N(SRAM, new SRAMDevice(), 0xed0000, 0x4000);
83: N(CGROM, new CGROMDevice(), 0xf00000, 0xc0000);
84: if (gConfig->Find("iplrom2-image").AsString().empty()) {
85: NEWDV(IPLROM2, new ROM30EmuDevice());
86: } else {
87: NEWDV(IPLROM2, new IPLROM2Device());
88: }
89: ADD_DEVICE(IPLROM2, 0xfc0000, 0x20000);
90: N(IPLROM1, new IPLROM1Device(), 0xfe0000, 0x20000);
91: }
92:
93: // デストラクタ
94: X68kIODevice::~X68kIODevice()
95: {
96: }
97:
98: // 初期化
99: bool
100: X68kIODevice::Init()
101: {
102: if (inherited::Init() == false) {
103: return false;
104: }
105:
106: auto buserr = GetBusErrDevice();
107: auto mainram = GetMainRAMDevice();
108:
1.1.1.2 ! root 109: // RAM は RamDevice::Init() で ram_size が決定してから行う。
1.1 root 110: for (int i = 0; i < mainram->GetSize() / 8192; i++) {
111: table[i] = mainram;
112: }
113:
1.1.1.2 ! root 114: // Nereid は1枚でもボードがある時だけメモリ空間に追加する。
! 115: // Nereid が1枚もない場合でもモニタやログ(この場合のログは起動時にどれが
! 116: // 有効とか無効と判断したことを表示するもの)のためデバイス自体は常に存在。
! 117: auto nereid = GetNereidDevice();
! 118: if (nereid->IsInstalled()) {
! 119: ADD_DEVICE(Nereid, 0xece000, 0x2000);
! 120: }
! 121:
1.1 root 122: // 必要なデバイスは全部埋めたので、この時点で nullptr なエントリを
123: // BusErr に差し替える。
124: for (auto&& d : table) {
125: if (d == nullptr) {
126: d = buserr;
127: }
128: }
129:
130: // デバッグ表示
131: if (0) {
132: for (int i = 1536; i < table.size(); i++) {
133: printf("[%3d] $%06x ", i, i * 8192);
134: assert(table[i]);
135: printf("%s\n", table[i]->GetName().c_str());
136: }
137: }
138:
139: return true;
140: }
141:
142: // デバイステーブルに dev を追加する。
143: void
144: X68kIODevice::AddDevice(IODevice *dev, uint devaddr, uint devlen)
145: {
146: int idx = devaddr / 8192;
147: for (int i = idx; i < idx + (devlen + 8191) / 8192; i++) {
148: // 重複するケースは未対応
149: assertmsg(table[i] == nullptr, "X68kIODevice.AddDevice '%s'",
150: table[i]->GetName().c_str());
151:
152: table[i] = dev;
153: }
154: }
155:
156: // アドレス addr に対応する IODevice* を返す。
157: // addr は事前に 24bit マスクしてあるもの。
158: inline IODevice *
159: X68kIODevice::SearchDevice(uint32 addr) const
160: {
161: uint idx = addr / 8192;
162: __assume(idx < 2048);
163: return table[idx];
164: }
165:
166: uint64
167: X68kIODevice::Read8(uint32 addr)
168: {
169: addr &= 0x00ffffff;
170: IODevice *d = SearchDevice(addr);
171: return d->Read8(addr);
172: }
173:
174: uint64
175: X68kIODevice::Read16(uint32 addr)
176: {
177: addr &= 0x00ffffff;
178: IODevice *d = SearchDevice(addr);
179: return d->Read16(addr);
180: }
181:
182: uint64
183: X68kIODevice::Read32(uint32 addr)
184: {
185: addr &= 0x00ffffff;
186: IODevice *d = SearchDevice(addr);
187: return d->Read32(addr);
188: }
189:
190: uint64
191: X68kIODevice::Write8(uint32 addr, uint32 data)
192: {
193: addr &= 0x00ffffff;
194: IODevice *d = SearchDevice(addr);
195: return d->Write8(addr, data);
196: }
197:
198: uint64
199: X68kIODevice::Write16(uint32 addr, uint32 data)
200: {
201: addr &= 0x00ffffff;
202: IODevice *d = SearchDevice(addr);
203: return d->Write16(addr, data);
204: }
205:
206: uint64
207: X68kIODevice::Write32(uint32 addr, uint32 data)
208: {
209: addr &= 0x00ffffff;
210: IODevice *d = SearchDevice(addr);
211: return d->Write32(addr, data);
212: }
213:
214: uint64
215: X68kIODevice::Peek8(uint32 addr)
216: {
217: addr &= 0x00ffffff;
218: IODevice *d = SearchDevice(addr);
219: return d->Peek8(addr);
220: }
221:
222: // このアドレスを担当する次段の IODevice を返す (IOContainerDevice 用)
223: IODevice *
224: X68kIODevice::GetDevice(uint32 addr) const
225: {
226: return SearchDevice(addr & 0x00ffffff);
227: }
228:
1.1.1.2 ! root 229: void
! 230: X68kIODevice::MonitorUpdate(Monitor *, TextScreen& screen)
! 231: {
! 232: screen.Clear();
! 233:
! 234: // 012345678901234567890
! 235: // $00'0000: 1234567
! 236:
! 237: // pos が表示開始位置(0-)
! 238: int pos = (int)screen.userdata;
! 239: int row = screen.GetRow();
! 240:
! 241: for (int i = 0; i < 8; i++) {
! 242: screen.Print(10 + i * 8, 0, "+$%04x", i * 0x2000);
! 243: }
! 244:
! 245: int idx = pos * 8;
! 246: for (int y = 1; y < row; y++) {
! 247: uint32 addr = idx * 0x2000;
! 248: std::string addrstr = '$' + strhex(addr >> 16, 2) + "'0000:";
! 249: screen.Puts(0, y, addrstr.c_str());
! 250: for (int i = 0; i < 8; i++) {
! 251: auto pair = MainbusDevice::FormatDevName(table[idx]);
! 252: const std::string& name = pair.first;
! 253: TA attr = pair.second;
! 254: screen.Print(10 + i * 8, y, attr, "%s", name.c_str());
! 255: idx++;
! 256: }
! 257: }
! 258: }
! 259:
1.1 root 260: // ブートページを切り替える。
261: // (VM_X68030::SwitchBootPage() の下請け)
262: void
263: X68kIODevice::SwitchBootPage(bool isrom)
264: {
265: IODevice *ram;
266: IODevice *rom;
267:
268: if (isrom) {
269: // 0x000000 からの 64KB ( 8エントリ)、
270: // 0xfe0000 からの 128KB (16エントリ) のどちらも IPLROM0 が担当する。
271: ram = GetIPLROM0Device();
272: rom = GetIPLROM0Device();
273: } else {
274: // 0x000000 からの 64KB ( 8エントリ) に RAM を見せる。
275: // 0xfe0000 からの 128KB (16エントリ) に IPLROM1 を見せる。
276: ram = GetMainRAMDevice();
277: rom = GetIPLROM1Device();
278: }
279:
280: for (int i = 0; i < 8; i++) {
281: table[i] = ram;
282: }
283: for (int i = 0; i < 16; i++) {
284: table[table.size() - 16 + i] = rom;
285: }
286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.