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

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: //    |           |
                     24: //    |           +-- Luna1PROMEmuDevice   (LUNA1 の PROM エミュレーション)
                     25: //    |           +-- Luna88kPROMEmuDevice (LUNA88K の PROM エミュレーション)
                     26: //    |
                     27: //    +-- PROM0Device   (LUNA* のブートページ切り替え用プロキシ)
                     28: //    +-- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ)
1.1.1.2   root       29: 
                     30: #include "romemu_luna.h"
1.1       root       31: #include "bt454.h"
1.1.1.9   root       32: #include "lunafb.h"
1.1       root       33: #include "mainapp.h"
                     34: #include "mk48t02.h"
1.1.1.13! root       35: #include "mpu.h"
        !            36: #include "prom.h"
1.1       root       37: #include "ram.h"
                     38: #include "sio.h"
                     39: #include "spc.h"
1.1.1.7   root       40: #include "ufs.h"
1.1       root       41: 
                     42: // コンストラクタ
                     43: LunaPROMEmuDevice::LunaPROMEmuDevice()
1.1.1.9   root       44:        : inherited("PROM")
1.1       root       45: {
1.1.1.10  root       46:        // LUNA では ROM への書き込みは何も起きない
                     47:        write_op = 0;
1.1       root       48: }
                     49: 
                     50: // デストラクタ
                     51: LunaPROMEmuDevice::~LunaPROMEmuDevice()
                     52: {
1.1.1.13! root       53:        gPROM = NULL;
1.1       root       54: }
                     55: 
                     56: bool
                     57: LunaPROMEmuDevice::Init()
                     58: {
                     59:        // 都度都度 dynamic_cast は面倒なので、ここで一度代入しとく
1.1.1.13! root       60:        nvram = dynamic_cast<MK48T02Device*>(gRTC);
1.1       root       61: 
                     62:        return true;
                     63: }
                     64: 
1.1.1.2   root       65: uint64
1.1       root       66: LunaPROMEmuDevice::Read32(uint32 addr)
                     67: {
1.1.1.10  root       68:        // ROM からのロングワードアクセスでだけ謎の I/O 空間が見える。
                     69:        // addr をマスクする前に評価すること。
1.1.1.9   root       70:        if ((gMPU->GetPaddr() & 0xff000000) == baseaddr) {
                     71:                switch (addr) {
                     72:                 case ROMIO_INIT:
1.1.1.2   root       73:                        return ROM_Init();
1.1       root       74: 
1.1.1.9   root       75:                 case ROMIO_KEYIN:
1.1.1.7   root       76:                        ROM_Keyin();
                     77:                        return 0;
1.1       root       78: 
1.1.1.9   root       79:                 case ROMIO_CLOSE:
1.1.1.7   root       80:                        ROM_Close();
                     81:                        return 0;
1.1       root       82: 
1.1.1.9   root       83:                 case ROMIO_ENTRY:
1.1.1.7   root       84:                        return ROM_Entry();
1.1.1.6   root       85: 
1.1       root       86:                 default:
                     87:                        break;
                     88:                }
                     89:        }
1.1.1.2   root       90: 
1.1.1.10  root       91:        return inherited::Read32(addr);
1.1       root       92: }
                     93: 
1.1.1.7   root       94: // デバイスの初期化の共通部分。(継承クラスの ROM_Init() から呼ぶ)
                     95: void
                     96: LunaPROMEmuDevice::InitDevice()
