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

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2018 [email protected]
                      4: //
                      5: 
                      6: #include "bitmap.h"
                      7: #include "bt454.h"
                      8: 
                      9: //
                     10: // ビットマッププレーン
                     11: //
                     12: // Bitmap の VRAM はロングワード単位でホストバイトオーダ配置なので、
                     13: // バイトアクセス、ワードアクセス時は HLB(), HLW() マクロを使用のこと。
                     14: //
                     15: 
                     16: // SX-9100 のほうはこう書いてあってこっちが正しいようだ。
                     17: //      +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
                     18: // b100 |RF|        |BS|        |共 通 B M P|プレーン#0 |
                     19: // b110 |プレーン#1 |プレーン#2 |プレーン#3 |プレーン#4 |
                     20: // b120 |プレーン#5 |プレーン#6 |プレーン#7 |FC|        |
                     21: // b130 |F0|        |F1|        |F2|        |F3|        |
                     22: // b140 |F4|        |F5|        |F6|        |F7|        |
                     23: //
                     24: // SX-7100 のほうはこう書いてあるがこうはなっていないようだ。
                     25: //      +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
                     26: // b100 |RF|        |BS|        |共 通 B M P|FC|        |
                     27: // b110 |プレーン#0 |プレーン#1 |プレーン#2 |プレーン#3 |
                     28: // b120 |プレーン#4 |プレーン#5 |プレーン#6 |プレーン#7 |
                     29: // b130 |F0|        |F1|        |F2|        |F3|        |
                     30: // b140 |F4|        |F5|        |F6|        |F7|        |
                     31: //
                     32: // RF: RFCNT (4バイト)
                     33: // BS: BMSEL (4バイト)
                     34: // FC: 共通ファンクションセット
                     35: // Fn: プレーン#n ファンクションセット
                     36: // 1区画が 64KB。空白のところは未調査。
                     37: 
                     38: BitmapDevice *gBitmap;
                     39: 
                     40: BitmapDevice::BitmapDevice()
                     41: {
                     42:        logname = "bitmap";
                     43:        devname = "Bitmap";
                     44:        devaddr = 0xb1000000;
                     45:        monitor.Init(42, 11);
                     46: 
                     47:        // XXX とりあえず。実際は設定による
                     48:        nplane = 1;
                     49:        // プレーン数によってメモリを確保
                     50:        mem = new uint8 [0x40000 * nplane];
                     51: }
                     52: 
                     53: BitmapDevice::~BitmapDevice()
                     54: {
                     55:        if (mem) {
                     56:                delete[] mem;
                     57:        }
                     58: }
                     59: 
                     60: void
                     61: BitmapDevice::ResetHard()
                     62: {
                     63:        // 厳密にどの時点でリセットされるのかは知らないけど
                     64:        bmsel = 0;
                     65: 
                     66:        // RFCNT の初期値は観測困難なので、とりあえず無視。
                     67: 
                     68:        for (int i = 0; i < MAX_PLANES; i++) {
                     69:                fcs[i] = 5;
                     70:                mask[i] = 0xffffffff;
                     71:        }
                     72: 
                     73:        // XXX ここ?
                     74:        Invalidate();
                     75: }
                     76: 
                     77: uint64
                     78: BitmapDevice::Read8(uint32 addr)
                     79: {
                     80:        if (addr < plane0base) {
                     81:                // 書き込み専用
                     82:                return 0xff;
                     83:        }
                     84:        if (addr < plane0base + 0x40000 * nplane) {
                     85:                // プレーンの読み出し
                     86:                return mem[HLB(addr - plane0base)];
                     87:        }
                     88:        // 残りは書き込み専用
                     89:        return 0xff;
                     90: }
                     91: 
                     92: uint64
                     93: BitmapDevice::Read16(uint32 addr)
                     94: {
                     95:        if (addr < plane0base) {
                     96:                // 書き込み専用
                     97:                return 0xffff;
                     98:        }
                     99:        if (addr < plane0base + 0x40000 * nplane) {
                    100:                // プレーンの読み出し
                    101:                return *(uint16 *)&mem[HLW(addr - plane0base)];
                    102:        }
                    103:        // 残りは書き込み専用
                    104:        return 0xffff;
                    105: }
                    106: 
                    107: uint64
                    108: BitmapDevice::Read32(uint32 addr)
                    109: {
                    110:        if (addr < plane0base) {
                    111:                // 書き込み専用
                    112:                return 0xffffffff;
                    113:        }
                    114:        if (addr < plane0base + 0x40000 * nplane) {
                    115:                // プレーンの読み出し
                    116:                return *(uint32 *)&mem[addr - plane0base];
                    117:        }
                    118:        // 残りは書き込み専用
                    119:        return 0xffffffff;
                    120: }
                    121: 
                    122: uint64
                    123: BitmapDevice::Write8(uint32 addr, uint32 data)
                    124: {
                    125:        switch (addr) {
                    126:         case 0xb1000000:
                    127:         case 0xb1000001:
                    128:         case 0xb1000002:
                    129:         case 0xb1000003:
                    130:                // このロングワード内へのバイトアクセスはロングワードにミラーされる
                    131:                data = (data << 24) | (data << 16) | (data << 8) | data;
                    132:                return Write32(addr & ~3, data);
                    133:         case 0xb1040000:
                    134:         case 0xb1040001:
                    135:         case 0xb1040002:
                    136:         case 0xb1040003:
                    137:                // BMSEL はバイトアクセスできる?
                    138:                putlog(0, "未実装バイト書き込み $%08x <- $%02x", addr, data);
                    139:                return 0;
                    140:        }
                    141: 
                    142:        if (addr < 0xb1080000) {
                    143:                putlog(0, "未実装バイト書き込み $%08x <- $%02x", addr, data);
                    144:                return 0;
                    145:        }
                    146:        if (addr < plane0base) {
                    147:                // 共通ビットマッププレーン
                    148:                WriteCommonBitmap8(addr, data);
                    149:                return 0;
                    150:        }
                    151: 
                    152:        if (addr < plane7end) {
                    153:                // ビットマッププレーン
                    154:                uint32 reladdr = addr - plane0base;
                    155:                uint plane = reladdr / 0x40000;
                    156:                uint32 offset = reladdr % 0x40000;
                    157: 
                    158:                if (plane < nplane) {
                    159:                        // ビットマッププレーンN
                    160:                        putlog(2, "プレーン%d書き込み $%08x <- $%02x", plane, addr, data);
                    161:                        WritePlane8(plane, offset, data);
                    162:                        return 0;
                    163:                }
                    164:                // HW 設定によっては存在しないプレーンへの書き込み
                    165:                putlog(3, "不在プレーン%d書き込み $%08x <- $%02x",
                    166:                        plane, addr, data);
                    167:                return 0;
                    168:        }
                    169: 
                    170:        putlog(0, "未実装バイト書き込み $%08x <- $%02x", addr, data);
                    171:        return 0;
                    172: }
                    173: 
                    174: uint64
                    175: BitmapDevice::Write16(uint32 addr, uint32 data)
                    176: {
                    177:        switch (addr) {
                    178:         case 0xb1000000:
                    179:         case 0xb1000002:
                    180:                // このロングワード内へのワードアクセスはロングワードにミラーされる
                    181:                data = (data << 16) | data;
                    182:                return Write32(addr & ~3, data);
                    183:         case 0xb1040000:
                    184:         case 0xb1040002:
                    185:                // BMSEL はワードアクセスできる?
                    186:                putlog(0, "未実装ワード書き込み $%08x <- $%04x", addr, data);
                    187:                return 0;
                    188:        }
                    189: 
                    190:        if (addr < 0xb1080000) {
                    191:                putlog(0, "未実装ワード書き込み $%08x <- $%04x", addr, data);
                    192:                return 0;
                    193:        }
                    194:        if (addr < plane0base) {
                    195:                // 共通ビットマッププレーン
                    196:                WriteCommonBitmap16(addr, data);
                    197:                return 0;
                    198:        }
                    199: 
                    200:        if (addr < plane7end) {
                    201:                // ビットマッププレーン
                    202:                uint32 reladdr = addr - plane0base;
                    203:                uint plane = reladdr / 0x40000;
                    204:                uint32 offset = reladdr % 0x40000;
                    205: 
                    206:                if (plane < nplane) {
                    207:                        // ビットマッププレーンN
                    208:                        putlog(2, "プレーン%d書き込み $%08x <- $%04x", plane, addr, data);
                    209:                        WritePlane16(plane, offset, data);
                    210:                        return 0;
                    211:                }
                    212:                // HW 設定によっては存在しないプレーンへの書き込み
                    213:                putlog(3, "不在プレーン%d書き込み $%08x <- $%04x",
                    214:                        plane, addr, data);
                    215:                return 0;
                    216:        }
                    217: 
                    218:        putlog(0, "未実装ワード書き込み $%08x <- $%04x", addr, data);
                    219:        return 0;
                    220: }
                    221: 
                    222: uint64
                    223: BitmapDevice::Write32(uint32 addr, uint32 data)
                    224: {
                    225:        switch (addr) {
                    226:         case 0xb1000000:
                    227:                // RFCNT
                    228:                WriteRFCNT(data);
                    229:                return 0;
                    230: 
                    231:         case 0xb1040000:
                    232:                // BMSEL
                    233:                bmsel = data & 0xf;
                    234:                putlog(1, "BMSEL <- $%08x", data);
                    235:                return 0;
                    236:        }
                    237: 
                    238:        if (addr < 0xb1080000) {
                    239:                putlog(0, "未実装ロング書き込み $%08x <- $%08x", addr, data);
                    240:                return 0;
                    241:        }
                    242:        if (addr < plane0base) {
                    243:                // 共通ビットマッププレーン
                    244:                WriteCommonBitmap32(addr, data);
                    245:                return 0;
                    246:        }
                    247: 
                    248:        if (addr < plane7end) {
                    249:                // ビットマッププレーン
                    250:                uint32 reladdr = addr - plane0base;
                    251:                uint plane = reladdr / 0x40000;
                    252:                uint32 offset = reladdr % 0x40000;
                    253: 
                    254:                if (plane < nplane) {
                    255:                        // ビットマッププレーンN
                    256:                        putlog(3, "プレーン%d書き込み $%08x <- $%08x", plane, addr, data);
                    257:                        WritePlane32(plane, offset, data);
                    258:                        return 0;
                    259:                }
                    260:                // HW 設定によっては存在しないプレーンへの書き込み
                    261:                putlog(3, "不在プレーン%d書き込み $%08x <- $%08x",
                    262:                        plane, addr, data);
                    263:                return 0;
                    264:        }
                    265: 
                    266:        if (addr < 0xb1300000) {
                    267:                // 共通ファンクションセット
                    268:                uint rop = (addr & 0x3f) / 4;
                    269:                putlog(2, "共通FCSet 書き込み $%08x <- $%08x (%s)",
                    270:                        addr, data, RopStr(rop));
                    271:                for (int i = 0; i < nplane; i++) {
                    272:                        if ((bmsel & (1 << i))) {
                    273:                                fcs[i] = rop;
                    274:                                mask[i] = data;
                    275:                        }
                    276:                }
                    277:                return 0;
                    278:        }
                    279: 
                    280:        if (addr < fcset7end) {
                    281:                // ファンクションセット
                    282:                int plane = (addr - 0xb1300000) / 0x40000;
                    283: 
                    284:                if (plane < nplane) {
                    285:                        // ファンクションセットN
                    286:                        uint rop = (addr & 0x3f) / 4;
                    287:                        putlog(2, "FCSet%d書き込み $%08x <- $%08x (%s)",
                    288:                                plane, addr, data, RopStr(rop));
                    289:                        fcs[plane] = rop;
                    290:                        mask[plane] = data;
                    291:                        return 0;
                    292:                }
                    293:                // HW 設定によっては存在しない FCSet への書き込み
                    294:                putlog(3, "不在FCSet%d書き込み $%08x <- $%08x",
                    295:                        plane, addr, data);
                    296:                return 0;
                    297:        }
                    298: 
                    299:        putlog(0, "未実装ロング書き込み $%08x <- $%08x", addr, data);
                    300:        return 0;
                    301: }
                    302: 
                    303: uint64
                    304: BitmapDevice::Peek8(uint32 addr)
                    305: {
                    306:        if (addr < plane0base) {
                    307:                // 書き込み専用
                    308:                return 0xff;
                    309:        }
                    310:        if (addr < plane0base + 0x40000 * nplane) {
                    311:                // プレーンの読み出し
                    312:                return mem[HLB(addr - plane0base)];
                    313:        }
                    314:        // 残りは書き込み専用
                    315:        return 0xff;
                    316: }
                    317: 
                    318: bool
                    319: BitmapDevice::MonitorUpdate()
                    320: {
                    321:        int i;
                    322: 
                    323:        monitor.Clear();
                    324: 
                    325:        // 0         1         2         3         4
                    326:        // 012345678901234567890123456789012345678901
                    327:        // RFCNT: $12345678 (X=-123dot, Y=1023dot)
                    328:        //
                    329:        //    BMSEL=$4 ROP  Mask           RGB    RGB
                    330:        // Plane#0 Sel THRU $ffffffff   $0:RGB $8:RGB
                    331:        monitor.Print(0, 0, "RFCNT: $%08x (X=%ddot, Y=%ddot)",
                    332:                rfcnt, hscroll, vscroll);
                    333:        monitor.Print(3, 2, "BMSEL=$%x ROP  Mask", bmsel);
                    334: 
                    335:        for (i = 0; i < nplane; i++) {
                    336:                monitor.Print(0, 3 + i, "Plane#%d %s %s $%08x",
                    337:                        i,
                    338:                        (bmsel & (1 << i)) ? "Sel" : "---",
                    339:                        RopStr(fcs[i]), mask[i]);
                    340:        }
                    341:        for (; i < MAX_PLANES; i++) {
                    342:                monitor.Print(0, 3 + i, TA::Disable, "Plane#%d (Not installed)", i);
                    343:        }
                    344: 
                    345:        // ついでなのでここで BT454 のパレットも表示。
                    346:        // 012345
                    347:        // $0:RGB
                    348:        const uint8 *pal = gBT454->reg.color;
                    349:        monitor.Print(29, 1, "<BT454>");
                    350:        monitor.Print(32, 2, "RGB    RGB");
                    351:        for (i = 0; i < 16; i++) {
                    352:                uint rgb =
                    353:                        ((pal[i * 3 + 0] & 0xf0) << 4) +
                    354:                        ((pal[i * 3 + 1] & 0xf0)     ) +
                    355:                        ((pal[i * 3 + 2] & 0xf0) >> 4);
                    356:                monitor.Print(29 + (i / 8) * 7, (i % 8) + 3, "$%x:%03x", i, rgb);
                    357:        }
                    358: 
                    359:        return true;
                    360: }
                    361: 
                    362: // 全画面の更新フラグを立てる
                    363: void
                    364: BitmapDevice::Invalidate()
                    365: {
                    366:        for (int i = 0; i < 1024; i++) {
                    367:                atomic_dirty[i] = 1;
                    368:        }
                    369: }
                    370: 
                    371: // RFCNT への書き込み
                    372: void
                    373: BitmapDevice::WriteRFCNT(uint32 data)
                    374: {
                    375:        // レジスタ値
                    376:        rfcnt = data;
                    377: 
                    378:        // 水平オフセットを計算
                    379:        // XXX マニュアルでは -8 まで指定できるように読めるが
                    380:        //     指定する方法が分からない。
                    381:        // XXX 193 以上を指定するとどうなるのか (とりあえずほっとく)
                    382:        //     実機の挙動を目分量で見ると、右にはみ出た部分は
                    383:        //     256 ラスタ先のラスタデータを描画しているようだ。
                    384:        hscroll = ((rfcnt >> 16) & 0xff) + 8;
                    385:        hscroll *= 4;
                    386: 
                    387:        // ラスタ(垂直)カウンタ
                    388:        // マニュアルには +26 オフセットすると書いてあるように読めるが、
                    389:        // 手元の実機では +49 でいい感じになるようだ。なんでかは知らん。
                    390:        // ROM モニタで
                    391:        // > b1000000;,a
                    392:        // > h
                    393:        // > h
                    394:        // とした時の画面上下のヘルプメッセージのフォントの見切れ方で検証。
                    395:        vscroll = (rfcnt + 49) & 0x3ff;
                    396: 
                    397:        // 全画面更新
                    398:        Invalidate();
                    399: 
                    400:        putlog(1, "RFCNT <- $%08x (水平 %ddot, 垂直 %ddot)",
                    401:                data, hscroll, vscroll);
                    402: }
                    403: 
                    404: // 共通ビットマッププレーン バイト書き込み
                    405: void
                    406: BitmapDevice::WriteCommonBitmap8(uint32 addr, uint32 data)
                    407: {
                    408:        uint32 offset = addr - 0xb1080000;
                    409:        putlog(2, "共通プレーン書き込み $%08x <- $%02x", addr, data);
                    410:        for (int i = 0; i < nplane; i++) {
                    411:                if ((bmsel & (1 << i))) {
                    412:                        WritePlane8(i, offset, data);
                    413:                }
                    414:        }
                    415: }
                    416: 
                    417: // 共通ビットマッププレーン ワード書き込み
                    418: void
                    419: BitmapDevice::WriteCommonBitmap16(uint32 addr, uint32 data)
                    420: {
                    421:        uint32 offset = addr - 0xb1080000;
                    422:        putlog(2, "共通プレーン書き込み $%08x <- $%04x", addr, data);
                    423:        for (int i = 0; i < nplane; i++) {
                    424:                if ((bmsel & (1 << i))) {
                    425:                        WritePlane16(i, offset, data);
                    426:                }
                    427:        }
                    428: }
                    429: 
                    430: // 共通ビットマッププレーン ロング書き込み
                    431: void
                    432: BitmapDevice::WriteCommonBitmap32(uint32 addr, uint32 data)
                    433: {
                    434:        uint32 offset = addr - 0xb1080000;
                    435:        putlog(2, "共通プレーン書き込み $%08x <- $%08x", addr, data);
                    436:        for (int i = 0; i < nplane; i++) {
                    437:                if ((bmsel & (1 << i))) {
                    438:                        WritePlane32(i, offset, data);
                    439:                }
                    440:        }
                    441: }
                    442: 
                    443: static inline uint32
                    444: RasterOp(uint rop, uint32 data, uint32 m)
                    445: {
                    446:        switch (rop) {
                    447:         case 0:        // ZERO
                    448:                data = 0;
                    449:                break;
                    450:         case 1:        // AND1
                    451:                data &= m;
                    452:                break;
                    453:         case 2:        // AND2
                    454:                data = ~data & m;
                    455:                break;
                    456:         case 3:        // 使用不可
                    457:                // 本当はここにシリアルモード変更コマンドがあるらしい
                    458:                data = m;
                    459:                break;
                    460:         case 4:        // AND3
                    461:                data &= ~m;
                    462:                break;
                    463:         case 5:        // THROUGH
                    464:                break;
                    465:         case 6:        // EOR
                    466:                data ^= m;
                    467:                break;
                    468:         case 7:        // OR1
                    469:                data |= m;
                    470:                break;
                    471:         case 8:        // NOR
                    472:                data = ~data & ~m;
                    473:                break;
                    474:         case 9:        // ENOR
                    475:                data = (data & m) | (~data & ~m);
                    476:                break;
                    477:         case 10:       // INV1
                    478:                data = ~data;
                    479:                break;
                    480:         case 11:       // OR2
                    481:                data = ~data | m;
                    482:                break;
                    483:         case 12:       // INV2
                    484:                data = ~m;
                    485:                break;
                    486:         case 13:       // OR3
                    487:                data |= ~m;
                    488:                break;
                    489:         case 14:       // NAND
                    490:                data = ~data | ~m;
                    491:                break;
                    492:         case 15:       // ONE
                    493:                data = 0xffffffff;
                    494:                break;
                    495:        }
                    496:        return data;
                    497: }
                    498: 
                    499: // ROP 文字列を返す
                    500: const char *
                    501: BitmapDevice::RopStr(uint rop)
                    502: {
                    503:        static const char * ropstr[] = {
                    504:                "ZERO",
                    505:                "AND1",
                    506:                "AND2",
                    507:                "(3)",
                    508:                "AND3",
                    509:                "THRU", // THROUGH
                    510:                "EOR",
                    511:                "OR1",
                    512:                "NOR",
                    513:                "ENOR",
                    514:                "INV1",
                    515:                "OR2",
                    516:                "INV2",
                    517:                "OR3",
                    518:                "NAND",
                    519:                "ONE",
                    520:        };
                    521:        return ropstr[rop];
                    522: }
                    523: 
                    524: // プレーン バイト書き込み
                    525: void
                    526: BitmapDevice::WritePlane8(uint plane, uint32 offset, uint32 data)
                    527: {
                    528:        uint32 memoffset = plane * 0x40000 + offset;
                    529:        uint32 m;
                    530:        uint32 mask8;
                    531: 
                    532:        m = mem[HLB(memoffset)];
                    533:        data = RasterOp(fcs[plane], data, m);
                    534:        mask8 = mask[plane] >> (24 - (memoffset & 3) * 8);
                    535:        mem[HLB(memoffset)] = (data & mask8) | (m & ~mask8);
                    536:        atomic_dirty[offset / 256] = 1;
                    537: }
                    538: 
                    539: // プレーン ワード書き込み
                    540: void
                    541: BitmapDevice::WritePlane16(uint plane, uint32 offset, uint32 data)
                    542: {
                    543:        uint32 memoffset = plane * 0x40000 + offset;
                    544:        uint32 m;
                    545:        uint32 mask16;
                    546: 
                    547:        m = *(uint16 *)&mem[HLW(memoffset)];
                    548:        data = RasterOp(fcs[plane], data, m);
                    549:        if ((memoffset & 2) == 0) {
                    550:                // 上位ワード
                    551:                mask16 = mask[plane] >> 16;
                    552:        } else {
                    553:                // 下位ワード
                    554:                mask16 = mask[plane];
                    555:        }
                    556:        *(uint16 *)&mem[HLW(memoffset)] = (data & mask16) | (m & ~mask16);
                    557:        atomic_dirty[offset / 256] = 1;
                    558: }
                    559: 
                    560: // プレーン ロングワード書き込み
                    561: void
                    562: BitmapDevice::WritePlane32(uint plane, uint32 offset, uint32 data)
                    563: {
                    564:        uint32 memoffset = plane * 0x40000 + offset;
                    565:        uint32 m;
                    566: 
                    567:        m = *(uint32 *)&mem[memoffset];
                    568:        data = RasterOp(fcs[plane], data, m);
                    569:        *(uint32 *)&mem[memoffset] = (data & mask[plane]) | (m & ~mask[plane]);
                    570:        atomic_dirty[offset / 256] = 1;
                    571: }

unix.superglobalmegacorp.com

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