Annotation of nono/vm/romemu_luna.cpp, revision 1.1.1.15

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.13  root        7: //
1.1.1.7   root        8: // LUNA シリーズの ROM エミュレーション共通部分
1.1.1.10  root        9: //
1.1.1.13  root       10: 
1.1.1.10  root       11: // IODevice
                     12: //    |
                     13: //    +-- ROMDevice (LoadROM()、ウェイト、マスク等を持つ)
                     14: //    |     |
                     15: //    |     +-- PROMDevice    (LUNA* の PROM)
                     16: //    |     +-- IPLROM1Device (X680x0 の IPLROM 後半)
                     17: //    |     +-- IPLROM2Device (X680x0 の IPLROM 前半)
                     18: //    |     +-- CGROMDevice   (X680x0 の CGROM)
                     19: //    |     |
                     20: //    |     |  +-------------------+
                     21: //    |     +--| LunaPROMEmuDevice | (LUNA PROM エミュレーションの共通部分)
                     22: //    |        +-------------------+
                     23: //    |           |
1.1.1.14  root       24: //    |           +-- Luna1PROMEmuDevice   (LUNA-I の PROM エミュレーション)
                     25: //    |           +-- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション)
1.1.1.10  root       26: //    |
                     27: //    +-- PROM0Device   (LUNA* のブートページ切り替え用プロキシ)
                     28: //    +-- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ)
1.1.1.2   root       29: 
                     30: #include "romemu_luna.h"
1.1.1.14  root       31: #include "bt45x.h"
1.1.1.15! root       32: #include "builtinrom.h"
1.1.1.9   root       33: #include "lunafb.h"
1.1       root       34: #include "mainapp.h"
1.1.1.14  root       35: #include "mainram.h"
1.1       root       36: #include "mk48t02.h"
1.1.1.13  root       37: #include "mpu.h"
1.1.1.14  root       38: #include "pio.h"
1.1.1.13  root       39: #include "prom.h"
1.1       root       40: #include "sio.h"
                     41: #include "spc.h"
1.1.1.7   root       42: #include "ufs.h"
1.1       root       43: 
                     44: // コンストラクタ
                     45: LunaPROMEmuDevice::LunaPROMEmuDevice()
1.1.1.14  root       46:        : inherited(OBJ_PROM)
1.1       root       47: {
1.1.1.10  root       48:        // LUNA では ROM への書き込みは何も起きない
                     49:        write_op = 0;
1.1       root       50: }
                     51: 
                     52: // デストラクタ
                     53: LunaPROMEmuDevice::~LunaPROMEmuDevice()
                     54: {
                     55: }
                     56: 
1.1.1.14  root       57: // 初期化
1.1       root       58: bool
                     59: LunaPROMEmuDevice::Init()
                     60: {
1.1.1.14  root       61:        if (inherited::Init() == false) {
                     62:                return false;
                     63:        }
                     64: 
                     65:        bt45x = GetBT45xDevice();
                     66:        lunafb = GetLunafbDevice();
                     67:        mainram = GetMainRAMDevice();
                     68:        nvram = GetMK48T02Device();
                     69:        sio = GetSIODevice();
                     70:        spc = GetSPCDevice();
1.1       root       71: 
                     72:        return true;
                     73: }
                     74: 
1.1.1.15! root       75: busdata
1.1       root       76: LunaPROMEmuDevice::Read32(uint32 addr)
                     77: {
1.1.1.10  root       78:        // ROM からのロングワードアクセスでだけ謎の I/O 空間が見える。
                     79:        // addr をマスクする前に評価すること。
1.1.1.14  root       80:        if ((mpu->GetPaddr() & 0xff000000) == baseaddr) {
1.1.1.9   root       81:                switch (addr) {
                     82:                 case ROMIO_INIT:
1.1.1.2   root       83:                        return ROM_Init();
1.1       root       84: 
1.1.1.15! root       85:                 case ROMIO_LOAD:
        !            86:                 {
        !            87:                        entrypoint = ROM_Load();
        !            88:                        putlog(2, "ROMIO_LOAD entrypoint=$%08x", entrypoint);
        !            89:                        return 0;
        !            90:                 }
        !            91: 
1.1.1.9   root       92:                 case ROMIO_KEYIN:
1.1.1.15! root       93:                        putlog(2, "ROMIO_KEYIN");
1.1.1.7   root       94:                        ROM_Keyin();
                     95:                        return 0;
1.1       root       96: 
1.1.1.9   root       97:                 case ROMIO_CLOSE:
1.1.1.15! root       98:                        putlog(2, "ROMIO_CLOSE");
1.1.1.7   root       99:                        ROM_Close();
                    100:                        return 0;
1.1       root      101: 
1.1.1.9   root      102:                 case ROMIO_ENTRY:
1.1.1.15! root      103:                 {
        !           104:                        uint32 rv = ROM_Entry();
        !           105:                        putlog(2, "ROMIO_ENTRY entrypoint=$%08x", rv);
        !           106:                        return rv;
        !           107:                 }
        !           108: 
        !           109:                 case ROMIO_AP1:
        !           110:                        ROM_AP1();
        !           111:                        return 0;
        !           112: 
        !           113:                 case ROMIO_AP2:
        !           114:                        ROM_AP2();
        !           115:                        return 0;
        !           116: 
        !           117:                 case ROMIO_CLKCNT:
        !           118:                        return clkcnt;
1.1.1.6   root      119: 
1.1       root      120:                 default:
                    121:                        break;
                    122:                }
                    123:        }
1.1.1.2   root      124: 
1.1.1.10  root      125:        return inherited::Read32(addr);
1.1       root      126: }
                    127: 
