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

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: 
1.1.1.3 ! root       11: // IODevice
        !            12: //   +-- MainbusBaseDevice (InitMainbus() と FC アクセスを持つ)
        !            13: //   |    +-- MainbusDevice (これがメインバス、システムに1つ)
        !            14: //   |    |    +-- Mainbus24Device (上位8ビットがテーブルで表せるメインバス)
        !            15: //   |    |    |    +-- LunaMainbus
        !            16: //   |    |    |    |    +-- Luna1Mainbus
        !            17: //   |    |    |    |    +-- Luna88kMainbus
        !            18: //   |    |    |    +-- NewsMainbus
        !            19: //   |    |    +-- X68kMainbus
        !            20: //   |    |
        !            21: //   |    |  +--------------+
        !            22: //   |    +--| X68kIODevice | (FC を受け取るため)
        !            23: //   |       +--------------+
        !            24: //   |
        !            25: //   +-- XPbusDevice
        !            26: 
1.1       root       27: #include "x68kio.h"
                     28: #include "adpcm.h"
                     29: #include "areaset.h"
1.1.1.3 ! root       30: #include "bankram.h"
1.1       root       31: #include "busio.h"
                     32: #include "config.h"
                     33: #include "crtc.h"
                     34: #include "dmac.h"
1.1.1.3 ! root       35: #include "extarea.h"
1.1       root       36: #include "fdc.h"
                     37: #include "gvram.h"
1.1.1.2   root       38: #include "mainbus.h"
1.1       root       39: #include "mainram.h"
                     40: #include "mfp.h"
1.1.1.3 ! root       41: #include "mpu.h"
1.1.1.2   root       42: #include "nereid.h"
1.1       root       43: #include "opm.h"
                     44: #include "pedec.h"
                     45: #include "pio.h"
                     46: #include "pluto.h"
                     47: #include "printer.h"
                     48: #include "romemu_x68k.h"
                     49: #include "romimg_x68k.h"
                     50: #include "rp5c15.h"
                     51: #include "scc.h"
                     52: #include "spc.h"
                     53: #include "sprite.h"
                     54: #include "sram.h"
                     55: #include "sysport.h"
                     56: #include "tvram.h"
                     57: #include "videoctlr.h"
1.1.1.3 ! root       58: #include "windrv.h"
        !            59: #include <algorithm>
1.1       root       60: 
                     61: // コンストラクタ
                     62: X68kIODevice::X68kIODevice()
                     63:        : inherited(OBJ_X68KIO)
                     64: {
1.1.1.2   root       65:        monitor.func = ToMonitorCallback(&X68kIODevice::MonitorUpdate);
                     66:        monitor.SetSize(73, 1 + 32);
                     67:        monitor.SetMaxHeight(1 + 256);
                     68:        monitor.Regist(ID_SUBWIN_X68KIO);
                     69: 
1.1.1.3 ! root       70:        // エリアセットは実質ここが担当しているので、モニタもここ。
        !            71:        monitor_area.func = ToMonitorCallback(&X68kIODevice::MonitorUpdateAreaset);
        !            72:        monitor_area.SetSize(32, 6);
        !            73:        monitor_area.Regist(ID_MONITOR_AREASET);
        !            74: 
        !            75:        cut_fc2 = (gConfig->Find("x68k-cut-fc2").AsInt() != 0);
        !            76: 
1.1       root       77: #define ADD_DEVICE(NAME, ADDR, LEN)    \
                     78:        AddDevice(__CONCAT(p,NAME).get(), ADDR, LEN)
                     79: 
                     80: #define N(NAME, NEW_CTOR, ADDR, LEN)   do {    \
                     81:                NEWDV(NAME, NEW_CTOR);  \
                     82:                ADD_DEVICE(NAME, ADDR, LEN);    \
                     83:        } while (0)
                     84: 
1.1.1.3 ! root       85:        NEWDV(BusErr, new BusErrDevice());
        !            86:        NEWDV(MainRAM, new MainRAMDevice());
        !            87:        NEWDV(IPLROM0, new IPLROM0Device());
        !            88: 
