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

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

unix.superglobalmegacorp.com

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