1.1.1.15! root      128: busdata
        !           129: LunaPROMEmuDevice::Write32(uint32 addr, uint32 data)
1.1       root      130: {
1.1.1.15! root      131:        // ROM からのロングワードアクセスでだけ謎の I/O 空間が見える。
        !           132:        // addr をマスクする前に評価すること。
        !           133:        if ((mpu->GetPaddr() & 0xff000000) == baseaddr) {
        !           134:                switch (addr) {
        !           135:                 case ROMIO_CLKCNT:
        !           136:                        clkcnt = data;
        !           137:                        return 0;
        !           138:                 default:
        !           139:                        break;
        !           140:                }
        !           141:        }
        !           142: 
        !           143:        return inherited::Write32(addr, data);
        !           144: }
1.1.1.14  root      145: 
1.1.1.15! root      146: // ROM 処理の初期化。
        !           147: int
        !           148: LunaPROMEmuDevice::ROM_Init()
        !           149: {
1.1       root      150:        // 初期パレット
1.1.1.15! root      151:        InitPalette();
1.1       root      152: 
                    153:        // SCSI
                    154:        // BDID の書き込みによってホストデバイスがバスにアタッチされる構造なので。
1.1.1.14  root      155:        spc->Write(SPC::BDID, 7);
1.1       root      156: 
1.1.1.7   root      157:        // キーボード(chB)を初期化
1.1.1.14  root      158:        sio->Write(3, 0x01);            // CR1
                    159:        sio->Write(3, 0x10);            //    RX Int(all char)
                    160:        sio->Write(3, 0x04);            // CR4
                    161:        sio->Write(3, 0x44);            //    Stop 1bit
                    162:        sio->Write(3, 0x03);            // CR3
                    163:        sio->Write(3, 0xc1);            //    RX Enable, 8bit
                    164:        sio->Write(3, 0x05);            // CR5
                    165:        sio->Write(3, 0x68);            //    TX Enable, 8bit
1.1.1.12  root      166: 
                    167:        // LED を(明示的に)オフ、マウスサンプリングをオフ
1.1.1.14  root      168:        sio->Write(2, 0x00);
                    169:        sio->Write(2, 0x01);
                    170:        sio->Write(2, 0x20);
                    171: 
                    172:        // 電源オフをキャンセル。
                    173:        // 実 PROM では、リセット後に PIO のモードセットを行っている。
                    174:        // モードセットを行うと PortC のビットが %0 になる = 電源オフなので、
                    175:        // 即座にこれをキャンセルしている。
                    176:        // ROMEmu ではモードセットを行っていないが、キャンセルだけ発行しておく。
1.1.1.15! root      177:        auto pio1 = GetPIO1Device();
1.1.1.14  root      178:        pio1->Write(3, 0x09);
1.1.1.15! root      179: 
        !           180:        // 機種別の初期化
        !           181:        ROM_InitMD();
        !           182: 
        !           183:        // スクリーンを初期化
        !           184:        InitScreen();
        !           185: 
        !           186:        return 0;
        !           187: }
        !           188: 
        !           189: // 起動時の実行ファイル読み込み処理を行う。
        !           190: // 次段実行ファイルの読み込みに成功すれば execute を true にして、
        !           191: // エントリポイントを返す。
        !           192: // そうでなければ -1 を返す。
        !           193: uint32
        !           194: LunaPROMEmuDevice::ROM_Load()
        !           195: {
        !           196:        uint32 entry;
        !           197: 
        !           198:        entry = -1;
        !           199:        execute = false;
        !           200: 
        !           201:        // 表示環境が整ったところで NVRAM を照合
        !           202:        if (VerifyNVRAM()) {
        !           203:                // DIPSW#1-1 が UP なら自動起動、DOWN なら ROM モニタ起動なので、
        !           204:                // これを真似する。
        !           205:                auto pio0 = GetPIO0Device();
        !           206:                if (pio0->IsDIPSW11Up()) {
        !           207:                        entry = LoadFile("");
        !           208:                        execute = true;
        !           209:                }
        !           210:        } else {
        !           211:                // LUNA-88K の PROM 1.20 は初期化するかどうか確認してくるけど、
        !           212:                // とりあえず。
        !           213:                InitNVRAM();
        !           214:                errmsg = "NVRAM Initialized.";
        !           215:                // NVRAM をクリアしたら DIPSW によらずプロンプトに降りる
        !           216:        }
        !           217: 
        !           218:        if (entry == -1) {
        !           219:                PrintTitle();
        !           220:                if (errmsg.empty() == false) {
        !           221:                        Print("** %s\n\n", errmsg.c_str());
        !           222:                }
        !           223:                ClearPrompt();
        !           224:        }
        !           225: 
        !           226:        return entry;
        !           227: }
        !           228: 
        !           229: // 実行ファイルに処理を移すならそのエントリポイントを返す。
        !           230: // そうでなければ -1 を返す。
        !           231: uint32
        !           232: LunaPROMEmuDevice::ROM_Entry()
        !           233: {
        !           234:        if (execute == false) {
        !           235:                return -1;
        !           236:        }
        !           237:        return entrypoint;
        !           238: }
        !           239: 
        !           240: // パレットを初期化
        !           241: void
        !           242: LunaPROMEmuDevice::InitPalette()
        !           243: {
        !           244:        // 偶数番は白(R/G/B=15/15/15)、奇数番は黒(0/0/0)。
        !           245:        uint8 val = 0xff;
        !           246:        bt45x->Write(0, 0);     // select palette
        !           247:        for (int i = 0; i < 16; i++) {
        !           248:                bt45x->Write(1, val);   // R
        !           249:                bt45x->Write(1, val);   // G
        !           250:                bt45x->Write(1, val);   // B
        !           251:                val ^= 0xff;
        !           252:        }
1.1.1.7   root      253: }
1.1.1.2   root      254: 
1.1.1.7   root      255: // スクリーンを初期化
                    256: void