1.1       root       89:        // デバイスクラス作成。
                     90:        // 初期化順の制約がない限りアドレス順。
                     91:        //                                              開始アドレス 長さ
                     92:        N(GVRAM, new GVRAMDevice(),                                     0xc00000,0x200000);
                     93:        N(PlaneVRAM, new TVRAMDevice(),                         0xe00000, 0x80000);
1.1.1.3 ! root       94:        N(CRTC, new CRTCDevice(),                                       0xe80000,  0x2000);
1.1       root       95:        N(VideoCtlr, new VideoCtlrDevice(),                     0xe82000,  0x2000);
                     96:        N(DMAC, new DMACDevice(),                                       0xe84000,  0x2000);
                     97:        N(AreaSet, new AreaSetDevice(),                         0xe86000,  0x2000);
                     98:        N(MFP, new BusIO_EB<MFPDevice>(),                       0xe88000,  0x2000);
                     99:        N(RTC, new BusIO_EB<RP5C15Device>(),            0xe8a000,  0x2000);
                    100:        N(Printer, new PrinterDevice(),                         0xe8c000,  0x2000);
                    101:        N(Sysport,new BusIO_FB<SysportDevice>(),        0xe8e000,  0x2000);
                    102:        N(OPM, new BusIO_EB<OPMDevice>(),                       0xe90000,  0x2000);
                    103:        N(ADPCM, new BusIO_EB<ADPCMDevice>(),           0xe92000,  0x2000);
                    104:        N(FDC, new BusIO_EB<FDCDevice>(),                       0xe94000,  0x2000);
                    105:        N(SPC, new BusIO_X68kSPC<SPCDevice>(),          0xe96000,  0x2000);
                    106:        N(SCC, new BusIO_EB<SCCDevice>(),                       0xe98000,  0x2000);
                    107:        N(PPI, new BusIO_EB<PPIDevice>(),                       0xe9a000,  0x2000);
                    108:        N(PEDEC, new BusIO_EB<PEDECDevice>(),           0xe9c000,  0x2000);
1.1.1.3 ! root      109:        // Windrv はデバイスは常に作成し、マップするかどうかは設定による。
        !           110:        NEWDV(Windrv, new WindrvDevice());
        !           111:        if (WindrvDevice::IsWindrv()) {
        !           112:                ADD_DEVICE(Windrv,                                              0xe9e000,  0x2000);
        !           113:        }
1.1       root      114:        N(Pluto, new PlutoDevice(),                                     0xeac000,  0x2000);
1.1.1.3 ! root      115:        N(ExtArea, new ExtAreaDevice(),                         0xeae000,  0x2000);
1.1       root      116:        N(Sprite, new SpriteDevice(),                           0xeb0000, 0x10000);
1.1.1.2   root      117:        // Nereid はこの時点ではデバイスの追加のみ。Init() 参照。
                    118:        NEWDV(Nereid, new NereidDevice());              //      0xece000,  0x2000
1.1       root      119:        N(SRAM, new SRAMDevice(),                                       0xed0000,  0x4000);
                    120:        N(CGROM, new CGROMDevice(),                                     0xf00000, 0xc0000);
                    121:        if (gConfig->Find("iplrom2-image").AsString().empty()) {
                    122:                NEWDV(IPLROM2, new ROM30EmuDevice());
                    123:        } else {
                    124:                NEWDV(IPLROM2, new IPLROM2Device());
                    125:        }
                    126:        ADD_DEVICE(IPLROM2,                                                     0xfc0000, 0x20000);
                    127:        N(IPLROM1, new IPLROM1Device(),                         0xfe0000, 0x20000);
                    128: }
                    129: 
                    130: // デストラクタ
                    131: X68kIODevice::~X68kIODevice()
                    132: {
                    133: }
                    134: 
