--- nono/vm/xiospace.cpp 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/xiospace.cpp 2026/04/29 17:05:14 1.1.1.11 @@ -1,20 +1,31 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include +// +// X68030 のメイン空間 ($000000-$FFFFFF) 担当 +// + +#include "xiospace.h" +#include "adpcm.h" #include "areaset.h" +#include "busio.h" +#include "config.h" #include "crtc.h" #include "dmac.h" #include "fdc.h" #include "gvram.h" -#include "iocon.h" #include "mfp.h" +#include "opm.h" +#include "pedec.h" +#include "pio.h" #include "pluto.h" -#include "ppi.h" #include "printer.h" #include "ram.h" +#include "romemu_x68k.h" +#include "romimg_x68k.h" #include "rp5c15.h" #include "scc.h" #include "spc.h" @@ -22,75 +33,56 @@ #include "sram.h" #include "sysport.h" #include "tvram.h" -#include "vicon.h" +#include "videoctlr.h" #include "vm.h" -#include "x68krom.h" -#include "xiospace.h" // -// X68030 のメイン空間 ($000000-$FFFFFF) 担当。 -// - -// デバイス -AreaSetDevice *areaset; -CGROMDevice *cgrom; -CRTCDevice *crtc; -DMACDevice *dmac; -FDCDevice *fdc; -IPLROM1Device *iplrom1; -IPLROM2Device *iplrom2; -PlutoDevice *pluto; -PPIDevice *ppi; -PrinterDevice *printer; -SCCDevice *scc; -SpriteDevice *sprite; -SysportDevice *sysport; - // 1つの 8KB ブロックを複数のデバイスで共有する場合 -class MuxDevice - : public IODevice +// +class MuxDevice : public IODevice { - typedef IODevice inherited; + using inherited = IODevice; public: MuxDevice(); - virtual ~MuxDevice(); + virtual ~MuxDevice() override; - virtual uint64 Read8(uint32 addr); - virtual uint64 Read16(uint32 addr); - virtual uint64 Write8(uint32 addr, uint32 data); - virtual uint64 Write16(uint32 addr, uint32 data); - virtual uint64 Peek8(uint32 addr); + uint64 Read8(uint32 addr) override; + uint64 Read16(uint32 addr) override; + uint64 Write8(uint32 addr, uint32 data) override; + uint64 Write16(uint32 addr, uint32 data) override; + uint64 Peek8(uint32 addr) override; - IODevice *SearchDevice(uint32 addr); + IODevice *SearchDevice(uint32 addr) const; void AddDevice(IODevice *dev); std::vector devlist; }; +// コンストラクタ MuxDevice::MuxDevice() + : inherited("MuxDevice") { - logname = "none"; } +// デストラクタ MuxDevice::~MuxDevice() { } -// デバイスを追加します。 -// ここに追加するデバイスは dev->devlen の指定が必須です。 +// デバイスを追加する。 +// ここに追加するデバイスは dev->devlen を指定すること。 void MuxDevice::AddDevice(IODevice *dev) { - if (dev->devlen == 0) { - printf("MuxDevice::AddDevice: '%s' devlen not set!\n", dev->devname); - exit(1); - } + assertmsg(dev->devlen != 0, "MuxDevice::AddDevice '%s'", + dev->GetName().c_str()); + devlist.push_back(dev); } IODevice * -MuxDevice::SearchDevice(uint32 addr) +MuxDevice::SearchDevice(uint32 addr) const { for (const auto& d : devlist) { if (d->devaddr <= addr && addr < d->devaddr + d->devlen) { @@ -151,93 +143,115 @@ MuxDevice::Peek8(uint32 addr) } +// +// X68030 のメイン空間担当 +// + +// グローバル参照用 +XIOSpaceDevice *gXIOSpace; + // コンストラクタ XIOSpaceDevice::XIOSpaceDevice() + : inherited("IOSpace") { - logname = "xiospace"; - devname = "IOSpace"; +#define ADD_DEVICE(NAME, NEW_CTOR) do { \ + NEWDV(NAME, NEW_CTOR); \ + AddDevice(dynamic_cast(__CONCAT(p,NAME).get())); \ +} while (0) + + // デバイスクラス作成 (順序に注意) + ADD_DEVICE(ADPCM, new BusIO_EB()); + ADD_DEVICE(AreaSet, new AreaSetDevice()); + ADD_DEVICE(CGROM, new CGROMDevice()); + ADD_DEVICE(CRTC, new BusIO_W()); + ADD_DEVICE(DMAC, new DMACDevice()); + ADD_DEVICE(FDC, new BusIO_EB()); + ADD_DEVICE(GVRAM, new GVRAMDevice()); + ADD_DEVICE(PEDEC, new BusIO_EB()); + ADD_DEVICE(IPLROM1, new IPLROM1Device()); + if (gConfig->Find("iplrom2-image").AsString().empty()) { + ADD_DEVICE(IPLROM2, new ROM30EmuDevice()); + } else { + ADD_DEVICE(IPLROM2, new IPLROM2Device()); + } + ADD_DEVICE(MFP, new BusIO_EB()); + ADD_DEVICE(PlaneVRAM, new TVRAMDevice()); + ADD_DEVICE(Pluto, new PlutoDevice()); + ADD_DEVICE(PPI, new BusIO_EB()); + ADD_DEVICE(Printer, new PrinterDevice()); + ADD_DEVICE(RTC, new BusIO_EB()); + ADD_DEVICE(SCC, new BusIO_EB()); + ADD_DEVICE(SRAM, new SRAMDevice()); // Required by SPC + ADD_DEVICE(SPC, new BusIO_X68kSPC()); + ADD_DEVICE(Sprite, new SpriteDevice()); + ADD_DEVICE(Sysport, new BusIO_FB()); + ADD_DEVICE(VideoCtlr, new BusIO_W()); + ADD_DEVICE(OPM, new BusIO_EB()); +} + +// デストラクタ +XIOSpaceDevice::~XIOSpaceDevice() +{ + gXIOSpace = NULL; +} - // メモリ - // 通常メイン RAM は bus から直接アクセスするが、ウェイトを入れたい - // 場合や上位8ビットに値が入っていて 24bit にミラーされたアドレスへの - // アクセスになる場合はここを通る。 +bool +XIOSpaceDevice::Init() +{ + // RAM のみ RamDevice::Init() で ram_size が決定してから行う。 + int ram_size = gRAM->GetSize(); for (int i = 0; i < ram_size / 8192; i++) { table[i] = gRAM; } -#define ADD_DEVICE(varname, clsname) do { \ - varname = new clsname; \ - AddDevice(static_cast(varname)); \ -} while (0) - - // デバイスクラス作成 (順序に注意) - ADD_DEVICE(areaset, AreaSetDevice()); - ADD_DEVICE(cgrom, CGROMDevice()); - ADD_DEVICE(crtc, CRTCDevice()); - ADD_DEVICE(dmac, DMACDevice()); - ADD_DEVICE(fdc, FDCDevice()); - ADD_DEVICE(gGVRAM, GVRAMDevice()); - ADD_DEVICE(gIOCon, IOConDevice()); - ADD_DEVICE(iplrom1, IPLROM1Device()); - ADD_DEVICE(iplrom2, IPLROM2Device()); - ADD_DEVICE(gMFP, MFPDevice()); - ADD_DEVICE(pluto, PlutoDevice()); - ADD_DEVICE(ppi, PPIDevice()); - ADD_DEVICE(printer, PrinterDevice()); - ADD_DEVICE(gRTC, RP5C15Device()); - ADD_DEVICE(scc, SCCDevice()); - ADD_DEVICE(gSPC, SPCDevice(0xe96000)); - ADD_DEVICE(sprite, SpriteDevice()); - ADD_DEVICE(gSRAM, SRAMDevice()); - ADD_DEVICE(sysport, SysportDevice()); - ADD_DEVICE(gTVRAM, TVRAMDevice()); - ADD_DEVICE(gVicon, ViconDevice()); + // 必要なデバイスは全部埋めたので、この時点で nullptr なエントリを + // BusErr に差し替える。 + for (auto&& d : table) { + if (d == nullptr) { + d = gBusErr; + } + } // デバッグ表示 if (0) { - for (int i = 0; i < 512; i++) { - printf("[%3d] $%06x ", i, 0xc00000 + i * 8192); - if (table[i] == nullptr) { - printf("null\n"); - } else if (dynamic_cast(table[i])) { + for (int i = 1536; i < table.size(); i++) { + printf("[%3d] $%06x ", i, i * 8192); + assert(table[i]); + if (dynamic_cast(table[i])) { printf("MuxDevice\n"); - } else if (dynamic_cast(table[i])) { - printf("%s\n", table[i]->devname); + } else { + printf("%s\n", table[i]->GetName().c_str()); } } } -} -// デストラクタ -XIOSpaceDevice::~XIOSpaceDevice() -{ + return true; } // デバイステーブルに dev を追加する。 -// ここに追加するデバイスは dev->devlen の指定が必須です。 +// ここに追加するデバイスは dev->devlen を指定すること。 void XIOSpaceDevice::AddDevice(IODevice *dev) { - if (dev->devaddr == 0) { - printf("XIOSpaceDevice:AddDevice: '%s' devaddr not set!\n", dev->devname); - exit(1); - } - if (dev->devlen == 0) { - printf("XIOSpaceDevice:AddDevice: '%s' devlen not set!\n", dev->devname); - exit(1); - } + assertmsg(dev->devaddr != 0, "XIOSpaceDevice:AddDevice '%s'", + dev->GetName().c_str()); + assertmsg(dev->devlen != 0, "XIOSpaceDevice:AddDevice '%s'", + dev->GetName().c_str()); int idx = dev->devaddr / 8192; for (int i = idx; i < idx + (dev->devlen + 8191) / 8192; i++) { if (table[i] == nullptr) { table[i] = dev; - } else if (typeid(*table[i]) == typeid(MuxDevice)) { - (static_cast(table[i]))->AddDevice(dev); } else { - MuxDevice *muxdev = new MuxDevice(); - muxdev->AddDevice(table[i]); - muxdev->AddDevice(dev); - table[i] = muxdev; + MuxDevice *mux = dynamic_cast(table[i]); + if (mux) { + mux->AddDevice(dev); + } else { + MuxDevice *muxdev = new MuxDevice(); + muxdev->AddDevice(table[i]); + muxdev->AddDevice(dev); + table[i] = muxdev; + } } } } @@ -247,10 +261,6 @@ XIOSpaceDevice::Read8(uint32 addr) { addr &= 0x00ffffff; IODevice *d = SearchDevice(addr); - // BusErrDevice 導入すればこの if は不要 - if (d == nullptr) { - return (uint64)-1; - } return d->Read8(addr); } @@ -259,10 +269,6 @@ XIOSpaceDevice::Read16(uint32 addr) { addr &= 0x00ffffff; IODevice *d = SearchDevice(addr); - // BusErrDevice 導入すればこの if は不要 - if (d == nullptr) { - return (uint64)-1; - } return d->Read16(addr); } @@ -271,10 +277,6 @@ XIOSpaceDevice::Read32(uint32 addr) { addr &= 0x00ffffff; IODevice *d = SearchDevice(addr); - // BusErrDevice 導入すればこの if は不要 - if (d == nullptr) { - return (uint64)-1; - } return d->Read32(addr); } @@ -283,10 +285,6 @@ XIOSpaceDevice::Write8(uint32 addr, uint { addr &= 0x00ffffff; IODevice *d = SearchDevice(addr); - // BusErrDevice 導入すればこの if は不要 - if (d == nullptr) { - return (uint64)-1; - } return d->Write8(addr, data); } @@ -295,10 +293,6 @@ XIOSpaceDevice::Write16(uint32 addr, uin { addr &= 0x00ffffff; IODevice *d = SearchDevice(addr); - // BusErrDevice 導入すればこの if は不要 - if (d == nullptr) { - return (uint64)-1; - } return d->Write16(addr, data); } @@ -307,10 +301,6 @@ XIOSpaceDevice::Write32(uint32 addr, uin { addr &= 0x00ffffff; IODevice *d = SearchDevice(addr); - // BusErrDevice 導入すればこの if は不要 - if (d == nullptr) { - return (uint64)-1; - } return d->Write32(addr, data); } @@ -319,9 +309,33 @@ XIOSpaceDevice::Peek8(uint32 addr) { addr &= 0x00ffffff; IODevice *d = SearchDevice(addr); - // BusErrDevice 導入すればこの if は不要 - if (d == nullptr) { - return (uint64)-1; - } return d->Peek8(addr); } + +// ブートページを切り替える。 +// (VM_X68030::SwitchBootPage() の下請け) +void +XIOSpaceDevice::SwitchBootPage(bool isrom) +{ + IODevice *ram; + IODevice *rom; + + if (isrom) { + // 0x000000 からの 64KB ( 8エントリ)、 + // 0xfe0000 からの 128KB (16エントリ) のどちらも IPLROM0 が担当する。 + ram = gIPLROM0; + rom = gIPLROM0; + } else { + // 0x000000 からの 64KB ( 8エントリ) に RAM を見せる。 + // 0xfe0000 からの 128KB (16エントリ) に IPLROM1 を見せる。 + ram = gRAM; + rom = gIPLROM1; + } + + for (int i = 0; i < 8; i++) { + table[i] = ram; + } + for (int i = 0; i < 16; i++) { + table[table.size() - 16 + i] = rom; + } +}