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

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2018 [email protected]
                      4: //
                      5: 
                      6: #include "bitmap.h"
                      7: #include "bt454.h"
1.1.1.3 ! root        8: #include "cgrom.h"
1.1       root        9: 
                     10: //
                     11: // ビットマッププレーン
                     12: //
                     13: // Bitmap の VRAM はロングワード単位でホストバイトオーダ配置なので、
                     14: // バイトアクセス、ワードアクセス時は HLB(), HLW() マクロを使用のこと。
                     15: //
                     16: 
                     17: // SX-9100 のほうはこう書いてあってこっちが正しいようだ。
                     18: //      +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
                     19: // b100 |RF|        |BS|        |共 通 B M P|プレーン#0 |
                     20: // b110 |プレーン#1 |プレーン#2 |プレーン#3 |プレーン#4 |
                     21: // b120 |プレーン#5 |プレーン#6 |プレーン#7 |FC|        |
                     22: // b130 |F0|        |F1|        |F2|        |F3|        |
                     23: // b140 |F4|        |F5|        |F6|        |F7|        |
                     24: //
                     25: // SX-7100 のほうはこう書いてあるがこうはなっていないようだ。
                     26: //      +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
                     27: // b100 |RF|        |BS|        |共 通 B M P|FC|        |
                     28: // b110 |プレーン#0 |プレーン#1 |プレーン#2 |プレーン#3 |
                     29: // b120 |プレーン#4 |プレーン#5 |プレーン#6 |プレーン#7 |
                     30: // b130 |F0|        |F1|        |F2|        |F3|        |
                     31: // b140 |F4|        |F5|        |F6|        |F7|        |
                     32: //
                     33: // RF: RFCNT (4バイト)
                     34: // BS: BMSEL (4バイト)
                     35: // FC: 共通ファンクションセット
                     36: // Fn: プレーン#n ファンクションセット
                     37: // 1区画が 64KB。空白のところは未調査。
1.1.1.3 ! root       38: // 未装着のプレーン(#4..#7とか)は 0xff が読めるようだ。
        !            39: // ファンクションセットが 64バイトで折り返してるか未調査だが、
        !            40: // b130'0000 も b133'0000 も 0xff が読めるのでこの範囲全域でミラーかも。
        !            41: // b150'0000 以降(b1ff'ffffまで) は BUSERR のようだ。
        !            42: //