1.1.1.13  root      257: LunaPROMEmuDevice::InitScreen()
1.1.1.7   root      258: {
1.1.1.14  root      259:        lunafb->EmuInitScreen();
1.1.1.13  root      260: 
                    261:        screen_w = 80;
                    262:        screen_h = 32;
                    263:        cursor_x = 0;
                    264:        cursor_y = 0;
1.1.1.15! root      265:        cursor_on = true;
1.1.1.13  root      266: 
                    267:        // 表示範囲はざっくりセンタリングする
                    268:        origin_px = (1280 - screen_w * 12) / 2;
                    269:        origin_py = (1024 - screen_h * 24) / 2;
                    270:        // 横は 48ドット境界から始めておく。
                    271:        // こうすると1(,2)文字目の24ビットが必ずワード境界から始まるため。
                    272:        // 今となっては任意の場所から文字が描画できるようになったので揃える
                    273:        // 必要はなくなったが、依然このほうがアクセス効率はいいので。
                    274:        origin_px = (origin_px / 48) * 48;
                    275: 
1.1.1.15! root      276:        cursor_on = true;
        !           277: 
1.1.1.2   root      278:        inputbuf.clear();
                    279:        inputpos = 0;
                    280:        is_shift = false;
1.1.1.3   root      281:        mousecnt = 0;
1.1.1.13  root      282: }
1.1       root      283: 
1.1.1.13  root      284: // タイトルを出力
                    285: void
1.1.1.15! root      286: LunaPROMEmuDevice::PrintTitle()
1.1.1.13  root      287: {
                    288:        Print("NONO %d.%d.%d Emulated ROM Monitor for %s\n\n",
1.1.1.7   root      289:                NONO_MAJOR_VER, NONO_MINOR_VER, NONO_PATCH_VER, machine_name);
1.1.1.13  root      290: }
                    291: 
                    292: // 1文字出力
                    293: void
                    294: LunaPROMEmuDevice::Putc(uint ch)
                    295: {
                    296:        uint px = origin_px + cursor_x * 12;
                    297:        uint py = origin_py + cursor_y * 24;
                    298: 
1.1.1.15! root      299:        if (cursor_on) {
        !           300:                // カーソル位置の反転を元に戻す
        !           301:                lunafb->EmuPutc(px, py, ' ', ROP::INV2);
        !           302:        }
        !           303: 
        !           304:        // いくつかの制御コードを勝手に使う。
        !           305:        switch (ch) {
        !           306:         case 0x0f:     // SI
        !           307:                bold = true;
        !           308:                break;
        !           309:         case 0x0e:     // SO
        !           310:                bold = false;
        !           311:                break;
        !           312: 
        !           313:         case 0x10:
        !           314:         case 0x11:
        !           315:         case 0x12:
        !           316:         case 0x13:
        !           317:                // カラーコード変更
        !           318:                lunafb->SetBMSEL(ch - 0x10);
        !           319:                break;
        !           320: 
        !           321:         case CR:
        !           322:                break;
1.1.1.13  root      323: 
1.1.1.15! root      324:         case LF:
        !           325:         put_LF:
1.1.1.13  root      326:                cursor_x = 0;
                    327:                if (cursor_y < screen_h - 1) {
                    328:                        cursor_y++;
                    329:                } else {
                    330:                        // 上スクロールして..
1.1.1.14  root      331:                        lunafb->EmuScrollY(origin_py, origin_py + 24, (screen_h - 1) * 24);
1.1.1.13  root      332:                        // 最終行を消す
1.1.1.14  root      333:                        lunafb->EmuFill(0, py, 1280, 24, 0);
1.1.1.13  root      334:                }
1.1.1.15! root      335:                break;
        !           336: 
        !           337:         case LEFT:
1.1.1.13  root      338:                if (cursor_x > 0) {
                    339:                        cursor_x--;
                    340:                } else {
                    341:                        cursor_y--;
                    342:                        cursor_x = screen_w - 1;
                    343:                }
1.1.1.15! root      344:                break;
        !           345: 
        !           346:         case RIGHT:
1.1.1.13  root      347:                if (cursor_x < screen_w - 1) {
                    348:                        cursor_x++;
                    349:                } else {
                    350:                        cursor_y++;
                    351:                        cursor_x = 0;
                    352:                }
1.1.1.15! root      353:                break;
        !           354: 
        !           355:         default:
        !           356:                if (ch < 0x80) {
1.1.1.14  root      357:                        lunafb->EmuPutc(px, py, ch);
1.1.1.15! root      358:                        if (bold) {
        !           359:                                for (int i = 1; i < 2; i++) {
        !           360:                                        lunafb->EmuPutc(px + i, py, ch, ROP::OR1);
        !           361:                                }
        !           362:                        }
1.1.1.13  root      363:                } else {
1.1.1.15! root      364:                        lunafb->EmuPutc(px, py, ' ');
        !           365:                        lunafb->EmuPutc(px, py + 10, ch);
        !           366:                        if (bold) {
        !           367:                                for (int i = 1; i < 2; i++) {
        !           368:                                        lunafb->EmuPutc(px + i, py + 10, ch, ROP::OR1);
        !           369:                                }
        !           370:                        }
        !           371:                }
        !           372:                cursor_x++;
        !           373:                if (cursor_x >= screen_w) {
1.1.1.13  root      374:                        goto put_LF;
                    375:                }
1.1.1.15! root      376:                break;
1.1.1.13  root      377:        }
                    378: 
1.1.1.15! root      379:        if (cursor_on) {
        !           380:                // カーソル位置を再計算して描画 (文字を反転)
        !           381:                px = origin_px + cursor_x * 12;
        !           382:                py = origin_py + cursor_y * 24;
        !           383:                lunafb->EmuPutc(px, py, ' ', ROP::INV2);
        !           384:        }
1.1.1.13  root      385: }
                    386: 
                    387: // 文字列 s を出力
                    388: void
                    389: LunaPROMEmuDevice::Print(const std::string& s)
                    390: {
                    391:        for (auto *p = s.c_str(); *p; p++) {
                    392:                Putc(*p);
                    393:        }
                    394: }
                    395: 
                    396: // 文字列 fmt... を出力
                    397: void
                    398: LunaPROMEmuDevice::Print(const char *fmt, ...)
                    399: {
                    400:        char buf[1024];
                    401:        va_list ap;
                    402: 
                    403:        va_start(ap, fmt);
                    404:        vsnprintf(buf, sizeof(buf), fmt, ap);
                    405:        va_end(ap);
                    406: 
                    407:        for (char *p = buf; *p; p++) {
                    408:                Putc(*p);
                    409:        }
1.1       root      410: }
                    411: 