1.1       root       97: {
                     98:        // 初期パレット
1.1.1.4   root       99:        // 偶数番は白(R/G/B=15/15/15)、奇数番は黒(0/0/0)。
                    100:        uint8 val = 0xf0;
1.1.1.7   root      101:        gBT454->Write(0, 0);    // select palette
1.1.1.4   root      102:        for (int i = 0; i < 16; i++) {
1.1.1.7   root      103:                gBT454->Write(1, val);  // R
                    104:                gBT454->Write(1, val);  // G
                    105:                gBT454->Write(1, val);  // B
1.1.1.4   root      106:                val ^= 0xf0;
                    107:        }
1.1       root      108: 
                    109:        // SCSI
                    110:        // BDID の書き込みによってホストデバイスがバスにアタッチされる構造なので。
1.1.1.7   root      111:        gSPC->Write(SPC::BDID, 7);
1.1       root      112: 
1.1.1.7   root      113:        // キーボード(chB)を初期化
                    114:        gSIO->Write(3, 0x01);           // CR1
                    115:        gSIO->Write(3, 0x10);           //    RX Int(all char)
                    116:        gSIO->Write(3, 0x04);           // CR4
                    117:        gSIO->Write(3, 0x44);           //    Stop 1bit
1.1.1.13! root      118:        gSIO->Write(3, 0x03);           // CR3
        !           119:        gSIO->Write(3, 0xc1);           //    RX Enable, 8bit
1.1.1.7   root      120:        gSIO->Write(3, 0x05);           // CR5
                    121:        gSIO->Write(3, 0x68);           //    TX Enable, 8bit
1.1.1.12  root      122: 
                    123:        // LED を(明示的に)オフ、マウスサンプリングをオフ
                    124:        gSIO->Write(2, 0x00);
                    125:        gSIO->Write(2, 0x01);
                    126:        gSIO->Write(2, 0x20);
1.1.1.7   root      127: }
1.1.1.2   root      128: 
1.1.1.7   root      129: // スクリーンを初期化
                    130: void
1.1.1.13! root      131: LunaPROMEmuDevice::InitScreen()
1.1.1.7   root      132: {
1.1.1.13! root      133:        gLunafb->EmuInitScreen();
        !           134: 
        !           135:        screen_w = 80;
        !           136:        screen_h = 32;
        !           137:        cursor_x = 0;
        !           138:        cursor_y = 0;
        !           139: 
        !           140:        // 表示範囲はざっくりセンタリングする
        !           141:        origin_px = (1280 - screen_w * 12) / 2;
        !           142:        origin_py = (1024 - screen_h * 24) / 2;
        !           143:        // 横は 48ドット境界から始めておく。
        !           144:        // こうすると1(,2)文字目の24ビットが必ずワード境界から始まるため。
        !           145:        // 今となっては任意の場所から文字が描画できるようになったので揃える
        !           146:        // 必要はなくなったが、依然このほうがアクセス効率はいいので。
        !           147:        origin_px = (origin_px / 48) * 48;
        !           148: 
1.1.1.2   root      149:        inputbuf.clear();
                    150:        inputpos = 0;
                    151:        is_shift = false;
1.1.1.3   root      152:        mousecnt = 0;
1.1.1.13! root      153: }
1.1       root      154: 
1.1.1.13! root      155: // タイトルを出力
        !           156: void
        !           157: LunaPROMEmuDevice::PrintTitle(const char *machine_name)
        !           158: {
        !           159:        Print("NONO %d.%d.%d Emulated ROM Monitor for %s\n\n",
1.1.1.7   root      160:                NONO_MAJOR_VER, NONO_MINOR_VER, NONO_PATCH_VER, machine_name);
1.1.1.13! root      161: }
        !           162: 
        !           163: // 1文字出力
        !           164: void
        !           165: LunaPROMEmuDevice::Putc(uint ch)
        !           166: {
        !           167:        uint px = origin_px + cursor_x * 12;
        !           168:        uint py = origin_py + cursor_y * 24;
        !           169: 
        !           170:        // カーソル位置の反転を元に戻す
        !           171:        gLunafb->EmuPutc(px, py, ' ', ROP::INV2);
        !           172: 
        !           173:        if (ch == LF) {
        !           174:  put_LF:
        !           175:                cursor_x = 0;
        !           176:                if (cursor_y < screen_h - 1) {
        !           177:                        cursor_y++;
        !           178:                } else {
        !           179:                        // 上スクロールして..
        !           180:                        gLunafb->EmuScrollY(origin_py, origin_py + 24, (screen_h - 1) * 24);
        !           181:                        // 最終行を消す
        !           182:                        gLunafb->EmuFill(0, py, 1280, 24, 0);
        !           183:                }
        !           184:        } else if (ch == LEFT) {
        !           185:                if (cursor_x > 0) {
        !           186:                        cursor_x--;
        !           187:                } else {
        !           188:                        cursor_y--;
        !           189:                        cursor_x = screen_w - 1;
        !           190:                }
        !           191:        } else if (ch == RIGHT) {
        !           192:                if (cursor_x < screen_w - 1) {
        !           193:                        cursor_x++;
        !           194:                } else {
        !           195:                        cursor_y++;
        !           196:                        cursor_x = 0;
        !           197:                }
        !           198:        } else {
        !           199:                if (cursor_x < screen_w - 1) {
        !           200:                        gLunafb->EmuPutc(px, py, ch);
        !           201:                        cursor_x++;
        !           202:                } else {
        !           203:                        gLunafb->EmuPutc(px, py, ch);
        !           204:                        goto put_LF;
        !           205:                }
        !           206:        }
        !           207: 
        !           208:        // カーソル位置を再計算して描画 (文字を反転)
        !           209:        px = origin_px + cursor_x * 12;
        !           210:        py = origin_py + cursor_y * 24;
        !           211:        gLunafb->EmuPutc(px, py, ' ', ROP::INV2);
        !           212: }
        !           213: 
        !           214: // 文字列 s を出力
        !           215: void
        !           216: LunaPROMEmuDevice::Print(const std::string& s)
        !           217: {
        !           218:        for (auto *p = s.c_str(); *p; p++) {
        !           219:                Putc(*p);
        !           220:        }
        !           221: }
        !           222: 
        !           223: // 文字列 fmt... を出力
        !           224: void
        !           225: LunaPROMEmuDevice::Print(const char *fmt, ...)
        !           226: {
        !           227:        char buf[1024];
        !           228:        va_list ap;
        !           229: 
        !           230:        va_start(ap, fmt);
        !           231:        vsnprintf(buf, sizeof(buf), fmt, ap);
        !           232:        va_end(ap);
        !           233: 
        !           234:        for (char *p = buf; *p; p++) {
        !           235:                Putc(*p);
        !           236:        }
1.1       root      237: }
                    238: 
