Annotation of nono/vm/bt45x.cpp, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // Bt454/458
                      9: //
                     10: 
                     11: // 仕様書には $c100_0000 と書いてあるが、PROM も NetBSD カーネルも
                     12: // $c110_0000 にアクセスしている。実際にはアドレスバスの上位寄りは未接続の
                     13: // 箇所が多くほとんどの場所でミラーが見えているので問題はない。
                     14: //
                     15: // LUNA-I、LUNA-88K どちらでも (というかここはビデオボードなので本体関係なく)
                     16: // Bt454 ならバイトポートが連続配置 (BusIO_B 相当)、
                     17: // Bt458 ならバイトポートがロングワード配置 (たぶん BusIO_BFFF 相当、未確認)
                     18: // となっているようだ。このため、ここでは BusIO を使わず自力でデコードする。
                     19: //
                     20: // ソフトウェアから判別は以下の要領で行える。
                     21: // 先頭の1バイトは 1or4bpp ボード(連続配置)、8bpp ボード(ロングワード配置)の
                     22: // どちらでもアドレスレジスタなので、ここに $00 を書き込んでから読み返す。
                     23: // $0f が読み出せたら Bt454 なので 1or4bpp ボード、$00 が読み出せたら Bt458
                     24: // なので 8bpp ボードと分かる。Bt458 のデータバスは8ビットクリーンだが、
                     25: // Bt454 のデータバスは4ビットしかなく下位ニブルは常に $f になるため。
                     26: //
                     27: // LUNA-I の PROM v4.22 は 8bpp ボードに対応していない。
                     28: 
                     29: #include "bt45x.h"
                     30: #include "config.h"
                     31: #include "mainapp.h"
                     32: #include "mpu.h"
                     33: #include "planevram.h"
                     34: #include "prom.h"
                     35: #include "renderer.h"
                     36: #include "uimessage.h"
                     37: 
                     38: // Bt454 の下位ニブル用マスク
                     39: #define LOW_NIBBLE     (0x0f)
                     40: 
                     41: // コンストラクタ
                     42: BT45xDevice::BT45xDevice()
                     43:        : inherited(OBJ_BT45x)
                     44: {
                     45:        // func, size は Init() で決まる
                     46:        monitor.Regist(ID_MONITOR_BT45x);
                     47: }
                     48: 
                     49: // デストラクタ
                     50: BT45xDevice::~BT45xDevice()
                     51: {
                     52: }
                     53: 
                     54: // 初期化
                     55: bool
                     56: BT45xDevice::Init()
                     57: {
                     58:        if (inherited::Init() == false) {
                     59:                return false;
                     60:        }
                     61: 
                     62:        renderer = GetRenderer();
                     63: 
                     64:        // 設定からプレーン数を取得
                     65:        const ConfigItem& item = gConfig->Find("luna-video-plane");
                     66:        if (item.TryInt(&nplane) == false) {
                     67:                item.Err();
                     68:                return false;
                     69:        }
                     70:        if (nplane != 1 && nplane != 4 && nplane != 8) {
                     71:                item.Err("Must be 1, 4, or 8");
                     72:                return false;
                     73:        }
                     74: 
                     75:        // それによってモデル分け。1bpp/4bpp なら Bt454、8bpp なら Bt458。
                     76:        if (nplane <= 4) {
                     77:                bt454 = true;
                     78:                palettes = 16;
                     79:                low_nibble = LOW_NIBBLE;
                     80:                readmask = 0x0f;
                     81: 
                     82:                monitor.func = ToMonitorCallback(&BT45xDevice::MonitorUpdate454);
                     83:                monitor.SetSize(63, 3);
                     84:        } else {
                     85:                bt454 = false;
                     86:                palettes = 256;
                     87:                low_nibble = 0;
                     88:                // 初期化されないそうなのでゴミを入れておく
                     89:                readmask = 0xcc;
                     90: 
                     91:                monitor.func = ToMonitorCallback(&BT45xDevice::MonitorUpdate458);
                     92:                monitor.SetSize(116, 18);
                     93: 
                     94:                // LUNA-I の PROM v4.22 は 8bpp ボードをサポートしておらず PROM の
                     95:                // 画面は真っ暗のままになる。その後 OS が再初期化すれば使えるようには
                     96:                // なるが、PROM が映らずびっくりするのでメッセージだけ表示して、
                     97:                // 実行は継続する。他の ROM バージョンは未調査。
                     98:                auto prom = dynamic_cast<PROMDevice *>(GetPROMDevice());
                     99:                if (gMainApp.IsLUNA1() && prom != NULL) {
                    100:                        int ver = prom->GetROMVer();
                    101:                        if (ver <= 422) {
                    102:                                warnx("Warning: PROM v%d.%02d does not support 8bpp board.",
                    103:                                        ver / 100, ver % 100);
                    104:                                // 実行は継続
                    105:                        }
                    106:                }
                    107:        }
                    108: 
                    109:        color.resize(palettes * 3);
                    110:        hostcolor.resize(palettes);
                    111:        return true;
                    112: }
                    113: 
                    114: // リセット
                    115: void
                    116: BT45xDevice::ResetHard(bool poweron)
                    117: {
                    118:        idx = 0;
                    119: 
                    120:        // ReadMask、BlinkMask は初期化されない (初期値も不明)
                    121: 
                    122:        // XXX Bt45x のレジスタの初期値は不明なのでとりあえず全部黒にしておく
                    123:        memset(&color[0], 0, color.size());
                    124:        for (int i = 0; i < countof(color); i++) {
                    125:                MakeHostColor(i);
                    126:        }
                    127:        Notify();
                    128: }
                    129: 
                    130: /* static */ const char
                    131: BT45xDevice::rgbstr[3] = { 'R', 'G', 'B' };
                    132: 
                    133: // LUNA のビデオボードは Bt454 か Bt458 かでバイト配置が異なるようだ。
                    134: 
                    135: uint64
                    136: BT45xDevice::Read8(uint32 addr)
                    137: {
                    138:        if (bt454) {
                    139:                // バイトポートが連続、4バイトでミラー
                    140:                return Read(addr & 3);
                    141:        } else {
                    142:                // バイトポートがロングワード配置、隙間は何が見えるか不明、
                    143:                // たぶん16バイトでミラー。
                    144:                addr &= 15;
                    145:                if (addr % 4 == 0) {
                    146:                        return Read(addr / 4);
                    147:                } else {
                    148:                        return 0xff;
                    149:                }
                    150:        }
                    151: }
                    152: 
                    153: uint64
                    154: BT45xDevice::Write8(uint32 addr, uint32 data)
                    155: {
                    156:        if (bt454) {
                    157:                // バイトポートが連続、4バイトでミラー
                    158:                return Write(addr & 3, data);
                    159:        } else {
                    160:                // バイトポートがロングワード配置、隙間は何が見えるか不明、
                    161:                // たぶん16バイトでミラー。
                    162:                addr &= 15;
                    163:                if (addr % 4 == 0) {
                    164:                        return Write(addr / 4, data);
                    165:                } else {
                    166:                        return 0;
                    167:                }
                    168:        }
                    169: }
                    170: 
                    171: uint64
                    172: BT45xDevice::Peek8(uint32 addr)
                    173: {
                    174:        if (bt454) {
                    175:                // バイトポートが連続、4バイトでミラー
                    176:                return Peek(addr & 3);
                    177:        } else {
                    178:                // バイトポートがロングワード配置、隙間は何が見えるか不明、
                    179:                // たぶん16バイトでミラー。
                    180:                addr &= 15;
                    181:                if (addr % 4 == 0) {
                    182:                        return Peek(addr / 4);
                    183:                } else {
                    184:                        return 0xff;
                    185:                }
                    186:        }
                    187: }
                    188: 
                    189: // こっちがマッピング非依存のバイトポートアクセス
                    190: uint64
                    191: BT45xDevice::Read(uint32 offset)
                    192: {
                    193:        uint32 data;
                    194: 
                    195:        switch (offset) {
                    196:         case 0:        // アドレスレジスタ
                    197:                data = ReadAddress();
                    198:                break;
                    199: 
                    200:         case 1:        // カラーパレットレジスタ
                    201:                data = ReadPalette();
                    202:                break;
                    203: 
                    204:         case 2:        // Bt454 ならリセット(?)、Bt458 なら各種制御レジスタ
                    205:                data = ReadControl();
                    206:                break;
                    207: 
                    208:         case 3:
                    209:                putlog(0, "Read Overlay Register (NOT IMPLEMENTED)");
                    210:                data = 0xff;
                    211:                break;
                    212: 
                    213:         default:
                    214:                VMPANIC("corrupted offset=%d", offset);
                    215:        }
                    216: 
                    217:        return data;
                    218: }
                    219: 
                    220: // こっちがマッピング非依存のバイトポートアクセス
                    221: uint64
                    222: BT45xDevice::Write(uint32 offset, uint32 data)
                    223: {
                    224:        // Bt454 なら書き込みデータのうち有効なのは上位ニブルだけ
                    225: 
                    226:        switch (offset) {
                    227:         case 0:        // アドレスレジスタ
                    228:                WriteAddress(data);
                    229:                break;
                    230: 
                    231:         case 1:        // カラーパレットレジスタ
                    232:                WritePalette(data);
                    233:                break;
                    234: 
                    235:         case 2:        // Bt454 ならリセット(?)、Bt458 なら各種制御レジスタ
                    236:                WriteControl(data);
                    237:                break;
                    238: 
                    239:         case 3:
                    240:                putlog(0, "Overlay Register <- $%02x (NOT IMPLEMENTED)", data);
                    241:                break;
                    242: 
                    243:         default:
                    244:                VMPANIC("corrupted offset=%d", offset);
                    245:        }
                    246:        return 0;
                    247: }
                    248: 
                    249: // こっちがマッピング非依存のバイトポートアクセス
                    250: uint64
                    251: BT45xDevice::Peek(uint32 offset)
                    252: {
                    253:        uint8 data;
                    254: 
                    255:        switch (offset) {
                    256:         case 0:        // アドレスレジスタ
                    257:                data = idx / 3;
                    258:                data &= readmask;
                    259:                break;
                    260: 
                    261:         case 1:        // カラーパレットレジスタ
                    262:                // 今読み出そうとしたら読み出せるやつ
                    263:                data = color[idx];
                    264:                break;
                    265: 
                    266:         case 2:        // Bt454 ならリセット(?)、Bt458 なら各種制御レジスタ
                    267:                data = PeekControl();
                    268:                break;
                    269: 
                    270:         case 3:
                    271:                // 未実装
                    272:                data = 0xff;
                    273:                break;
                    274: 
                    275:         default:
                    276:                data = 0xff;
                    277:                break;
                    278:        }
                    279: 
                    280:        if (bt454) {
                    281:                data = (data << 4) | LOW_NIBBLE;
                    282:        }
                    283:        return data;
                    284: }
                    285: 
                    286: // Bt454
                    287: void
                    288: BT45xDevice::MonitorUpdate454(Monitor *, TextScreen& screen)
                    289: {
                    290:        screen.Clear();
                    291:        screen.Puts(0, 0, "Model: Bt454");
                    292: 
                    293:        // 01234567
                    294:        // $0  $1
                    295:        // RGB RGB
                    296: 
                    297:        for (int i = 0; i < 16; i++) {
                    298:                screen.Print(i * 4, 1, "$%x", i);
                    299:                screen.Puts(i * 4, 2, strhex(Palette454ToInt(i), 3).c_str());
                    300:        }
                    301: }
                    302: 
                    303: // Bt458
                    304: void
                    305: BT45xDevice::MonitorUpdate458(Monitor *, TextScreen& screen)
                    306: {
                    307:        screen.Clear();
                    308:        screen.Puts(0, 0, "Model: Bt458");
                    309: 
                    310:        // 012345678901
                    311:        //       +$0    +$1
                    312:        // $00: RRGGBB RRGGBB
                    313: 
                    314:        for (int i = 0; i < 16; i++) {
                    315:                screen.Print(5 + i * 7, 1, "+$%x", i);
                    316:        }
                    317:        int c = 0;
                    318:        for (int y = 0; y < 16; y++) {
                    319:                screen.Print(0, y + 2, "$%02x:", y * 16);
                    320:                for (int x = 0; x < 16; x++) {
                    321:                        screen.Print(5 + x * 7, y + 2, "%06x", Palette458ToInt(c));
                    322:                        c++;
                    323:                }
                    324:        }
                    325: }
                    326: 
                    327: // idx 番目のレジスタ値からホストパレットを作成。
                    328: void
                    329: BT45xDevice::MakeHostColor(int idx_)
                    330: {
                    331:        assert(idx_ < color.size());
                    332:        int col = idx_ / 3;
                    333:        int ab  = idx_ % 3;
                    334: 
                    335:        if (nplane == 1) {
                    336:                // 1bpp (モノクロプレーン) なら R,G,B のうち G の値だけを使用
                    337:                if (ab == 1) {
                    338:                        hostcolor[col].r = color[col * 3 + 1];
                    339:                        hostcolor[col].g = color[col * 3 + 1];
                    340:                        hostcolor[col].b = color[col * 3 + 1];
                    341:                }
                    342:        } else {
                    343:                // カラープレーンなら代入するだけ
                    344:                switch (ab) {
                    345:                 case 0:
                    346:                        hostcolor[col].r = color[col * 3 + ab];
                    347:                        break;
                    348:                 case 1:
                    349:                        hostcolor[col].g = color[col * 3 + ab];
                    350:                        break;
                    351:                 case 2:
                    352:                        hostcolor[col].b = color[col * 3 + ab];
                    353:                        break;
                    354:                 default:
                    355:                        VMPANIC("corrupted ab=%d", ab);
                    356:                }
                    357:        }
                    358: 
                    359:        // 通知が必要なら別途行うこと。
                    360: }
                    361: 
                    362: // 通知
                    363: void
                    364: BT45xDevice::Notify()
                    365: {
                    366:        // パレット変更が起きたことをレンダラに通知
                    367:        renderer->Invalidate2();
                    368: 
                    369:        // UI にも通知
                    370:        UIMessage::Post(UIMessage::PALETTE);
                    371: }
                    372: 
                    373: // アドレスレジスタ読み込み。
                    374: uint32
                    375: BT45xDevice::ReadAddress()
                    376: {
                    377:        uint32 data;
                    378: 
                    379:        // 今の(今からアクセスする)パレット番号を返す。
                    380:        data = idx / 3;
                    381:        // Bt458 ならこれをマスクする?
                    382:        data &= readmask;
                    383:        if (bt454) {
                    384:                data = (data << 4) | LOW_NIBBLE;
                    385:        }
                    386:        putlog(2, "Address Register -> $%02x", data);
                    387: 
                    388:        // アドレスレジスタアクセスで ab カウンタは 0 にリセットされる
                    389:        idx = (idx / 3) * 3;
                    390: 
                    391:        return data;
                    392: }
                    393: 
                    394: // パレットレジスタ読み込み。
                    395: uint32
                    396: BT45xDevice::ReadPalette()
                    397: {
                    398:        uint32 data;
                    399: 
                    400:        // Bt454 の場合 color[] の上位下位4ビットは同じ値にしてある
                    401:        data = color[idx] | low_nibble;
                    402:        putlog(2, "Color Palette $%x(%c) -> $%02x",
                    403:                idx / 3, rgbstr[idx % 3], data);
                    404: 
                    405:        // アクセスするたびにインクリメントする。
                    406:        idx++;
                    407:        if (idx >= color.size()) {
                    408:                idx = 0;
                    409:        }
                    410: 
                    411:        return data;
                    412: }
                    413: 
                    414: // Bt454 ならリセット(?)、
                    415: // Bt458 なら各種制御レジスタの読み込み。
                    416: uint32
                    417: BT45xDevice::ReadControl()
                    418: {
                    419:        uint32 data;
                    420: 
                    421:        if (bt454) {
                    422:                // ADDRa,b を 0 にする? D0-D3 は 0 になる??
                    423:                // データシートが雑でよく分からん…
                    424:                idx = (idx / 3) * 3;
                    425:                data = 0x00 | LOW_NIBBLE;
                    426:                putlog(2, "reset ab");
                    427:        } else {
                    428:                // Bt458 なら、この時点のアドレスによってコマンド処理
                    429:                uint addr = idx / 3;
                    430:                switch (addr) {
                    431:                 case 0x04:
                    432:                        data = readmask;
                    433:                        putlog(2, "Read ReadMask -> $%02x", data);
                    434:                        break;
                    435:                 case 0x05:
                    436:                        data = blinkmask;
                    437:                        putlog(2, "Read BlinkMask -> $%02x", data);
                    438:                        break;
                    439:                 case 0x06:
                    440:                        data = command;
                    441:                        putlog(2, "Read Command -> $%02x", data);
                    442:                        break;
                    443:                 case 0x07:
                    444:                        data = testreg;
                    445:                        putlog(2, "Read Test -> $%02x", data);
                    446:                        break;
                    447:                 default:
                    448:                        data = 0;
                    449:                        putlog(0, "Read $%02x (NOT IMPLEMENTED)", addr);
                    450:                        break;
                    451:                }
                    452:        }
                    453: 
                    454:        return data;
                    455: }
                    456: 
                    457: // アドレスレジスタ書き込み。
                    458: void
                    459: BT45xDevice::WriteAddress(uint32 data)
                    460: {
                    461:        // 今からアクセスするパレット番号。
                    462:        // アドレスレジスタアクセスで ab カウンタは 0 にリセットされる。
                    463:        // data はパレット番号だが idx は配列のインデックスなので 3倍。
                    464:        putlog(2, "Address Register <- $%02x", data);
                    465:        if (bt454) {
                    466:                data >>= 4;
                    467:        }
                    468:        idx = data * 3;
                    469: }
                    470: 
                    471: // パレットレジスタ書き込み。
                    472: void
                    473: BT45xDevice::WritePalette(uint32 data)
                    474: {
                    475:        // Bt454 なら上位下位4ビットに同じ値を置くことで 0 .. 255 にする。
                    476:        if (bt454) {
                    477:                data = (data & 0xf0) | ((data >> 4) & 0x0f);
                    478:        }
                    479:        color[idx] = data;
                    480: 
                    481:        if (loglevel == 1) {
                    482:                // ログレベル1なら RGB が書き込まれた時点で表示。
                    483:                // 大体はこれくらいの表示で構わないはず。
                    484:                if (idx % 3 == 2) {
                    485:                        if (bt454) {
                    486:                                putlogn("Color Palette $%x = (%x,%x,%x)",
                    487:                                        idx / 3,
                    488:                                        color[idx - 2] >> 4,
                    489:                                        color[idx - 1] >> 4,
                    490:                                        color[idx    ] >> 4);
                    491:                        } else {
                    492:                                putlogn("Color Palette $%02x = (%02x,%02x,%02x)",
                    493:                                        idx / 3,
                    494:                                        color[idx - 2],
                    495:                                        color[idx - 1],
                    496:                                        color[idx    ]);
                    497:                        }
                    498:                }
                    499:        } else if (loglevel >= 2) {
                    500:                if (bt454) {
                    501:                        putlogn("Color Palette $%x(%c) <- $%02x",
                    502:                                idx / 3, rgbstr[idx % 3], data);
                    503:                } else {
                    504:                        putlogn("Color Palette $%02x(%c) <- $%02x",
                    505:                                idx / 3, rgbstr[idx % 3], data);
                    506:                }
                    507:        }
                    508: 
                    509:        // ホストカラーを計算。
                    510:        // (Bt458 では?) Blue を書き込んだところで色情報がストアされるっぽい?
                    511:        MakeHostColor(idx);
                    512:        Notify();
                    513: 
                    514:        // ホストカラー計算後にインクリメントする。
                    515:        idx++;
                    516:        if (idx >= color.size()) {
                    517:                idx = 0;
                    518:        }
                    519: }
                    520: 
                    521: // Bt454 ならリセット(?)、
                    522: // Bt458 なら各種制御レジスタへの書き込み。
                    523: void
                    524: BT45xDevice::WriteControl(uint32 data)
                    525: {
                    526:        if (bt454) {
                    527:                // ab カウンタを 0 にする? データは無視されるようだ
                    528:                idx = (idx / 3) * 3;
                    529:                putlog(2, "reset ab");
                    530:        } else {
                    531:                // Bt458 なら、この時点のアドレスによってコマンド処理。
                    532:                uint addr = idx / 3;
                    533:                switch (addr) {
                    534:                 case 0x04:
                    535:                        WriteRMask(data);
                    536:                        break;
                    537:                 case 0x05:
                    538:                        WriteBMask(data);
                    539:                        break;
                    540:                 case 0x06:
                    541:                        WriteCommand(data);
                    542:                        break;
                    543:                 case 0x07:
                    544:                        WriteTest(data);
                    545:                        break;
                    546:                 default:
                    547:                        putlog(1, "Unknown command $%02x <- $%02x", addr, data);
                    548:                        break;
                    549:                }
                    550:        }
                    551: }
                    552: 
                    553: // Bt458 Read Mask の書き込み。
                    554: void
                    555: BT45xDevice::WriteRMask(uint32 data)
                    556: {
                    557:        readmask = data;
                    558:        putlog(1, "Write ReadMask <- $%02x", readmask);
                    559: }
                    560: 
                    561: // Bt458 Blink Mask の書き込み。
                    562: void
                    563: BT45xDevice::WriteBMask(uint32 data)
                    564: {
                    565:        // 未実装
                    566:        blinkmask = data;
                    567:        if (blinkmask != 0x00) {
                    568:                putlog(0, "Write BlinkMask <- $%02x (NOT IMPLEMENTED)", blinkmask);
                    569:        } else {
                    570:                putlog(1, "Write BlinkMask <- $%02x", blinkmask);
                    571:        }
                    572: }
                    573: 
                    574: // Bt458 コマンドレジスタへの書き込み。
                    575: void
                    576: BT45xDevice::WriteCommand(uint32 data)
                    577: {
                    578:        command = data;
                    579:        putlog(1, "Write Command <- $%02x", command);
                    580: 
                    581:        // 未実装
                    582:        if ((command & 0x80)) {
                    583:                putlog(0, "5:1 Multiplex (NOT IMPLEMENTED)");
                    584:        }
                    585:        if ((command & 0x40) == 0) {
                    586:                putlog(0, "Use overlay color0 (NOT IMPLEMENTED)");
                    587:        }
                    588:        if ((command & 0x0c)) {
                    589:                putlog(0, "Blink enable (NOT IMPLEMENTED)");
                    590:        }
                    591:        if ((command & 0x03)) {
                    592:                putlog(0, "Display enable (NOT IMPLEMENTED)");
                    593:        }
                    594: }
                    595: 
                    596: // テストレジスタへの書き込み。
                    597: void
                    598: BT45xDevice::WriteTest(uint32 data)
                    599: {
                    600:        // 未実装
                    601:        testreg = data;
                    602:        if (testreg != 0x00) {
                    603:                putlog(0, "Write Test <- $%02x (NOT IMPLEMENTED)", testreg);
                    604:        } else {
                    605:                // カーネルが初期化時にアクセスに来る
                    606:                putlog(1, "Write Test <- $%02x (NOT IMPLEMENTED)", testreg);
                    607:        }
                    608: }
                    609: 
                    610: // 制御レジスタを読み出す。(Peek() 用)
                    611: uint32
                    612: BT45xDevice::PeekControl() const
                    613: {
                    614:        if (bt454) {
                    615:                return 0x00;
                    616:        } else {
                    617:                uint addr = idx / 3;
                    618:                switch (addr) {
                    619:                 case 0x04:
                    620:                        return readmask;
                    621:                 case 0x05:
                    622:                        return blinkmask;
                    623:                 case 0x06:
                    624:                        return command;
                    625:                 case 0x07:
                    626:                        return testreg;
                    627:                 default:
                    628:                        // XXX ?
                    629:                        return 0;
                    630:                }
                    631:        }
                    632: }
                    633: 
                    634: // ゲストパレットを uint32 形式にしたものの一覧を返す。(GUI 用)
                    635: const std::vector<uint32>
                    636: BT45xDevice::GetIntPalette() const
                    637: {
                    638:        std::vector<uint32> ipal;
                    639: 
                    640:        if (bt454) {
                    641:                for (int i = 0; i < palettes; i++) {
                    642:                        ipal.push_back(Palette454ToInt(i));
                    643:                }
                    644:        } else {
                    645:                for (int i = 0; i < palettes; i++) {
                    646:                        ipal.push_back(Palette458ToInt(i));
                    647:                }
                    648:        }
                    649:        return ipal;
                    650: }
                    651: 
                    652: // Bt454 のパレット番号 n の生データを uint32 で返す。
                    653: // Bt454 の場合は RGB 各4ビットを右詰め。$0000'0RGB。
                    654: uint32
                    655: BT45xDevice::Palette454ToInt(int n) const
                    656: {
                    657:        return ((color[n * 3 + 0] & 0xf0) << 4) |
                    658:               ((color[n * 3 + 1] & 0xf0)     ) |
                    659:               ((color[n * 3 + 2] & 0x0f)     );
                    660: }
                    661: 
                    662: // Bt458 のパレット番号 n の生データを uint32 で返す。
                    663: // Bt458 の場合は RGB 各8ビットを右詰め。$00RR'GGBB。
                    664: uint32
                    665: BT45xDevice::Palette458ToInt(int n) const
                    666: {
                    667:        return (color[n * 3 + 0] << 16) |
                    668:               (color[n * 3 + 1] <<  8) |
                    669:                color[n * 3 + 2];
                    670: }

unix.superglobalmegacorp.com

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