1.1.1.3 ! root      135: // メインバスの初期化
1.1       root      136: bool
1.1.1.3 ! root      137: X68kIODevice::InitMainbus()
1.1       root      138: {
1.1.1.3 ! root      139:        auto buserr = pBusErr.get();
        !           140:        auto mainram = dynamic_cast<MainRAMDevice*>(pMainRAM.get());
1.1       root      141: 
1.1.1.3 ! root      142:        // RAM は容量が確定した後のここで配置。
1.1       root      143:        for (int i = 0; i < mainram->GetSize() / 8192; i++) {
1.1.1.3 ! root      144:                sdevice[i] = mainram;
1.1       root      145:        }
                    146: 
1.1.1.2   root      147:        // Nereid は1枚でもボードがある時だけメモリ空間に追加する。
                    148:        // Nereid が1枚もない場合でもモニタやログ(この場合のログは起動時にどれが
                    149:        // 有効とか無効と判断したことを表示するもの)のためデバイス自体は常に存在。
                    150:        auto nereid = GetNereidDevice();
                    151:        if (nereid->IsInstalled()) {
                    152:                ADD_DEVICE(Nereid, 0xece000, 0x2000);
1.1.1.3 ! root      153: 
        !           154:                // バンク領域もバンクメモリが有効な場合のみ追加する。
        !           155:                // #0 が $ee0000、
        !           156:                // #1 が $ef0000 固定にしている。
        !           157:                for (int i = 0; i < 2; i++) {
        !           158:                        auto bank = gMainApp.FindObject<BankRAMDevice>(OBJ_BANKRAM(i));
        !           159:                        if (bank != NULL && bank->GetSize() > 0) {
        !           160:                                AddDevice(bank, 0xee0000 + i * 0x010000, 0x010000);
        !           161:                        }
        !           162:                }
1.1.1.2   root      163:        }
                    164: 
1.1       root      165:        // 必要なデバイスは全部埋めたので、この時点で nullptr なエントリを
                    166:        // BusErr に差し替える。
1.1.1.3 ! root      167:        for (auto&& d : sdevice) {
1.1       root      168:                if (d == nullptr) {
                    169:                        d = buserr;
                    170:                }
                    171:        }
                    172: 
1.1.1.3 ! root      173:        // ユーザ空間にコピー。
        !           174:        // 00'0000 - BF'FFFF: S U : RAM
        !           175:        // C0'0000 - E7'FFFF: S - : GVRAM/TVRAM
        !           176:        // E8'0000 - EB'FFFF: S - : I/O 空間
        !           177:        // EC'0000 - EC'FFFF: S U : ユーザ I/O 空間
        !           178:        // ED'0000 - EF'FFFF: S - : I/O 空間
        !           179:        // F0'0000 - FF'FFFF: S - : ROM
        !           180:        SetUdevice(0x000000, 0xbfffff, true);
        !           181:        SetUdevice(0xc00000, 0xebffff, false);
        !           182:        SetUdevice(0xec0000, 0xecffff, true);
        !           183:        SetUdevice(0xed0000, 0xffffff, false);
        !           184: 
        !           185:        // ユーザ空間も nullptr をチェック。
        !           186:        assert(std::all_of(udevice.begin(), udevice.end(),
        !           187:                [](IODevice *d) { return d != nullptr; }));
        !           188: 
1.1       root      189:        // デバッグ表示
                    190:        if (0) {
1.1.1.3 ! root      191:                for (int i = 1536; i < sdevice.size(); i++) {
1.1       root      192:                        printf("[%3d] $%06x ", i, i * 8192);
1.1.1.3 ! root      193:                        assert(sdevice[i]);
        !           194:                        assert(udevice[i]);
        !           195:                        printf("S:%-8s U:%s\n",
        !           196:                                sdevice[i]->GetName().c_str(),
        !           197:                                udevice[i]->GetName().c_str());
1.1       root      198:                }
                    199:        }
                    200: 
                    201:        return true;
                    202: }
                    203: 
