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

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

unix.superglobalmegacorp.com

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