1.1.1.7   root      412: // ROM 処理のクローズ
                    413: void
1.1.1.2   root      414: LunaPROMEmuDevice::ROM_Close()
1.1       root      415: {
1.1.1.11  root      416:        // SIO をリセットしておく。
                    417:        // SIO のバッファにデータが残っていると、NetBSD のブートローダが
                    418:        // 起動してこないようだ。リセットして RXEN を落としておけば大丈夫ぽい。
1.1.1.14  root      419:        sio->ResetHard(false);
1.1.1.15! root      420: 
        !           421:        // 実行ファイルにジャンプ後、NMI でプロンプトにもう一度戻ってこれるので
        !           422:        // その時のためにエントリポイント等も初期化しておく。
        !           423:        entrypoint = -1;
        !           424:        execute = false;
1.1       root      425: }
                    426: 
1.1.1.2   root      427: // ROM プロンプトのキー入力。
1.1.1.7   root      428: // ゲストコードの割り込みハンドラから呼ばれて、キー入力で行を構成し、
                    429: // あるいは行が完成すればコマンドを実行する。
                    430: // 実行結果により画面を更新したりメンバ変数を更新する。
                    431: void
1.1.1.2   root      432: LunaPROMEmuDevice::ROM_Keyin()
1.1       root      433: {
1.1.1.14  root      434:        int asciicode = Getc();
                    435: 
1.1.1.15! root      436:        if (cursor_on && asciicode != -1) {
1.1.1.14  root      437:                ProcessChar(asciicode);
                    438:        }
                    439: }
                    440: 
                    441: // キー入力。
                    442: // 押されているキーの ASCII コードを返す。
                    443: // キー入力が無いときは -1 を返す。
                    444: int
                    445: LunaPROMEmuDevice::Getc()
                    446: {
                    447:        // コントロールレジスタポインタを確実に 0 にするため読み捨てる
                    448:        sio->Read(3);
                    449: 
                    450:        uint8 sr0 = sio->Read(3);
                    451:        if ((sr0 & MPSCC::SR0_RXAVAIL) == 0) {
                    452:                return -1;
                    453:        }
                    454: 
                    455:        uint32 lunakey = sio->Read(2);
1.1       root      456: 
1.1.1.3   root      457:        // マウス入力の 2, 3バイト目は無視
                    458:        if (mousecnt > 0) {
                    459:                mousecnt--;
1.1.1.14  root      460:                return -1;
1.1.1.3   root      461:        }
                    462: 
1.1.1.2   root      463:        // SHIFT キーだけ状態を持つので先に処理
                    464:        if (lunakey == 0x0c || lunakey == 0x0d) {       // 左右SHIFT押下
                    465:                is_shift = true;
1.1.1.14  root      466:                return -1;
1.1.1.2   root      467:        }
                    468:        if (lunakey == 0x8c || lunakey == 0x8d) {       // 左右SHIFT開放
1.1       root      469:                is_shift = false;
1.1.1.14  root      470:                return -1;
1.1.1.2   root      471:        }
1.1.1.3   root      472:        // マウスデータの1バイト目なら、後続2バイトをスキップ
                    473:        if ((lunakey & 0xf8) == 0x80) {
                    474:                mousecnt = 2;
1.1.1.14  root      475:                return -1;
1.1.1.3   root      476:        }
                    477:        // キー開放は無視してよい
1.1.1.2   root      478:        if ((lunakey & 0x80)) {
1.1.1.14  root      479:                return -1;
1.1.1.2   root      480:        }
1.1       root      481: 
1.1.1.9   root      482:        // キーコードから文字を取得
1.1.1.14  root      483:        int asciicode;
1.1.1.9   root      484:        if (is_shift) {
                    485:                asciicode = lunakey2shifttable[lunakey];
                    486:        } else {
                    487:                asciicode = lunakey2asciitable[lunakey];
                    488:        }
1.1.1.14  root      489:        if (asciicode == 0) {
                    490:                return -1;
1.1.1.9   root      491:        }
1.1.1.14  root      492: 
                    493:        return asciicode;
1.1.1.9   root      494: }
                    495: 
                    496: // キー入力ハンドラ (キー入力割り込みによって呼ばれる)。
                    497: // 引数 asciicode は概ね ASCII コード (ただし 0x1c..0x1f が上下左右)。
                    498: void