1.1.1.3 ! root      204: // アドレス start から end (を含む) までのユーザ空間を作成する。
        !           205: // accessible true ならユーザアクセス可能 (スーパーバイザ空間をコピー)。
        !           206: // false なら BusErr で埋める。
        !           207: void
        !           208: X68kIODevice::SetUdevice(uint32 startaddr, uint32 endaddr, bool accessible)
        !           209: {
        !           210:        assert(startaddr < endaddr);
        !           211:        assert(((endaddr + 1) & 0x1fff) == 0);
        !           212:        int start = startaddr / 8192;
        !           213:        int end = (endaddr + 1) / 8192;
        !           214: 
        !           215:        // MPU の FC2 ピンカットの動作は本来 MPU 側を加工すべきだが、
        !           216:        // MPU アクセスのほうが圧倒的に多いので影響の少ない DMAC 側で処理する。
        !           217: 
        !           218:        // FC2 ピンカットする前の情報を DMAC に展開。
        !           219:        auto dmac = dynamic_cast<DMACDevice*>(pDMAC.get());
        !           220:        dmac->SetUdevice(start, end, accessible);
        !           221: 
        !           222:        // FC2 ピンカットなら全域がユーザアクセス可能。
        !           223:        if (cut_fc2) {
        !           224:                accessible = true;
        !           225:        }
        !           226: 
        !           227:        if (accessible) {
        !           228:                memcpy(&udevice[start], &sdevice[start],
        !           229:                        (end - start) * sizeof(udevice[0]));
        !           230:        } else {
        !           231:                auto buserr = pBusErr.get();
        !           232:                for (int i = start; i < end; i++) {
        !           233:                        udevice[i] = buserr;
        !           234:                }
        !           235:        }
        !           236: }
        !           237: 
        !           238: // デバイステーブル sdevice に dev を追加する。
1.1       root      239: void
                    240: X68kIODevice::AddDevice(IODevice *dev, uint devaddr, uint devlen)
                    241: {
                    242:        int idx = devaddr / 8192;
                    243:        for (int i = idx; i < idx + (devlen + 8191) /  8192; i++) {
                    244:                // 重複するケースは未対応
1.1.1.3 ! root      245:                assertmsg(sdevice[i] == nullptr, "X68kIODevice.AddDevice '%s'",
        !           246:                        sdevice[i]->GetName().c_str());
1.1       root      247: 
1.1.1.3 ! root      248:                sdevice[i] = dev;
1.1       root      249:        }
                    250: }
                    251: 
1.1.1.3 ! root      252: // アドレス super:addr に対応する IODevice* を返す。
1.1       root      253: // addr は事前に 24bit マスクしてあるもの。
                    254: inline IODevice *
1.1.1.3 ! root      255: X68kIODevice::Decoder(bool super, uint32 addr) const
1.1       root      256: {
                    257:        uint idx = addr / 8192;
1.1.1.3 ! root      258:        if (super) {
        !           259:                return sdevice[idx];
        !           260:        } else {
        !           261:                return udevice[idx];
        !           262:        }
1.1       root      263: }
                    264: 
1.1.1.3 ! root      265: busdata
        !           266: X68kIODevice::Peek8(uint32 addr)
1.1       root      267: {
                    268:        addr &= 0x00ffffff;
1.1.1.3 ! root      269: 
        !           270:        IODevice *d = Decoder(true, addr);
        !           271:        return d->Peek8(addr);
1.1       root      272: }
                    273: 
1.1.1.3 ! root      274: bool
        !           275: X68kIODevice::Poke8(uint32 addr, uint32 data)
1.1       root      276: {
                    277:        addr &= 0x00ffffff;
1.1.1.3 ! root      278: 
        !           279:        IODevice *d = Decoder(true, addr);
        !           280:        return d->Poke8(addr, data);
1.1       root      281: }
                    282: 
