|
|
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: // ラスタ(垂直)カウンタ
1.1.1.2 ! root 388: vscroll = (rfcnt + 26) & 0x3ff;
1.1 root 389:
390: // 全画面更新
391: Invalidate();
392:
393: putlog(1, "RFCNT <- $%08x (水平 %ddot, 垂直 %ddot)",
394: data, hscroll, vscroll);
395: }
396:
397: // 共通ビットマッププレーン バイト書き込み
398: void
399: BitmapDevice::WriteCommonBitmap8(uint32 addr, uint32 data)
400: {
401: uint32 offset = addr - 0xb1080000;
402: putlog(2, "共通プレーン書き込み $%08x <- $%02x", addr, data);
403: for (int i = 0; i < nplane; i++) {
404: if ((bmsel & (1 << i))) {
405: WritePlane8(i, offset, data);
406: }
407: }
408: }
409:
410: // 共通ビットマッププレーン ワード書き込み
411: void
412: BitmapDevice::WriteCommonBitmap16(uint32 addr, uint32 data)
413: {
414: uint32 offset = addr - 0xb1080000;
415: putlog(2, "共通プレーン書き込み $%08x <- $%04x", addr, data);
416: for (int i = 0; i < nplane; i++) {
417: if ((bmsel & (1 << i))) {
418: WritePlane16(i, offset, data);
419: }
420: }
421: }
422:
423: // 共通ビットマッププレーン ロング書き込み
424: void
425: BitmapDevice::WriteCommonBitmap32(uint32 addr, uint32 data)
426: {
427: uint32 offset = addr - 0xb1080000;
428: putlog(2, "共通プレーン書き込み $%08x <- $%08x", addr, data);
429: for (int i = 0; i < nplane; i++) {
430: if ((bmsel & (1 << i))) {
431: WritePlane32(i, offset, data);
432: }
433: }
434: }
435:
436: static inline uint32
437: RasterOp(uint rop, uint32 data, uint32 m)
438: {
439: switch (rop) {
440: case 0: // ZERO
441: data = 0;
442: break;
443: case 1: // AND1
444: data &= m;
445: break;
446: case 2: // AND2
447: data = ~data & m;
448: break;
449: case 3: // 使用不可
450: // 本当はここにシリアルモード変更コマンドがあるらしい
451: data = m;
452: break;
453: case 4: // AND3
454: data &= ~m;
455: break;
456: case 5: // THROUGH
457: break;
458: case 6: // EOR
459: data ^= m;
460: break;
461: case 7: // OR1
462: data |= m;
463: break;
464: case 8: // NOR
465: data = ~data & ~m;
466: break;
467: case 9: // ENOR
468: data = (data & m) | (~data & ~m);
469: break;
470: case 10: // INV1
471: data = ~data;
472: break;
473: case 11: // OR2
474: data = ~data | m;
475: break;
476: case 12: // INV2
477: data = ~m;
478: break;
479: case 13: // OR3
480: data |= ~m;
481: break;
482: case 14: // NAND
483: data = ~data | ~m;
484: break;
485: case 15: // ONE
486: data = 0xffffffff;
487: break;
488: }
489: return data;
490: }
491:
492: // ROP 文字列を返す
493: const char *
494: BitmapDevice::RopStr(uint rop)
495: {
496: static const char * ropstr[] = {
497: "ZERO",
498: "AND1",
499: "AND2",
500: "(3)",
501: "AND3",
502: "THRU", // THROUGH
503: "EOR",
504: "OR1",
505: "NOR",
506: "ENOR",
507: "INV1",
508: "OR2",
509: "INV2",
510: "OR3",
511: "NAND",
512: "ONE",
513: };
514: return ropstr[rop];
515: }
516:
517: // プレーン バイト書き込み
518: void
519: BitmapDevice::WritePlane8(uint plane, uint32 offset, uint32 data)
520: {
521: uint32 memoffset = plane * 0x40000 + offset;
522: uint32 m;
523: uint32 mask8;
524:
525: m = mem[HLB(memoffset)];
526: data = RasterOp(fcs[plane], data, m);
527: mask8 = mask[plane] >> (24 - (memoffset & 3) * 8);
528: mem[HLB(memoffset)] = (data & mask8) | (m & ~mask8);
529: atomic_dirty[offset / 256] = 1;
530: }
531:
532: // プレーン ワード書き込み
533: void
534: BitmapDevice::WritePlane16(uint plane, uint32 offset, uint32 data)
535: {
536: uint32 memoffset = plane * 0x40000 + offset;
537: uint32 m;
538: uint32 mask16;
539:
540: m = *(uint16 *)&mem[HLW(memoffset)];
541: data = RasterOp(fcs[plane], data, m);
542: if ((memoffset & 2) == 0) {
543: // 上位ワード
544: mask16 = mask[plane] >> 16;
545: } else {
546: // 下位ワード
547: mask16 = mask[plane];
548: }
549: *(uint16 *)&mem[HLW(memoffset)] = (data & mask16) | (m & ~mask16);
550: atomic_dirty[offset / 256] = 1;
551: }
552:
553: // プレーン ロングワード書き込み
554: void
555: BitmapDevice::WritePlane32(uint plane, uint32 offset, uint32 data)
556: {
557: uint32 memoffset = plane * 0x40000 + offset;
558: uint32 m;
559:
560: m = *(uint32 *)&mem[memoffset];
561: data = RasterOp(fcs[plane], data, m);
562: *(uint32 *)&mem[memoffset] = (data & mask[plane]) | (m & ~mask[plane]);
563: atomic_dirty[offset / 256] = 1;
564: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.