1.1.1.14  root      499: LunaPROMEmuDevice::ProcessChar(char asciicode)
1.1.1.9   root      500: {
1.1.1.14  root      501:        // LUNA-I の場合、
1.1.1.9   root      502:        // 実機 PROM にはカーソル左右移動の機能はなく、カーソルは常に行末にいる。
                    503:        // そのためかどうか Delete も BackSpace と同じく1文字前を消す動作をして
                    504:        // いる。カーソル位置に文字はないので、Delete をそうするのはまあ分からん
                    505:        // でもない。
                    506:        // 一方、エミュレーション ROM では、カーソルの左右移動をサポートしてみた
                    507:        // ため Delete を「カーソル位置の文字を消す」にすることは出来るが、それは
                    508:        // それで実機と乖離が広がるので、どうしたもんか。
                    509: 
                    510:        switch (asciicode) {
                    511:         case BS:
                    512:                if (inputbuf.empty() == false && inputpos != 0) {
                    513:                        inputbuf.erase(--inputpos, 1);
1.1.1.13  root      514:                        Putc(LEFT);
                    515:                        for (int i = inputpos; i < inputbuf.size(); i++) {
                    516:                                Putc(inputbuf[i]);
                    517:                        }
                    518:                        Putc(' ');
                    519:                        for (int i = 0; i < 1 + inputbuf.size() - inputpos; i++) {
                    520:                                Putc(LEFT);
                    521:                        }
1.1       root      522:                }
1.1.1.2   root      523:                break;
1.1.1.9   root      524: 
                    525:         case LF:
1.1.1.2   root      526:                // 改行
1.1.1.13  root      527:                Putc(asciicode);
                    528:                prompt_y = cursor_y;
1.1.1.9   root      529:                // コマンド実行
1.1.1.7   root      530:                Command();
1.1.1.9   root      531:                // プロンプトを更新
                    532:                ClearPrompt();
1.1.1.2   root      533:                break;
1.1.1.9   root      534: 
                    535:         case LEFT:
1.1.1.2   root      536:                if (inputpos > 0) {
                    537:                        inputpos--;
1.1.1.13  root      538:                        Putc(LEFT);
1.1       root      539:                }
1.1.1.2   root      540:                break;
1.1.1.9   root      541:         case RIGHT:
1.1.1.2   root      542:                if (inputpos < inputbuf.length()) {
1.1       root      543:                        inputpos++;
1.1.1.13  root      544:                        Putc(RIGHT);
1.1       root      545:                }
                    546:                break;
1.1.1.9   root      547: 
                    548:         case UP:
                    549:         case DOWN:
                    550:         case 0:        // キー割り当てなし、これは来ないはずだが一応
                    551:                return;
                    552: 
                    553:         default:       // 通常文字のはず
1.1.1.2   root      554:                inputbuf.insert(inputbuf.begin() + inputpos, asciicode);
1.1.1.13  root      555:                for (int i = inputpos; i < inputbuf.size(); i++) {
                    556:                        Putc(inputbuf[i]);
                    557:                }
                    558:                for (int i = 0; i < inputbuf.size() - inputpos - 1; i++) {
                    559:                        Putc(LEFT);
                    560:                }
1.1.1.2   root      561:                inputpos++;
                    562:                break;
1.1       root      563:        }
1.1.1.2   root      564: }
1.1       root      565: 
1.1.1.9   root      566: // 入力バッファを初期化する。
                    567: void
                    568: LunaPROMEmuDevice::ClearPrompt()
                    569: {
1.1.1.13  root      570:        prompt_y = cursor_y;
1.1.1.9   root      571:        // 入力行をクリア
                    572:        inputbuf.clear();
                    573:        inputpos = 0;
                    574: 
1.1.1.13  root      575:        Print(prompt);
1.1.1.9   root      576: }
                    577: 
                    578: // NVRAM のチェックサムを返す
                    579: uint8
                    580: LunaPROMEmuDevice::CalcNVRAMCsum() const
                    581: {
                    582:        uint8 eor = 0;
                    583:        for (uint32 addr = 0x20; addr < 0x560; addr++) {
                    584:                eor ^= nvram->Peek(addr);
                    585:        }
                    586:        return eor;
                    587: }
                    588: 
                    589: // NVRAM のチェックサムを計算して書き込む
                    590: void
                    591: LunaPROMEmuDevice::WriteNVRAMCsum()
                    592: {
                    593:        uint8 eor = CalcNVRAMCsum();
                    594: 
                    595:        nvram->Write(0x001c, eor);
                    596:        nvram->Write(0x001d, eor);
                    597:        nvram->Write(0x001e, eor);
                    598: }
                    599: 
                    600: // NVRAM のマジックとチェックサムを照合する
                    601: bool
                    602: LunaPROMEmuDevice::VerifyNVRAM() const
                    603: {
                    604:        if (nvram->PeekString(0x0004) != "<nv>") {
                    605:                return false;
                    606:        }
                    607: 
                    608:        uint8 eor = CalcNVRAMCsum();
                    609:        for (uint32 addr = 0x1c; addr < 0x1f; addr++) {
                    610:                if (nvram->Peek(addr) != eor) {
                    611:                        return false;
                    612:                }
                    613:        }
                    614:        return true;
1.1       root      615: }
                    616: 