1.1.1.3 ! root      283: // 回路図より CIIN は以下の通り。
        !           284: //
        !           285: // FC1 ---------|
        !           286: // ______       |OR ---o|&      ____
        !           287: // DSACK0 --o|>-|       |&o---- CIIN
        !           288: // __                   |&
        !           289: // AS -----------------o|&
        !           290: //
        !           291: // __     ___                 ____
        !           292: // AS FC1 DS0 : DS0 FC1|DS0 : CIIN
        !           293: //  L   0   H :  L     L    :  L   (データ空間 & 16ビットポート)
        !           294: //  L   0   L :  H     H    :  H
        !           295: //  L   1   H :  L     H    :  H
        !           296: //  L   1   L :  H     H    :  H
        !           297: 
        !           298: inline void
        !           299: X68kIODevice::CheckCI(busaddr addr)
1.1       root      300: {
1.1.1.3 ! root      301:        // 16ビットポートはメインメモリ、GVRAM、TVRAM、ROM を除いた部分なので
        !           302:        // 0xe80000 .. 0xefffff かな。
        !           303:        busaddr cimask(0xf80000, busaddr::D);
        !           304:        busaddr data16(0xe80000, busaddr::D);
        !           305:        if ((addr.Get() & cimask.Get()) == data16.Get()) {
        !           306:                mpu->SetCI();
        !           307:        }
1.1       root      308: }
                    309: 
1.1.1.3 ! root      310: // Read*/Write* 全部の共通部分。副作用のあるマクロ。
        !           311: #define PREPARE() \
        !           312:        CheckCI(addr);  \
        !           313:        uint32 addr24 = addr.Addr() & 0x00ffffff;       \
        !           314:        IODevice *d = Decoder(addr.IsSuper(), addr24);
        !           315: 
        !           316: busdata
        !           317: X68kIODevice::Read8(busaddr addr)
1.1       root      318: {
1.1.1.3 ! root      319:        PREPARE();
        !           320: 
        !           321:        busdata bd = d->Read8(addr24);
        !           322:        putlog(2, "Read  $%06x -> $%02x", addr24, bd.Data());
        !           323:        return bd;
1.1       root      324: }
                    325: 
1.1.1.3 ! root      326: busdata
        !           327: X68kIODevice::Read16(busaddr addr)
1.1       root      328: {
1.1.1.3 ! root      329:        PREPARE();
        !           330: 
        !           331:        busdata bd = d->Read16(addr24);
        !           332:        putlog(2, "Read  $%06x -> $%04x", addr24, bd.Data());
        !           333:        return bd;
1.1       root      334: }
                    335: 
1.1.1.3 ! root      336: busdata
        !           337: X68kIODevice::Read32(busaddr addr)
1.1       root      338: {
1.1.1.3 ! root      339:        PREPARE();
        !           340: 
        !           341:        busdata bd = d->Read32(addr24);
        !           342:        putlog(2, "Read  $%06x -> $%08x", addr24, bd.Data());
        !           343:        return bd;
1.1       root      344: }
                    345: 
1.1.1.3 ! root      346: busdata
        !           347: X68kIODevice::Write8(busaddr addr, uint32 data)
1.1       root      348: {
1.1.1.3 ! root      349:        PREPARE();
        !           350: 
        !           351:        putlog(1, "Write $%06x <- $%02x", addr24, data);
        !           352:        return d->Write8(addr24, data);
1.1       root      353: }
                    354: 
1.1.1.3 ! root      355: busdata
        !           356: X68kIODevice::Write16(busaddr addr, uint32 data)
1.1       root      357: {
1.1.1.3 ! root      358:        PREPARE();
        !           359: 
        !           360:        putlog(1, "Write $%06x <- $%04x", addr24, data);
        !           361:        return d->Write16(addr24, data);
        !           362: }
        !           363: 
        !           364: busdata
        !           365: X68kIODevice::Write32(busaddr addr, uint32 data)
        !           366: {
        !           367:        PREPARE();
        !           368: 
        !           369:        putlog(1, "Write $%06x <- $%08x", addr24, data);
        !           370:        return d->Write32(addr24, data);
1.1       root      371: }
                    372: 
