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

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

unix.superglobalmegacorp.com

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