1.1.1.7   root      239: // ROM 処理のクローズ
                    240: void
1.1.1.2   root      241: LunaPROMEmuDevice::ROM_Close()
1.1       root      242: {
1.1.1.11  root      243:        // SIO をリセットしておく。
                    244:        // SIO のバッファにデータが残っていると、NetBSD のブートローダが
                    245:        // 起動してこないようだ。リセットして RXEN を落としておけば大丈夫ぽい。
1.1.1.13! root      246:        gSIO->ResetHard(false);
1.1       root      247: }
                    248: 
1.1.1.2   root      249: // ROM プロンプトのキー入力。
1.1.1.7   root      250: // ゲストコードの割り込みハンドラから呼ばれて、キー入力で行を構成し、
                    251: // あるいは行が完成すればコマンドを実行する。
                    252: // 実行結果により画面を更新したりメンバ変数を更新する。
                    253: void
1.1.1.2   root      254: LunaPROMEmuDevice::ROM_Keyin()
1.1       root      255: {
1.1.1.7   root      256:        uint32 lunakey = gSIO->Read(2);
1.1       root      257: 
1.1.1.3   root      258:        // マウス入力の 2, 3バイト目は無視
                    259:        if (mousecnt > 0) {
                    260:                mousecnt--;
1.1.1.7   root      261:                return;
1.1.1.3   root      262:        }
                    263: 
1.1.1.2   root      264:        // SHIFT キーだけ状態を持つので先に処理
                    265:        if (lunakey == 0x0c || lunakey == 0x0d) {       // 左右SHIFT押下
                    266:                is_shift = true;
1.1.1.7   root      267:                return;
1.1.1.2   root      268:        }
                    269:        if (lunakey == 0x8c || lunakey == 0x8d) {       // 左右SHIFT開放
1.1       root      270:                is_shift = false;
1.1.1.7   root      271:                return;
1.1.1.2   root      272:        }
1.1.1.3   root      273:        // マウスデータの1バイト目なら、後続2バイトをスキップ
                    274:        if ((lunakey & 0xf8) == 0x80) {
                    275:                mousecnt = 2;
1.1.1.7   root      276:                return;
1.1.1.3   root      277:        }
                    278:        // キー開放は無視してよい
1.1.1.2   root      279:        if ((lunakey & 0x80)) {
1.1.1.7   root      280:                return;
1.1.1.2   root      281:        }
1.1       root      282: 
1.1.1.9   root      283:        // キーコードから文字を取得
                    284:        char asciicode;
                    285:        if (is_shift) {
                    286:                asciicode = lunakey2shifttable[lunakey];
                    287:        } else {
                    288:                asciicode = lunakey2asciitable[lunakey];
                    289:        }
                    290:        if (asciicode != 0) {
                    291:                GetChar(asciicode);
                    292:        }
                    293: }
                    294: 
                    295: // キー入力ハンドラ (キー入力割り込みによって呼ばれる)。
                    296: // 引数 asciicode は概ね ASCII コード (ただし 0x1c..0x1f が上下左右)。
                    297: void
                    298: LunaPROMEmuDevice::GetChar(char asciicode)
                    299: {
                    300:        // LUNA1 の場合、
                    301:        // 実機 PROM にはカーソル左右移動の機能はなく、カーソルは常に行末にいる。
                    302:        // そのためかどうか Delete も BackSpace と同じく1文字前を消す動作をして
                    303:        // いる。カーソル位置に文字はないので、Delete をそうするのはまあ分からん
                    304:        // でもない。
                    305:        // 一方、エミュレーション ROM では、カーソルの左右移動をサポートしてみた
                    306:        // ため Delete を「カーソル位置の文字を消す」にすることは出来るが、それは
                    307:        // それで実機と乖離が広がるので、どうしたもんか。
                    308: 
                    309:        switch (asciicode) {
                    310:         case BS:
                    311:                if (inputbuf.empty() == false && inputpos != 0) {
                    312:                        inputbuf.erase(--inputpos, 1);
1.1.1.13! root      313:                        Putc(LEFT);
        !           314:                        for (int i = inputpos; i < inputbuf.size(); i++) {
        !           315:                                Putc(inputbuf[i]);
        !           316:                        }
        !           317:                        Putc(' ');
        !           318:                        for (int i = 0; i < 1 + inputbuf.size() - inputpos; i++) {
        !           319:                                Putc(LEFT);
        !           320:                        }
1.1       root      321:                }
1.1.1.2   root      322:                break;
1.1.1.9   root      323: 
                    324:         case LF:
1.1.1.2   root      325:                // 改行
1.1.1.13! root      326:                Putc(asciicode);
        !           327:                prompt_y = cursor_y;
1.1.1.9   root      328:                // コマンド実行
1.1.1.7   root      329:                Command();
1.1.1.9   root      330:                // プロンプトを更新
                    331:                ClearPrompt();
1.1.1.2   root      332:                break;
1.1.1.9   root      333: 
                    334:         case LEFT:
1.1.1.2   root      335:                if (inputpos > 0) {
                    336:                        inputpos--;
1.1.1.13! root      337:                        Putc(LEFT);
1.1       root      338:                }
1.1.1.2   root      339:                break;
1.1.1.9   root      340:         case RIGHT:
1.1.1.2   root      341:                if (inputpos < inputbuf.length()) {
1.1       root      342:                        inputpos++;
1.1.1.13! root      343:                        Putc(RIGHT);
1.1       root      344:                }
                    345:                break;
1.1.1.9   root      346: 
                    347:         case UP:
                    348:         case DOWN:
                    349:         case 0:        // キー割り当てなし、これは来ないはずだが一応
                    350:                return;
                    351: 
                    352:         default:       // 通常文字のはず
1.1.1.2   root      353:                inputbuf.insert(inputbuf.begin() + inputpos, asciicode);
1.1.1.13! root      354:                for (int i = inputpos; i < inputbuf.size(); i++) {
        !           355:                        Putc(inputbuf[i]);
        !           356:                }
        !           357:                for (int i = 0; i < inputbuf.size() - inputpos - 1; i++) {
        !           358:                        Putc(LEFT);
        !           359:                }
1.1.1.2   root      360:                inputpos++;
                    361:                break;
1.1       root      362:        }
1.1.1.2   root      363: }
1.1       root      364: 
1.1.1.9   root      365: // 入力バッファを初期化する。
                    366: void
                    367: LunaPROMEmuDevice::ClearPrompt()
                    368: {
1.1.1.13! root      369:        prompt_y = cursor_y;
1.1.1.9   root      370:        // 入力行をクリア
                    371:        inputbuf.clear();
                    372:        inputpos = 0;
                    373: 
1.1.1.13! root      374:        Print(prompt);
1.1.1.9   root      375: }
                    376: 
                    377: // NVRAM のチェックサムを返す
                    378: uint8
                    379: LunaPROMEmuDevice::CalcNVRAMCsum() const
                    380: {
                    381:        uint8 eor = 0;
                    382:        for (uint32 addr = 0x20; addr < 0x560; addr++) {
                    383:                eor ^= nvram->Peek(addr);
                    384:        }
                    385:        return eor;
                    386: }
                    387: 
                    388: // NVRAM のチェックサムを計算して書き込む
                    389: void
                    390: LunaPROMEmuDevice::WriteNVRAMCsum()
                    391: {
                    392:        uint8 eor = CalcNVRAMCsum();
                    393: 
                    394:        nvram->Write(0x001c, eor);
                    395:        nvram->Write(0x001d, eor);
                    396:        nvram->Write(0x001e, eor);
                    397: }
                    398: 
                    399: // NVRAM のマジックとチェックサムを照合する
                    400: bool
                    401: LunaPROMEmuDevice::VerifyNVRAM() const
                    402: {
                    403:        if (nvram->PeekString(0x0004) != "<nv>") {
                    404:                return false;
                    405:        }
                    406: 
                    407:        uint8 eor = CalcNVRAMCsum();
                    408:        for (uint32 addr = 0x1c; addr < 0x1f; addr++) {
                    409:                if (nvram->Peek(addr) != eor) {
                    410:                        return false;
                    411:                }
                    412:        }
                    413:        return true;
1.1       root      414: }
                    415: 