1.1.1.2   root      373: void
                    374: X68kIODevice::MonitorUpdate(Monitor *, TextScreen& screen)
                    375: {
                    376:        screen.Clear();
                    377: 
                    378:        // pos が表示開始位置(0-)
                    379:        int pos = (int)screen.userdata;
                    380: 
1.1.1.3 ! root      381:        // ヘッダは常に描く
        !           382:        screen.Clear();
1.1.1.2   root      383:        for (int i = 0; i < 8; i++) {
                    384:                screen.Print(10 + i * 8, 0, "+$%04x", i * 0x2000);
                    385:        }
                    386: 
1.1.1.3 ! root      387:        // 012345678901234567890
        !           388:        // $00'0000: 1234567
        !           389: 
1.1.1.2   root      390:        int idx = pos * 8;
1.1.1.3 ! root      391:        for (int y = 1, end = screen.GetRow(); y < end; y++) {
        !           392:                screen.Print(0, y, "$%02x'0000:", (idx * 0x2000) >> 16);
1.1.1.2   root      393:                for (int i = 0; i < 8; i++) {
1.1.1.3 ! root      394:                        auto sdev = sdevice[idx];
        !           395:                        auto udev = udevice[idx];
        !           396:                        auto pair = MainbusBaseDevice::FormatDevName(sdev);
        !           397:                        TA attr;
        !           398:                        if (sdev != udev) {
        !           399:                                // スーパーバイザ空間は太字とかにして区別する。
        !           400:                                attr = TA::Bold;
        !           401:                        } else {
        !           402:                                // 両方からアクセス可能 (かそもそもバスエラー)。
        !           403:                                attr = pair.second;
        !           404:                        }
1.1.1.2   root      405:                        const std::string& name = pair.first;
                    406:                        screen.Print(10 + i * 8, y, attr, "%s", name.c_str());
                    407:                        idx++;
                    408:                }
                    409:        }
                    410: }
                    411: 
