|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.