1.1.1.10  root      416: // -X オプションで指定されたホストファイルをロードする。
1.1       root      417: // ロードできればエントリポイントを返す。
1.1.1.10  root      418: // exec_file が指定されている時に呼ぶこと。
1.1       root      419: uint32
                    420: LunaPROMEmuDevice::LoadHostFile()
                    421: {
1.1.1.10  root      422:        assert(gMainApp.exec_file);
1.1       root      423: 
1.1.1.10  root      424:        uint32 entry = gRAM->LoadFile(gMainApp.exec_file);
1.1       root      425:        if (entry) {
1.1.1.13! root      426:                Print("Host program loaded.  Entry point = $%08x\n", entry);
1.1       root      427:        } else {
1.1.1.13! root      428:                Print("** Couldn't load specified host program.\n");
1.1       root      429:        }
                    430:        return entry;
                    431: }
                    432: 
1.1.1.7   root      433: // bootinfo に従ってゲストから起動先をロードする。
1.1       root      434: // 成功すればエントリポイントを返す。
                    435: // 失敗ならをエラーメッセージを errmsg にセットして 0 を返す。
                    436: uint32
1.1.1.7   root      437: LunaPROMEmuDevice::LoadGuestFile(const bootinfo_t& bootinfo)
1.1       root      438: {
1.1.1.7   root      439:        const int& dkpart = bootinfo.dkpart;
                    440:        const int& dkunit = bootinfo.dkunit;
                    441:        const std::string& dkfile = bootinfo.dkfile;
1.1       root      442: 
                    443:        // ユニット (今は SCSI ID=6 決め打ち)
                    444:        int id = 6;
                    445:        SCSITarget *target = gSPC->GetTarget(id);
                    446:        if (target == NULL) {
                    447:                errmsg = "No bootable disks";
                    448:                putmsg(0, "%s", errmsg.c_str());
                    449:                return 0;
                    450:        }
1.1.1.3   root      451:        if (target->GetDevType() != SCSI::DevType::HD) {
1.1       root      452:                errmsg = "No bootable disks";
                    453:                putmsg(0, "%s", errmsg.c_str());
                    454:                return 0;
                    455:        }
                    456: 
1.1.1.10  root      457:        SCSIDisk *hd = dynamic_cast<SCSIDisk*>(target);
1.1       root      458:        putmsg(2, "%s SCSIHD[%d] found", __func__, id);
                    459: 
                    460:        // +0 セクタ目(512byte)に Sun disklabel
                    461:        scd_dk_label dk;
1.1.1.10  root      462:        if (hd->Peek(&dk, 0, sizeof(dk)) == false) {
1.1       root      463:                putmsg(0, "SCSIHD[%d] ReadSector failed", id);
                    464:                errmsg = string_format("dk%d Read disklabel failed.", dkunit);
                    465:                return 0;
                    466:        }
                    467: 
                    468:        // +$1fc の MAGIC をチェック
                    469:        uint32 magic = be16toh(dk.magic);
                    470:        if (magic != scd_dk_label::DKL_MAGIC) {
                    471:                putmsg(0, "SCSIHD[%d] Bad magic 0x%04x (!= 0x%x)",
                    472:                        id, magic, scd_dk_label::DKL_MAGIC);
                    473:                errmsg = string_format("dk%d Bad disklabel magic.", dkunit);
                    474:                return 0;
                    475:        }
                    476: 
                    477:        // チェックサム照合は手抜きで省略
                    478: 
                    479:        // 指定パーティションの開始位置とサイズ
                    480:        if (loglevel >= 2) {
                    481:                // デバッグ用に全部表示
                    482:                for (int i = 0; i < 8; i++) {
1.1.1.7   root      483:                        putmsgn("%s partition %c: { start=%8u size=%8u }", __func__,
1.1       root      484:                                'a' + i,
                    485:                                be32toh(dk.map[i].blkno),
                    486:                                be32toh(dk.map[i].nblk));
                    487:                }
                    488:        }
                    489:        uint32 part_start = be32toh(dk.map[dkpart].blkno);
                    490:        uint32 part_size  = be32toh(dk.map[dkpart].nblk);
                    491:        putmsg(1, "%s partition=%c, start=%u size=%u", __func__,
                    492:                dkpart + 'a', part_start, part_size);
                    493: 
                    494:        // ファイルシステムをオープン (マウントっぽいイメージ)
                    495:        Filesys fsys(this);
1.1.1.7   root      496:        if (fsys.Mount(hd, part_start, part_size) == false) {
                    497:                errmsg = string_format("dk%d,%c Open ffs failed: %s",
                    498:                        dkunit, dkpart + 'a', fsys.errstr.c_str());
                    499:                putmsg(0, "%s: %s", __func__, errmsg.c_str());
1.1       root      500:                return 0;
                    501:        }
                    502: 
1.1.1.7   root      503:        // ファイルを探してオープンする
                    504:        inodefile f(this);
                    505:        if (fsys.OpenFile(f, dkfile) == false) {
                    506:                errmsg = string_format("dk%d,%c,%s open failed: %s",
                    507:                        dkunit, dkpart + 'a', dkfile.c_str(), fsys.errstr.c_str());
                    508:                putmsg(0, "%s: %s", __func__, errmsg.c_str());
1.1       root      509:                return 0;
                    510:        }
1.1.1.7   root      511: 
1.1       root      512:        // ファイル本体を読み込み
1.1.1.7   root      513:        fsys.ReadData(f);
1.1       root      514: 
                    515:        // ロード
                    516:        uint32 entry;
                    517:        std::string name = string_format("SCSIHD %d,%c:%s",
1.1.1.7   root      518:                id, dkpart + 'a', dkfile.c_str());
                    519:        entry = gRAM->LoadFile(name.c_str(), f.data.data(), f.data.size());
                    520:        if (entry == 0) {
                    521:                errmsg = string_format("dk%d,%c,%s not executable",
                    522:                        dkunit, dkpart + 'a', dkfile.c_str());
1.1       root      523:        }
                    524: 
1.1.1.7   root      525:        return entry;
1.1       root      526: }
                    527: 