1.1       root      412: // ブートページを切り替える。
1.1.1.3 ! root      413: // X68kMainbus から呼ばれるが実際はこっちがメイン。
1.1       root      414: void
                    415: X68kIODevice::SwitchBootPage(bool isrom)
                    416: {
                    417:        IODevice *ram;
                    418:        IODevice *rom;
                    419: 
1.1.1.3 ! root      420:        if (gMainApp.human_mode) {
        !           421:                // Human モードではブートページを RAM に見せる。
        !           422:                // 今のところ。
        !           423:                return;
        !           424:        }
        !           425: 
        !           426:        // 共通処理
        !           427:        inherited::SwitchBootPage(isrom);
        !           428: 
1.1       root      429:        if (isrom) {
                    430:                // 0x000000 からの  64KB ( 8エントリ)、
                    431:                // 0xfe0000 からの 128KB (16エントリ) のどちらも IPLROM0 が担当する。
                    432:                ram = GetIPLROM0Device();
                    433:                rom = GetIPLROM0Device();
                    434:        } else {
                    435:                // 0x000000 からの  64KB ( 8エントリ) に RAM を見せる。
                    436:                // 0xfe0000 からの 128KB (16エントリ) に IPLROM1 を見せる。
                    437:                ram = GetMainRAMDevice();
                    438:                rom = GetIPLROM1Device();
                    439:        }
                    440: 
                    441:        for (int i = 0; i < 8; i++) {
1.1.1.3 ! root      442:                sdevice[i] = ram;
1.1       root      443:        }
                    444:        for (int i = 0; i < 16; i++) {
1.1.1.3 ! root      445:                sdevice[sdevice.size() - 16 + i] = rom;
        !           446:        }
        !           447: }
        !           448: 
        !           449: // エリアセット設定
        !           450: void
        !           451: X68kIODevice::SetAreaset(uint8 arealimit_)
        !           452: {
        !           453:        arealimit = arealimit_;
        !           454: 
        !           455:        // $000000 から (設定値 + 1) * 8KB をスーパーバイザ領域にする。
        !           456:        // $00 なら $000000 から $001FFF まで (8KB)。
        !           457:        // $ff なら $000000 から $01FFFF まで (2MB)。
        !           458:        // X68030 なのでメモリは最低でも 4MB あるので上限チェックは不要。
        !           459:        int end = (arealimit + 1);
        !           460:        SetUdevice(0x00'0000, end * 8192 - 1, false);
        !           461:        SetUdevice(end * 8192, 0x20'0000 - 1, true);
        !           462: }
        !           463: 
        !           464: // 拡張エリアセット取得
        !           465: uint8
        !           466: X68kIODevice::GetExtarea(int offset) const
        !           467: {
        !           468:        if (0 <= offset && offset < extarea.size()) {
        !           469:                return extarea[offset];
        !           470:        }
        !           471:        // ?
        !           472:        return 0xff;
        !           473: }
        !           474: 
        !           475: // 拡張エリアセット設定
        !           476: void
        !           477: X68kIODevice::SetExtarea(int offset, uint8 data)
        !           478: {
        !           479:        if (0 <= offset && offset < extarea.size()) {
        !           480:                extarea[offset] = data;
        !           481:        }
        !           482: 
        !           483:        // [0] $200000 .. $3fffff (2MB)
        !           484:        // [1] $400000 .. $5fffff
        !           485:        // [2] $600000 .. $7fffff
        !           486:        // [3] $800000 .. $9fffff
        !           487:        // [4] $a00000 .. $bfffff
        !           488:        //
        !           489:        // +----+----+----+----+----+----+----+----+
        !           490:        // | S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 |
        !           491:        // +----+----+----+----+----+----+----+----+
        !           492:        //
        !           493:        // S0 は +$000000 〜 +$03ffff (256KB、32エントリ)
        !           494:        // S1 は +$040000 〜 +$07ffff
        !           495:        // S2 は +$080000 〜 +$0bffff
        !           496:        // S3 は +$0c0000 〜 +$0fffff
        !           497:        // S4 は +$100000 〜 +$13ffff
        !           498:        // S5 は +$140000 〜 +$17ffff
        !           499:        // S6 は +$180000 〜 +$1bffff
        !           500:        // S7 は +$1c0000 〜 +$1fffff
        !           501:        //
        !           502:        // %1 ならスーパーバイザ保護 (ユーザアクセス不可)。
        !           503: 
        !           504:        uint32 addr = (offset + 1) * 0x20'0000;
        !           505:        data = ~data;
        !           506:        for (int i = 0; i < 8; i++) {
        !           507:                bool u = (data & 1);
        !           508:                SetUdevice(addr, addr + 0x04'0000 - 1, u);
        !           509: 
        !           510:                data >>= 1;
        !           511:                addr += 0x04'0000;
        !           512:        }
        !           513: }
        !           514: 
        !           515: // エリアセットと拡張エリアセットのモニタ。
        !           516: void
        !           517: X68kIODevice::MonitorUpdateAreaset(Monitor *, TextScreen& screen)
        !           518: {
        !           519:        int areaend;
        !           520: 
        !           521:        screen.Clear();
        !           522: 
        !           523:        // エリアセット
        !           524:        areaend = (arealimit + 1) * 8192;
        !           525:        screen.Print(0, 0, "Areaset    $%02x  $000000-$%06x",
        !           526:                arealimit, areaend);
        !           527: 
        !           528:        // 拡張エリアセット
        !           529:        for (int i = 0; i < extarea.size(); i++) {
        !           530:                uint8 data = GetExtarea(i);
        !           531:                screen.Print(0, i + 1, "Extarea[%d] $%02x  $%06x", i, data,
        !           532:                        (i + 1) * 0x20'0000);
        !           533:                for (int j = 0; j < 8; j++) {
        !           534:                        screen.Putc(24 + j, i + 1, (((int8)data < 0) ? 'S' : '-'));
        !           535:                        data <<= 1;
        !           536:                }
1.1       root      537:        }
                    538: }

unix.superglobalmegacorp.com

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