1.1.1.15! root      617: static const uint8 __unused test0[] = {
        !           618:        0x12, 0x0f, 0x4e, 0x4f, 0x4e, 0x4f, 0x0e, 0x1e, 0x13, 0x00,
        !           619: };
        !           620: static const uint8 __unused test1[] = {
        !           621:        0xcd, 0xd5, 0xcc, 0xd4, 0xc9, 0xad, 0xd2, 0xc9, 0xd3, 0xc3,
        !           622:        0x20, 0xd7, 0xcf, 0xd2, 0xcb, 0xd3, 0xd4, 0xc1, 0xd4, 0xc9,
        !           623:        0xcf, 0xce, 0x20, 0x11, 0x0f, 0x4c, 0x55, 0x4e, 0x41, 0x2d,
        !           624:        0x38, 0x38, 0x4b, 0x00, 0xaa, 0x12, 0x43, 0x58, 0xc2, 0x00,
        !           625: };
        !           626: static const uint8 __unused test2[] = {
        !           627:        0xc8, 0xcf, 0xcc, 0xcf, 0xce, 0xc9, 0xc3, 0x20, 0xd7, 0xcf,
        !           628:        0xd2, 0xcb, 0xd3, 0xd4, 0xc1, 0xd4, 0xc9, 0xcf, 0xce, 0x20,
        !           629:        0x11, 0x0f, 0x4c, 0x55, 0x4e, 0x41, 0x00, 0x21, 0xd8, 0x67,
        !           630: };
        !           631: static const uint8 __unused test3[] = {
        !           632:        0x0e, 0x1e, 0x13, 0xd3, 0xc5, 0xd2, 0xc9, 0xc5, 0xd3, 0x0a,
        !           633:        0x00, 0x0f, 0xd0, 0x4f, 0x7e, 0x40, 0x41, 0xcc, 0xdf, 0x09,
        !           634: };
        !           635: 
1.1.1.10  root      636: // -X オプションで指定されたホストファイルをロードする。
1.1       root      637: // ロードできればエントリポイントを返す。
1.1.1.15! root      638: // 失敗ならエラーメッセージを errmsg にセットして (uint32)-1 を返す。
1.1.1.10  root      639: // exec_file が指定されている時に呼ぶこと。
1.1       root      640: uint32
                    641: LunaPROMEmuDevice::LoadHostFile()
                    642: {
1.1.1.10  root      643:        assert(gMainApp.exec_file);
1.1       root      644: 
1.1.1.14  root      645:        LoadInfo info(gMainApp.exec_file);
1.1.1.15! root      646:        if (mainram->LoadExec(&info)) {
1.1.1.14  root      647:                return info.entry;
1.1       root      648:        } else {
1.1.1.15! root      649:                errmsg = "Couldn't load specified host program.";
        !           650:                return -1;
1.1       root      651:        }
                    652: }
                    653: 
1.1.1.7   root      654: // bootinfo に従ってゲストから起動先をロードする。
1.1.1.15! root      655: // ロードできればエントリポイントを返す。
        !           656: // 失敗ならエラーメッセージを errmsg にセットして (uint32)-1 を返す。