1.1.1.7   root      528: // キーコードから文字への変換
                    529: /*static*/ const uint8
                    530: LunaPROMEmuDevice::lunakey2asciitable[] = {
1.1.1.9   root      531:         0,   0,   0,   0,   0,   0,   0,   0,
                    532:         0,   0,   0,   0,   0,   0,   0,   0,
                    533:         0,  BS,  LF,   0, ' ',   0,   0,   0,
                    534:         0,   0,   0,   0,  UP,LEFT,RIGHT,DOWN,
1.1.1.7   root      535:         0,   0,  '1', '2', '3', '4', '5', '6',
                    536:        '7', '8', '9', '0', '-', '^', '\\', 0,
                    537:         0,   0,  'q', 'w', 'e', 'r', 't', 'y',
                    538:        'u', 'i', 'o', 'p', '@', '[',  0,   0,
                    539:         0,   0,  'a', 's', 'd', 'f', 'g', 'h',
                    540:        'j', 'k', 'l', ';', ':', ']',  0,   0,
                    541:         0,   0,  'z', 'x', 'c', 'v', 'b', 'n',
                    542:        'm', ',', '.', '/',  0,   0,   0,   0,
1.1.1.13! root      543:         0,  '+', '-', '7', '8', '9', '4', '5',
        !           544:        '6', '1', '2', '3', '0', '.', LF,   0,
        !           545:         0,   0,   0,   0,   0,   0,   0,   0,
        !           546:         0,   0,   0,   0,  '*', '/', '=', ',',
1.1.1.7   root      547: };
                    548: /*static*/ const uint8
                    549: LunaPROMEmuDevice::lunakey2shifttable[] = {
1.1.1.9   root      550:         0,   0,   0,   0,   0,   0,   0,   0,
                    551:         0,   0,   0,   0,   0,   0,   0,   0,
                    552:         0,  BS,  LF,   0, ' ',   0,   0,   0,
                    553:         0,   0,   0,   0,  UP,LEFT,RIGHT,DOWN,
                    554:         0,   0,  '!', '\"','#', '$', '%', '&',
                    555:        '\'','(', ')', ' ', '=', '~', '|',  0,          // XXX SHIFT+'0'は?
1.1.1.7   root      556:         0,   0,  'Q', 'W', 'E', 'R', 'T', 'Y',
                    557:        'U', 'I', 'O', 'P', '`', '{',  0,   0,
                    558:         0,   0,  'A', 'S', 'D', 'F', 'G', 'H',
                    559:        'J', 'K', 'L', '+', '*', '}',  0,   0,
                    560:         0,   0,  'Z', 'X', 'C', 'V', 'B', 'N',
                    561:        'M', '<', '>', '?', '_',  0,   0,   0,
1.1.1.13! root      562:         0,  '+', '-', '7', '8', '9', '4', '5',
        !           563:        '6', '1', '2', '3', '0', '.', LF,   0,
        !           564:         0,   0,   0,   0,   0,   0,   0,   0,
        !           565:         0,   0,   0,   0,  '*', '/', '=', ',',
1.1.1.7   root      566: };

unix.superglobalmegacorp.com

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