Annotation of nono/vm/x68kio.cpp, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.