1.1       root       43: 
1.1.1.3 ! root       44: std::unique_ptr<BitmapDevice> gBitmap;
1.1       root       45: 
                     46: BitmapDevice::BitmapDevice()
                     47: {
                     48:        logname = "bitmap";
                     49:        devname = "Bitmap";
                     50:        devaddr = 0xb1000000;
                     51:        monitor.Init(42, 11);
                     52: 
                     53:        // XXX とりあえず。実際は設定による
                     54:        nplane = 1;
                     55:        // プレーン数によってメモリを確保
1.1.1.3 ! root       56:        mem.reset(new uint8 [0x40000 * nplane]);
1.1       root       57: }
                     58: 
                     59: BitmapDevice::~BitmapDevice()
                     60: {
                     61: }
                     62: 
                     63: void
                     64: BitmapDevice::ResetHard()
                     65: {
                     66:        // 厳密にどの時点でリセットされるのかは知らないけど
                     67:        bmsel = 0;
                     68: 
                     69:        // RFCNT の初期値は観測困難なので、とりあえず無視。
                     70: 
                     71:        for (int i = 0; i < MAX_PLANES; i++) {
                     72:                fcs[i] = 5;
                     73:                mask[i] = 0xffffffff;
                     74:        }
                     75: 
                     76:        // XXX ここ?
                     77:        Invalidate();
                     78: }
                     79: 
                     80: uint64
                     81: BitmapDevice::Read8(uint32 addr)
                     82: {
                     83:        if (addr < plane0base) {
                     84:                // 書き込み専用
                     85:                return 0xff;
                     86:        }
                     87:        if (addr < plane0base + 0x40000 * nplane) {
                     88:                // プレーンの読み出し
                     89:                return mem[HLB(addr - plane0base)];
                     90:        }
                     91:        // 残りは書き込み専用
                     92:        return 0xff;
                     93: }
                     94: 
                     95: uint64
                     96: BitmapDevice::Read16(uint32 addr)
                     97: {
                     98:        if (addr < plane0base) {
                     99:                // 書き込み専用
                    100:                return 0xffff;
                    101:        }
                    102:        if (addr < plane0base + 0x40000 * nplane) {
                    103:                // プレーンの読み出し
                    104:                return *(uint16 *)&mem[HLW(addr - plane0base)];
                    105:        }
                    106:        // 残りは書き込み専用
                    107:        return 0xffff;
                    108: }
                    109: 
                    110: uint64
                    111: BitmapDevice::Read32(uint32 addr)
                    112: {
                    113:        if (addr < plane0base) {
                    114:                // 書き込み専用
                    115:                return 0xffffffff;
                    116:        }
                    117:        if (addr < plane0base + 0x40000 * nplane) {
                    118:                // プレーンの読み出し
                    119:                return *(uint32 *)&mem[addr - plane0base];
                    120:        }
                    121:        // 残りは書き込み専用
                    122:        return 0xffffffff;
                    123: }
                    124: 
                    125: uint64
                    126: BitmapDevice::Write8(uint32 addr, uint32 data)
                    127: {
                    128:        switch (addr) {
                    129:         case 0xb1000000:
                    130:         case 0xb1000001:
                    131:         case 0xb1000002:
                    132:         case 0xb1000003:
                    133:                // このロングワード内へのバイトアクセスはロングワードにミラーされる
                    134:                data = (data << 24) | (data << 16) | (data << 8) | data;
                    135:                return Write32(addr & ~3, data);
                    136:         case 0xb1040000:
                    137:         case 0xb1040001:
                    138:         case 0xb1040002:
                    139:         case 0xb1040003:
                    140:                // BMSEL はバイトアクセスできる?
                    141:                putlog(0, "未実装バイト書き込み $%08x <- $%02x", addr, data);
                    142:                return 0;
                    143:        }
                    144: 
                    145:        if (addr < 0xb1080000) {
                    146:                putlog(0, "未実装バイト書き込み $%08x <- $%02x", addr, data);
                    147:                return 0;
                    148:        }
                    149:        if (addr < plane0base) {
                    150:                // 共通ビットマッププレーン
                    151:                WriteCommonBitmap8(addr, data);
                    152:                return 0;
                    153:        }
                    154: 
                    155:        if (addr < plane7end) {
                    156:                // ビットマッププレーン
                    157:                uint32 reladdr = addr - plane0base;
                    158:                uint plane = reladdr / 0x40000;
                    159:                uint32 offset = reladdr % 0x40000;
                    160: 
                    161:                if (plane < nplane) {
                    162:                        // ビットマッププレーンN
                    163:                        putlog(2, "プレーン%d書き込み $%08x <- $%02x", plane, addr, data);
                    164:                        WritePlane8(plane, offset, data);
                    165:                        return 0;
                    166:                }
                    167:                // HW 設定によっては存在しないプレーンへの書き込み
                    168:                putlog(3, "不在プレーン%d書き込み $%08x <- $%02x",
                    169:                        plane, addr, data);
                    170:                return 0;
                    171:        }
                    172: 
                    173:        putlog(0, "未実装バイト書き込み $%08x <- $%02x", addr, data);
                    174:        return 0;
                    175: }
                    176: 
                    177: uint64
                    178: BitmapDevice::Write16(uint32 addr, uint32 data)
                    179: {
                    180:        switch (addr) {
                    181:         case 0xb1000000:
                    182:         case 0xb1000002:
                    183:                // このロングワード内へのワードアクセスはロングワードにミラーされる
                    184:                data = (data << 16) | data;
                    185:                return Write32(addr & ~3, data);
                    186:         case 0xb1040000:
                    187:         case 0xb1040002:
                    188:                // BMSEL はワードアクセスできる?
                    189:                putlog(0, "未実装ワード書き込み $%08x <- $%04x", addr, data);
                    190:                return 0;
                    191:        }
                    192: 
                    193:        if (addr < 0xb1080000) {
                    194:                putlog(0, "未実装ワード書き込み $%08x <- $%04x", addr, data);
                    195:                return 0;
                    196:        }
                    197:        if (addr < plane0base) {
                    198:                // 共通ビットマッププレーン
                    199:                WriteCommonBitmap16(addr, data);
                    200:                return 0;
                    201:        }
                    202: 
                    203:        if (addr < plane7end) {
                    204:                // ビットマッププレーン
                    205:                uint32 reladdr = addr - plane0base;
                    206:                uint plane = reladdr / 0x40000;
                    207:                uint32 offset = reladdr % 0x40000;
                    208: 
                    209:                if (plane < nplane) {
                    210:                        // ビットマッププレーンN
                    211:                        putlog(2, "プレーン%d書き込み $%08x <- $%04x", plane, addr, data);
                    212:                        WritePlane16(plane, offset, data);
                    213:                        return 0;
                    214:                }
                    215:                // HW 設定によっては存在しないプレーンへの書き込み
                    216:                putlog(3, "不在プレーン%d書き込み $%08x <- $%04x",
                    217:                        plane, addr, data);
                    218:                return 0;
                    219:        }
                    220: 
                    221:        putlog(0, "未実装ワード書き込み $%08x <- $%04x", addr, data);
                    222:        return 0;
                    223: }
                    224: 
                    225: uint64
                    226: BitmapDevice::Write32(uint32 addr, uint32 data)
                    227: {
                    228:        switch (addr) {
                    229:         case 0xb1000000:
                    230:                // RFCNT
                    231:                WriteRFCNT(data);
                    232:                return 0;
                    233: 
                    234:         case 0xb1040000:
                    235:                // BMSEL
                    236:                bmsel = data & 0xf;
                    237:                putlog(1, "BMSEL <- $%08x", data);
                    238:                return 0;
                    239:        }
                    240: 
                    241:        if (addr < 0xb1080000) {
                    242:                putlog(0, "未実装ロング書き込み $%08x <- $%08x", addr, data);
                    243:                return 0;
                    244:        }
                    245:        if (addr < plane0base) {
                    246:                // 共通ビットマッププレーン
                    247:                WriteCommonBitmap32(addr, data);
                    248:                return 0;
                    249:        }
                    250: 
                    251:        if (addr < plane7end) {
                    252:                // ビットマッププレーン
                    253:                uint32 reladdr = addr - plane0base;
                    254:                uint plane = reladdr / 0x40000;
                    255:                uint32 offset = reladdr % 0x40000;
                    256: 
                    257:                if (plane < nplane) {
                    258:                        // ビットマッププレーンN
                    259:                        putlog(3, "プレーン%d書き込み $%08x <- $%08x", plane, addr, data);
                    260:                        WritePlane32(plane, offset, data);
                    261:                        return 0;
                    262:                }
                    263:                // HW 設定によっては存在しないプレーンへの書き込み
                    264:                putlog(3, "不在プレーン%d書き込み $%08x <- $%08x",
                    265:                        plane, addr, data);
                    266:                return 0;
                    267:        }
                    268: 
                    269:        if (addr < 0xb1300000) {
                    270:                // 共通ファンクションセット
                    271:                uint rop = (addr & 0x3f) / 4;
                    272:                putlog(2, "共通FCSet 書き込み $%08x <- $%08x (%s)",
                    273:                        addr, data, RopStr(rop));
                    274:                for (int i = 0; i < nplane; i++) {
                    275:                        if ((bmsel & (1 << i))) {
                    276:                                fcs[i] = rop;
                    277:                                mask[i] = data;
                    278:                        }
                    279:                }
                    280:                return 0;
                    281:        }
                    282: 
                    283:        if (addr < fcset7end) {
                    284:                // ファンクションセット
                    285:                int plane = (addr - 0xb1300000) / 0x40000;
                    286: 
                    287:                if (plane < nplane) {
                    288:                        // ファンクションセットN
                    289:                        uint rop = (addr & 0x3f) / 4;
                    290:                        putlog(2, "FCSet%d書き込み $%08x <- $%08x (%s)",
                    291:                                plane, addr, data, RopStr(rop));
                    292:                        fcs[plane] = rop;
                    293:                        mask[plane] = data;
                    294:                        return 0;
                    295:                }
                    296:                // HW 設定によっては存在しない FCSet への書き込み
                    297:                putlog(3, "不在FCSet%d書き込み $%08x <- $%08x",
                    298:                        plane, addr, data);
                    299:                return 0;
                    300:        }
                    301: 
                    302:        putlog(0, "未実装ロング書き込み $%08x <- $%08x", addr, data);
                    303:        return 0;
                    304: }
                    305: 
                    306: uint64
                    307: BitmapDevice::Peek8(uint32 addr)
                    308: {
                    309:        if (addr < plane0base) {
                    310:                // 書き込み専用
                    311:                return 0xff;
                    312:        }
                    313:        if (addr < plane0base + 0x40000 * nplane) {
                    314:                // プレーンの読み出し
                    315:                return mem[HLB(addr - plane0base)];
                    316:        }
                    317:        // 残りは書き込み専用
                    318:        return 0xff;
                    319: }
                    320: 
                    321: bool
                    322: BitmapDevice::MonitorUpdate()
                    323: {
                    324:        int i;
                    325: 
                    326:        monitor.Clear();
                    327: 
                    328:        // 0         1         2         3         4
                    329:        // 012345678901234567890123456789012345678901
                    330:        // RFCNT: $12345678 (X=-123dot, Y=1023dot)
                    331:        //
                    332:        //    BMSEL=$4 ROP  Mask           RGB    RGB
                    333:        // Plane#0 Sel THRU $ffffffff   $0:RGB $8:RGB
                    334:        monitor.Print(0, 0, "RFCNT: $%08x (X=%ddot, Y=%ddot)",
                    335:                rfcnt, hscroll, vscroll);
                    336:        monitor.Print(3, 2, "BMSEL=$%x ROP  Mask", bmsel);
                    337: 
                    338:        for (i = 0; i < nplane; i++) {
                    339:                monitor.Print(0, 3 + i, "Plane#%d %s %s $%08x",
                    340:                        i,
                    341:                        (bmsel & (1 << i)) ? "Sel" : "---",
                    342:                        RopStr(fcs[i]), mask[i]);
                    343:        }
                    344:        for (; i < MAX_PLANES; i++) {
                    345:                monitor.Print(0, 3 + i, TA::Disable, "Plane#%d (Not installed)", i);
                    346:        }
                    347: 
                    348:        // ついでなのでここで BT454 のパレットも表示。
                    349:        // 012345
                    350:        // $0:RGB
                    351:        const uint8 *pal = gBT454->reg.color;
                    352:        monitor.Print(29, 1, "<BT454>");
                    353:        monitor.Print(32, 2, "RGB    RGB");
                    354:        for (i = 0; i < 16; i++) {
                    355:                uint rgb =
                    356:                        ((pal[i * 3 + 0] & 0xf0) << 4) +
                    357:                        ((pal[i * 3 + 1] & 0xf0)     ) +
                    358:                        ((pal[i * 3 + 2] & 0xf0) >> 4);
                    359:                monitor.Print(29 + (i / 8) * 7, (i % 8) + 3, "$%x:%03x", i, rgb);
                    360:        }
                    361: 
                    362:        return true;
                    363: }
                    364: 
                    365: // 全画面の更新フラグを立てる
                    366: void
                    367: BitmapDevice::Invalidate()
                    368: {
                    369:        for (int i = 0; i < 1024; i++) {
                    370:                atomic_dirty[i] = 1;
                    371:        }
                    372: }
                    373: 
                    374: // RFCNT への書き込み
                    375: void
                    376: BitmapDevice::WriteRFCNT(uint32 data)
                    377: {
                    378:        // レジスタ値
                    379:        rfcnt = data;
                    380: 
                    381:        // 水平オフセットを計算
                    382:        // XXX マニュアルでは -8 まで指定できるように読めるが
                    383:        //     指定する方法が分からない。
                    384:        // XXX 193 以上を指定するとどうなるのか (とりあえずほっとく)
                    385:        //     実機の挙動を目分量で見ると、右にはみ出た部分は
                    386:        //     256 ラスタ先のラスタデータを描画しているようだ。
                    387:        hscroll = ((rfcnt >> 16) & 0xff) + 8;
                    388:        hscroll *= 4;
                    389: 
                    390:        // ラスタ(垂直)カウンタ
1.1.1.2   root      391:        vscroll = (rfcnt + 26) & 0x3ff;
1.1       root      392: 
                    393:        // 全画面更新
                    394:        Invalidate();
                    395: 
                    396:        putlog(1, "RFCNT <- $%08x (水平 %ddot, 垂直 %ddot)",
                    397:                data, hscroll, vscroll);
                    398: }
                    399: 
                    400: // 共通ビットマッププレーン バイト書き込み
                    401: void
                    402: BitmapDevice::WriteCommonBitmap8(uint32 addr, uint32 data)
                    403: {
                    404:        uint32 offset = addr - 0xb1080000;
                    405:        putlog(2, "共通プレーン書き込み $%08x <- $%02x", addr, data);
                    406:        for (int i = 0; i < nplane; i++) {
                    407:                if ((bmsel & (1 << i))) {
                    408:                        WritePlane8(i, offset, data);
                    409:                }
                    410:        }
                    411: }
                    412: 
                    413: // 共通ビットマッププレーン ワード書き込み
                    414: void
                    415: BitmapDevice::WriteCommonBitmap16(uint32 addr, uint32 data)
                    416: {
                    417:        uint32 offset = addr - 0xb1080000;
                    418:        putlog(2, "共通プレーン書き込み $%08x <- $%04x", addr, data);
                    419:        for (int i = 0; i < nplane; i++) {
                    420:                if ((bmsel & (1 << i))) {
                    421:                        WritePlane16(i, offset, data);
                    422:                }
                    423:        }
                    424: }
                    425: 
                    426: // 共通ビットマッププレーン ロング書き込み
                    427: void
                    428: BitmapDevice::WriteCommonBitmap32(uint32 addr, uint32 data)
                    429: {
                    430:        uint32 offset = addr - 0xb1080000;
                    431:        putlog(2, "共通プレーン書き込み $%08x <- $%08x", addr, data);
                    432:        for (int i = 0; i < nplane; i++) {
                    433:                if ((bmsel & (1 << i))) {
                    434:                        WritePlane32(i, offset, data);
                    435:                }
                    436:        }
                    437: }
                    438: 
                    439: static inline uint32
                    440: RasterOp(uint rop, uint32 data, uint32 m)
                    441: {
                    442:        switch (rop) {
                    443:         case 0:        // ZERO
                    444:                data = 0;
                    445:                break;
                    446:         case 1:        // AND1
                    447:                data &= m;
                    448:                break;
                    449:         case 2:        // AND2
                    450:                data = ~data & m;
                    451:                break;
                    452:         case 3:        // 使用不可
                    453:                // 本当はここにシリアルモード変更コマンドがあるらしい
                    454:                data = m;
                    455:                break;
                    456:         case 4:        // AND3
                    457:                data &= ~m;
                    458:                break;
                    459:         case 5:        // THROUGH
                    460:                break;
                    461:         case 6:        // EOR
                    462:                data ^= m;
                    463:                break;
                    464:         case 7:        // OR1
                    465:                data |= m;
                    466:                break;
                    467:         case 8:        // NOR
                    468:                data = ~data & ~m;
                    469:                break;
                    470:         case 9:        // ENOR
                    471:                data = (data & m) | (~data & ~m);
                    472:                break;
                    473:         case 10:       // INV1
                    474:                data = ~data;
                    475:                break;
                    476:         case 11:       // OR2
                    477:                data = ~data | m;
                    478:                break;
                    479:         case 12:       // INV2
                    480:                data = ~m;
                    481:                break;
                    482:         case 13:       // OR3
                    483:                data |= ~m;
                    484:                break;
                    485:         case 14:       // NAND
                    486:                data = ~data | ~m;
                    487:                break;
                    488:         case 15:       // ONE
                    489:                data = 0xffffffff;
                    490:                break;
                    491:        }
                    492:        return data;
                    493: }
                    494: 
                    495: // ROP 文字列を返す
                    496: const char *
                    497: BitmapDevice::RopStr(uint rop)
                    498: {
                    499:        static const char * ropstr[] = {
                    500:                "ZERO",
                    501:                "AND1",
                    502:                "AND2",
                    503:                "(3)",
                    504:                "AND3",
                    505:                "THRU", // THROUGH
                    506:                "EOR",
                    507:                "OR1",
                    508:                "NOR",
                    509:                "ENOR",
                    510:                "INV1",
                    511:                "OR2",
                    512:                "INV2",
                    513:                "OR3",
                    514:                "NAND",
                    515:                "ONE",
                    516:        };
                    517:        return ropstr[rop];
                    518: }
                    519: 
                    520: // プレーン バイト書き込み
                    521: void
                    522: BitmapDevice::WritePlane8(uint plane, uint32 offset, uint32 data)
                    523: {
                    524:        uint32 memoffset = plane * 0x40000 + offset;
                    525:        uint32 m;
                    526:        uint32 mask8;
                    527: 
                    528:        m = mem[HLB(memoffset)];
                    529:        data = RasterOp(fcs[plane], data, m);
                    530:        mask8 = mask[plane] >> (24 - (memoffset & 3) * 8);
                    531:        mem[HLB(memoffset)] = (data & mask8) | (m & ~mask8);
                    532:        atomic_dirty[offset / 256] = 1;
                    533: }
                    534: 
                    535: // プレーン ワード書き込み
                    536: void
                    537: BitmapDevice::WritePlane16(uint plane, uint32 offset, uint32 data)
                    538: {
                    539:        uint32 memoffset = plane * 0x40000 + offset;
                    540:        uint32 m;
                    541:        uint32 mask16;
                    542: 
                    543:        m = *(uint16 *)&mem[HLW(memoffset)];
                    544:        data = RasterOp(fcs[plane], data, m);
                    545:        if ((memoffset & 2) == 0) {
                    546:                // 上位ワード
                    547:                mask16 = mask[plane] >> 16;
                    548:        } else {
                    549:                // 下位ワード
                    550:                mask16 = mask[plane];
                    551:        }
                    552:        *(uint16 *)&mem[HLW(memoffset)] = (data & mask16) | (m & ~mask16);
                    553:        atomic_dirty[offset / 256] = 1;
                    554: }
                    555: 
                    556: // プレーン ロングワード書き込み
                    557: void
                    558: BitmapDevice::WritePlane32(uint plane, uint32 offset, uint32 data)
                    559: {
                    560:        uint32 memoffset = plane * 0x40000 + offset;
                    561:        uint32 m;
                    562: 
                    563:        m = *(uint32 *)&mem[memoffset];
                    564:        data = RasterOp(fcs[plane], data, m);
                    565:        *(uint32 *)&mem[memoffset] = (data & mask[plane]) | (m & ~mask[plane]);
                    566:        atomic_dirty[offset / 256] = 1;
                    567: }