1.1       root      657: uint32
1.1.1.7   root      658: LunaPROMEmuDevice::LoadGuestFile(const bootinfo_t& bootinfo)
1.1       root      659: {
1.1.1.7   root      660:        const int& dkpart = bootinfo.dkpart;
                    661:        const int& dkunit = bootinfo.dkunit;
                    662:        const std::string& dkfile = bootinfo.dkfile;
1.1       root      663: 
                    664:        // ユニット (今は SCSI ID=6 決め打ち)
                    665:        int id = 6;
1.1.1.14  root      666:        SCSITarget *target = spc->GetTarget(id);
1.1       root      667:        if (target == NULL) {
                    668:                errmsg = "No bootable disks";
                    669:                putmsg(0, "%s", errmsg.c_str());
1.1.1.14  root      670:                return -1;
1.1       root      671:        }
1.1.1.3   root      672:        if (target->GetDevType() != SCSI::DevType::HD) {
1.1       root      673:                errmsg = "No bootable disks";
                    674:                putmsg(0, "%s", errmsg.c_str());
1.1.1.14  root      675:                return -1;
1.1       root      676:        }
                    677: 
1.1.1.10  root      678:        SCSIDisk *hd = dynamic_cast<SCSIDisk*>(target);
1.1       root      679:        putmsg(2, "%s SCSIHD[%d] found", __func__, id);
                    680: 
                    681:        // +0 セクタ目(512byte)に Sun disklabel
                    682:        scd_dk_label dk;
1.1.1.10  root      683:        if (hd->Peek(&dk, 0, sizeof(dk)) == false) {
1.1       root      684:                putmsg(0, "SCSIHD[%d] ReadSector failed", id);
                    685:                errmsg = string_format("dk%d Read disklabel failed.", dkunit);
1.1.1.14  root      686:                return -1;
1.1       root      687:        }
                    688: 
                    689:        // +$1fc の MAGIC をチェック
                    690:        uint32 magic = be16toh(dk.magic);
                    691:        if (magic != scd_dk_label::DKL_MAGIC) {
                    692:                putmsg(0, "SCSIHD[%d] Bad magic 0x%04x (!= 0x%x)",
                    693:                        id, magic, scd_dk_label::DKL_MAGIC);
                    694:                errmsg = string_format("dk%d Bad disklabel magic.", dkunit);
1.1.1.14  root      695:                return -1;
1.1       root      696:        }
                    697: 
                    698:        // チェックサム照合は手抜きで省略
                    699: 
                    700:        // 指定パーティションの開始位置とサイズ
                    701:        if (loglevel >= 2) {
                    702:                // デバッグ用に全部表示
                    703:                for (int i = 0; i < 8; i++) {
1.1.1.7   root      704:                        putmsgn("%s partition %c: { start=%8u size=%8u }", __func__,
1.1       root      705:                                'a' + i,
                    706:                                be32toh(dk.map[i].blkno),
                    707:                                be32toh(dk.map[i].nblk));
                    708:                }
                    709:        }
                    710:        uint32 part_start = be32toh(dk.map[dkpart].blkno);
                    711:        uint32 part_size  = be32toh(dk.map[dkpart].nblk);
                    712:        putmsg(1, "%s partition=%c, start=%u size=%u", __func__,
                    713:                dkpart + 'a', part_start, part_size);
                    714: 
                    715:        // ファイルシステムをオープン (マウントっぽいイメージ)
                    716:        Filesys fsys(this);
1.1.1.7   root      717:        if (fsys.Mount(hd, part_start, part_size) == false) {
                    718:                errmsg = string_format("dk%d,%c Open ffs failed: %s",
                    719:                        dkunit, dkpart + 'a', fsys.errstr.c_str());
                    720:                putmsg(0, "%s: %s", __func__, errmsg.c_str());
1.1.1.14  root      721:                return -1;
1.1       root      722:        }
                    723: 
1.1.1.7   root      724:        // ファイルを探してオープンする
                    725:        inodefile f(this);
                    726:        if (fsys.OpenFile(f, dkfile) == false) {
                    727:                errmsg = string_format("dk%d,%c,%s open failed: %s",
                    728:                        dkunit, dkpart + 'a', dkfile.c_str(), fsys.errstr.c_str());
                    729:                putmsg(0, "%s: %s", __func__, errmsg.c_str());
1.1.1.14  root      730:                return -1;
1.1       root      731:        }
1.1.1.7   root      732: 
1.1       root      733:        // ファイル本体を読み込み
1.1.1.7   root      734:        fsys.ReadData(f);
1.1       root      735: 
                    736:        // ロード
                    737:        std::string name = string_format("SCSIHD %d,%c:%s",
1.1.1.7   root      738:                id, dkpart + 'a', dkfile.c_str());
1.1.1.14  root      739:        LoadInfo info(name.c_str(), f.data.data(), f.data.size());
1.1.1.15! root      740:        if (mainram->LoadExec(&info) == false) {
1.1.1.14  root      741:                errmsg = string_format("dk%d,%c,%s load failed",
                    742:                        dkunit, dkpart + 'a', dkfile.c_str());
                    743:                putmsg(0, "%s: %s", __func__, errmsg.c_str());
                    744:                return -1;
                    745:        }
                    746: 
                    747:        if (info.entry == -1) {
1.1.1.7   root      748:                errmsg = string_format("dk%d,%c,%s not executable",
                    749:                        dkunit, dkpart + 'a', dkfile.c_str());
1.1.1.14  root      750:                putmsg(0, "%s: %s", __func__, errmsg.c_str());
                    751:                return -1;
1.1       root      752:        }
                    753: 
1.1.1.14  root      754:        return info.entry;
1.1       root      755: }
                    756: 