1.1.1.3 ! root      568: 
        !           569: 
        !           570: // エミュレータによる画面出力
        !           571: //
        !           572: // VM 内からの操作ではなく、エミュレータ本体から画面を操作する
        !           573: // エミュレーション ROM によるモニタコンソール用の機能。
        !           574: // サービスを使いたい側 (EmuROM など) が任意の大きさの TextScreen を
        !           575: // 用意し EmuConsoleOpen() をコールすると (現在のパレットのまま) 画面を
        !           576: // クリアし、画面中央をこのテキスト VRAM の表示エリアとみなす。
        !           577: // 以降は EmuConsoleUpdate() で TextScreen の内容に従って画面を更新し、
        !           578: // 使用後は EmuConsoleClose() で再び画面をクリア (およびリソースの解放) を
        !           579: // すること。
        !           580: 
        !           581: // エミュレータによる出力開始
        !           582: void
        !           583: BitmapDevice::EmuConsoleOpen(TextScreen *t)
        !           584: {
        !           585:        textscr = t;
        !           586: 
        !           587:        screen_w = textscr->GetCol();
        !           588:        screen_h = textscr->GetRow();
        !           589:        prev.reset(new uint16[screen_w * screen_h]);
        !           590:        for (int i = 0; i < screen_w * screen_h; i++) {
        !           591:                prev[i] = 0x0020;
        !           592:        }
        !           593: 
        !           594:        // ざっくりセンタリングする
        !           595:        origin_x = (1280 - screen_w * 12) / 2;
        !           596:        origin_y = (1024 - screen_h * 24) / 2;
        !           597:        // ただし横は 48ドット境界から始める
        !           598:        // こうすると1(,2)文字目の24ビットが必ずワード境界から始まる。
        !           599:        origin_x = (origin_x / 48) * 48;
        !           600: 
        !           601:        // 同時書き込み設定
        !           602:        bmsel = (1 << nplane) - 1;
        !           603: 
        !           604:        // 全画面をクリア
        !           605:        for (uint32 addr = 0xb1080000; addr < 0xb10c0000; addr += 4) {
        !           606:                WriteCommonBitmap32(addr, 0);
        !           607:        }
        !           608: }
        !           609: 
        !           610: // エミュレータによる出力終了
        !           611: void
        !           612: BitmapDevice::EmuConsoleClose()
        !           613: {
        !           614:        // 全画面をクリア
        !           615:        for (uint32 addr = 0xb1080000; addr < 0xb10c0000; addr += 4) {
        !           616:                WriteCommonBitmap32(addr, 0);
        !           617:        }
        !           618:        // 同時書き込みも元に戻す
        !           619:        bmsel = 0;
        !           620: 
        !           621:        textscr = NULL;
        !           622:        prev.reset();
        !           623: }
        !           624: 
        !           625: // エミュレータによる出力
        !           626: // ts が出力するテキスト情報、oldts は前回の情報。
        !           627: void
        !           628: BitmapDevice::EmuConsoleUpdate()
        !           629: {
        !           630:        const uint16 *text = textscr->GetBuf();
        !           631: 
        !           632:        // 12ドットフォントなので2文字ずつ (24ビットずつ) 更新する
        !           633:        for (int y = 0; y < screen_h; y++) {
        !           634:                for (int x = 0; x < screen_w; x += 2) {
        !           635:                        // 2文字分の文字と属性
        !           636:                        uint32 t32 = *(const uint32 *)&text[y * screen_w + x];
        !           637:                        uint32 p32 = *(const uint32 *)&prev[y * screen_w + x];
        !           638:                        if (t32 == p32) {
        !           639:                                continue;
        !           640:                        }
        !           641:                        // ここからは変更があったので出力
        !           642:                        *(uint32 *)&prev[y * screen_w + x] = t32;
        !           643:                        // 2文字分として直接32ビットキャストして取り出した t32 だと
        !           644:                        // エンディアンによって上下が変わるので、ここでは改めて
        !           645:                        // 順序通りに2回取り出す
        !           646:                        uint32 ch0 = text[y * screen_w + x];
        !           647:                        uint32 ch1 = text[y * screen_w + x + 1];
        !           648:                        // その文字のフォントデータ上でのオフセット
        !           649:                        uint32 fo0 = 0x3d000 + (ch0 & 0xff) * 48;
        !           650:                        uint32 fo1 = 0x3d000 + (ch1 & 0xff) * 48;
        !           651: 
        !           652:                        // 1,2文字目なら true、3,4文字目なら false
        !           653:                        bool evenpair = ((x & 2) == 0);
        !           654: 
        !           655:                        // ビットマップ上の書き始めアドレス
        !           656:                        uint32 addr = 0xb1080000 +
        !           657:                                ((origin_y + y * 24) * 256) +
        !           658:                                ((origin_x + x * 12) / 8);
        !           659: 
        !           660:                        for (int i = 0; i < 24; i++) {
        !           661:                                // その文字のフォントデータ
        !           662:                                uint32 fdat0 = be16toh(*(uint16*)(&builtin_cgrom[fo0 + i * 2]));
        !           663:                                uint32 fdat1 = be16toh(*(uint16*)(&builtin_cgrom[fo1 + i * 2]));
        !           664: 
        !           665:                                // 属性はとりあえず反転のみサポート
        !           666:                                if ((ch0 & TA::On)) {
        !           667:                                        fdat0 = ~fdat0 & 0xfff0;
        !           668:                                }
        !           669:                                if ((ch1 & TA::On)) {
        !           670:                                        fdat1 = ~fdat1 & 0xfff0;
        !           671:                                }
        !           672: 
        !           673:                                // 1文字目と2文字目を組み合わせて 24bit にする
        !           674:                                uint32 data = (fdat0 << 8) | (fdat1 >> 4);
        !           675: 
        !           676:                                // 書き込みは一度に 3バイトずつになるので、
        !           677:                                // 効率化のため上位下位ペアで書き込みパターンを変える。
        !           678:                                //
        !           679:                                // | chr1 | chr2  | chr3 | chr4  |
        !           680:                                // +----+----+----+----+----+----+
        !           681:                                // | +0 | +1 | +2 | +3 | +4 | +5 |
        !           682:                                // +----+----+----+----+----+----+
        !           683:                                // |<-.Word->|<.B>|<.B>|<-.Word->|
        !           684:                                if (evenpair) {
        !           685:                                        WriteCommonBitmap16(addr, data >> 8);
        !           686:                                        WriteCommonBitmap8(addr + 2, data & 0xff);
        !           687:                                } else {
        !           688:                                        WriteCommonBitmap8(addr, data >> 16);
        !           689:                                        WriteCommonBitmap16(addr + 1, data & 0xffff);
        !           690:                                }
        !           691: 
        !           692:                                addr += 256;    // 1ライン進める
        !           693:                        }
        !           694:                }
        !           695:        }
        !           696: }

unix.superglobalmegacorp.com

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