1.1.1.15! root      757: void
        !           758: LunaPROMEmuDevice::ROM_AP1()
        !           759: {
        !           760:        char buf[100];
        !           761:        int n;
        !           762: 
        !           763:        cursor_on = false;
        !           764: 
        !           765:        static uint8 ap1pal[] = {
        !           766:                0x00, 0x00, 0x00,
        !           767:                0x00, 0xf8, 0xf8,
        !           768:                0xf8, 0xf8, 0x00,
        !           769:                0xf8, 0xf8, 0xf8,
        !           770:        };
        !           771:        bt45x->Write(0, 0);
        !           772:        for (int i = 0; i < countof(ap1pal); i++) {
        !           773:                bt45x->Write(1, ap1pal[i]);
        !           774:        }
        !           775: 
        !           776:        Print(std::string((const char *)test0));
        !           777:        if (gMainApp.IsLUNA88K()) {
        !           778:                Print(std::string((const char *)test1));
        !           779:        } else {
        !           780:                Print(std::string((const char *)test2));
        !           781:        }
        !           782:        Print(std::string((const char *)test3));
        !           783: 
        !           784:        n = strlcpy(buf, (const char *)&Builtin::IPLROM30[0x111e3], sizeof(buf));
        !           785:        snprintf(buf + n, sizeof(buf) - n, "%d.%d.%d %s",
        !           786:                NONO_MAJOR_VER, NONO_MINOR_VER, NONO_PATCH_VER, NONO_DATE);
        !           787:        for (int i = 0; buf[i]; i++) {
        !           788:                if (buf[i] == '/')
        !           789:                        buf[i] = '.';
        !           790:        }
        !           791:        Print("%s\n", buf);
        !           792: 
        !           793:        memcpy(buf, &Builtin::IPLROM30[0x111f5], 0x28);
        !           794:        memcpy(buf + 0x1e, mpu->GetMPUName(), 7);
        !           795:        n = 0x27;
        !           796:        n += snprintf(buf + n, sizeof(buf) - n, "%4.1f",
        !           797:                (double)mpu->GetClockSpeed() / 1000);
        !           798:        strlcpy(buf + n, (const char *)&Builtin::IPLROM30[0x1121f],
        !           799:                sizeof(buf) - n);
        !           800:        Print(std::string(buf));
        !           801: 
        !           802:        strlcpy(buf, (const char *)&Builtin::IPLROM30[0x11226], sizeof(buf));
        !           803:        if (gMainApp.Has(VMCap::M88K)) {
        !           804:                memcpy(buf + 0x1e, mpu->GetMPUName(), 7);
        !           805:                memcpy(buf + 0x25, &Builtin::IPLROM30[0x11251], 3);
        !           806:        }
        !           807:        Print(std::string(buf));
        !           808: 
        !           809:        strlcpy(buf, (const char *)&Builtin::IPLROM30[0x11254], sizeof(buf));
        !           810:        buf[0x0c] = 'e';
        !           811:        if (gMainApp.Has(VMCap::M88K)) {
        !           812:                memcpy(buf + 0x1e, mpu->GetMPUName(), 7);
        !           813:                memcpy(buf + 0x25, &Builtin::IPLROM30[0x1127d], 3);
        !           814:                buf[0x22] = 0x32;
        !           815:        }
        !           816:        Print(std::string(buf));
        !           817: 
        !           818:        strlcpy(buf, (const char *)&Builtin::IPLROM30[0x11280], sizeof(buf));
        !           819:        n = 0x1e;
        !           820:        n += snprintf(buf + n, sizeof(buf) - n, "%d", mainram->GetSizeMB());
        !           821:        strlcpy(buf + n, (const char *)&Builtin::IPLROM30[0x1129f],
        !           822:                sizeof(buf) - n);
        !           823:        Print(std::string(buf));
        !           824: }
        !           825: 
        !           826: void
        !           827: LunaPROMEmuDevice::ROM_AP2()
        !           828: {
        !           829:        InitPalette();
        !           830:        InitScreen();
        !           831: }
        !           832: 
1.1.1.7   root      833: // キーコードから文字への変換
                    834: /*static*/ const uint8
                    835: LunaPROMEmuDevice::lunakey2asciitable[] = {
1.1.1.9   root      836:         0,   0,   0,   0,   0,   0,   0,   0,
                    837:         0,   0,   0,   0,   0,   0,   0,   0,
                    838:         0,  BS,  LF,   0, ' ',   0,   0,   0,
                    839:         0,   0,   0,   0,  UP,LEFT,RIGHT,DOWN,
1.1.1.7   root      840:         0,   0,  '1', '2', '3', '4', '5', '6',
                    841:        '7', '8', '9', '0', '-', '^', '\\', 0,
                    842:         0,   0,  'q', 'w', 'e', 'r', 't', 'y',
                    843:        'u', 'i', 'o', 'p', '@', '[',  0,   0,
                    844:         0,   0,  'a', 's', 'd', 'f', 'g', 'h',
                    845:        'j', 'k', 'l', ';', ':', ']',  0,   0,
                    846:         0,   0,  'z', 'x', 'c', 'v', 'b', 'n',
                    847:        'm', ',', '.', '/',  0,   0,   0,   0,
1.1.1.13  root      848:         0,  '+', '-', '7', '8', '9', '4', '5',
                    849:        '6', '1', '2', '3', '0', '.', LF,   0,
                    850:         0,   0,   0,   0,   0,   0,   0,   0,
                    851:         0,   0,   0,   0,  '*', '/', '=', ',',
1.1.1.7   root      852: };
                    853: /*static*/ const uint8
                    854: LunaPROMEmuDevice::lunakey2shifttable[] = {
1.1.1.9   root      855:         0,   0,   0,   0,   0,   0,   0,   0,
                    856:         0,   0,   0,   0,   0,   0,   0,   0,
                    857:         0,  BS,  LF,   0, ' ',   0,   0,   0,
                    858:         0,   0,   0,   0,  UP,LEFT,RIGHT,DOWN,
                    859:         0,   0,  '!', '\"','#', '$', '%', '&',
                    860:        '\'','(', ')', ' ', '=', '~', '|',  0,          // XXX SHIFT+'0'は?
1.1.1.7   root      861:         0,   0,  'Q', 'W', 'E', 'R', 'T', 'Y',
                    862:        'U', 'I', 'O', 'P', '`', '{',  0,   0,
                    863:         0,   0,  'A', 'S', 'D', 'F', 'G', 'H',
                    864:        'J', 'K', 'L', '+', '*', '}',  0,   0,
                    865:         0,   0,  'Z', 'X', 'C', 'V', 'B', 'N',
                    866:        'M', '<', '>', '?', '_',  0,   0,   0,
1.1.1.13  root      867:         0,  '+', '-', '7', '8', '9', '4', '5',
                    868:        '6', '1', '2', '3', '0', '.', LF,   0,
                    869:         0,   0,   0,   0,   0,   0,   0,   0,
                    870:         0,   0,   0,   0,  '*', '/', '=', ',',
1.1.1.7   root      871: };

unix.superglobalmegacorp.com

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