|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.2 root 7: // LUNA88K の ROM エミュレーション
8:
9: // IODevice
10: // |
11: // +----------+----------+
12: // v v
13: // ROMDevice Luna88KPROMEmuDeivce (ROM エミュレーション)
14: // |
15: // v
16: // PROMDevice (実ROM)
17:
18: #include "romemu_luna88k.h"
1.1 root 19: #include "aout.h"
20: #include "bt454.h"
21: #include "mainapp.h"
22: #include "memorystream.h"
23: #include "ram.h"
24: #include "spc.h"
25:
26: // コンストラクタ
27: Luna88kPROMEmuDevice::Luna88kPROMEmuDevice()
28: {
29: devaddr = baseaddr;
1.1.1.2 root 30: devlen = 256 * 1024;
31:
32: romdatalen = 1024; // サイズは適当
33: romdata.reset(new uint8 [romdatalen]);
1.1 root 34: }
35:
36: // デストラクタ
37: Luna88kPROMEmuDevice::~Luna88kPROMEmuDevice()
38: {
39: }
40:
41: bool
42: Luna88kPROMEmuDevice::Init()
43: {
1.1.1.2 root 44: MemoryStreamBE ms(romdata.get());
1.1 root 45:
46: // リセットベクタは本来2ワードだけだが他のベクタは使わないので
47: // 直接コードを書く。
48: uint32 hi = ROMIO_IPL >> 16;
49: uint32 lo = ROMIO_IPL & 0xffff;
50: ms.Write32(0x5c400000 | hi); // or.u r2, r0, (ROMIO_IPL >> 16)
51: ms.Write32(0x58420000 | lo); // or r2, r2, (ROMIO_IPL & 0xffff)
52: ms.Write32(0xf4221400); // ld r1, r2, r0
53: ms.Write32(0xf400c001); // jmp r1
54:
55: return true;
56: }
57:
58: void
59: Luna88kPROMEmuDevice::ResetHard()
60: {
61: ipl_done = false;
62: }
63:
64: // アドレスデコーダ
65: inline uint64
66: Luna88kPROMEmuDevice::Decoder(uint32 addr) const
67: {
1.1.1.2 root 68: // 折り返しなし
1.1 root 69: return addr - baseaddr;
70: }
71:
72: uint64
1.1.1.2 root 73: Luna88kPROMEmuDevice::Read8(uint32 addr)
74: {
75: // LUNA88K で Read8 呼ばれるんだっけ?
76:
77: uint64 offset = Decoder(addr) & (devlen - 1);
78:
79: // 謎の IO 空間は(ロング)ワードアクセスのみ
80: if (offset < romdatalen) {
81: return romdata[offset];
82: } else {
83: return 0xff;
84: }
85: }
86:
87: uint64
88: Luna88kPROMEmuDevice::Read16(uint32 addr)
89: {
90: // LUNA88K で Read16 呼ばれるんだっけ?
91:
92: uint64 offset = Decoder(addr) & (devlen - 1);
93:
94: // 謎の IO 空間は(ロング)ワードアクセスのみ
95: if (offset < romdatalen) {
96: return be16toh(*(uint16 *)(&romdata[offset]));
97: } else {
98: return 0xffff;
99: }
100: }
101:
102: uint64
1.1 root 103: Luna88kPROMEmuDevice::Read32(uint32 addr)
104: {
105: uint64 offset = Decoder(addr);
106:
107: // (ロング)ワードアクセスでだけ謎の I/O 空間が見える
108: switch (offset) {
109: case ROMIO_IPL - baseaddr:
110: if (!ipl_done)
111: return IPL();
112: break;
113: }
114:
1.1.1.2 root 115: offset &= (devlen - 1);
116: if (offset < romdatalen) {
117: return be32toh(*(uint32 *)(&romdata[offset]));
118: } else {
119: return 0xffffffff;
120: }
121: }
122:
123: uint64
124: Luna88kPROMEmuDevice::Write8(uint32 addr, uint32 data)
125: {
126: return 0;
127: }
128:
129: uint64
130: Luna88kPROMEmuDevice::Write16(uint32 addr, uint32 data)
131: {
132: return 0;
133: }
134:
135: uint64
136: Luna88kPROMEmuDevice::Write32(uint32 addr, uint32 data)
137: {
138: return 0;
139: }
140:
141: uint64
142: Luna88kPROMEmuDevice::Peek8(uint32 addr)
143: {
144: uint64 offset = Decoder(addr) & (devlen - 1);
145:
146: if (offset < romdatalen) {
147: return romdata[offset];
148: } else {
149: return 0xff;
150: }
1.1 root 151: }
152:
153: // 起動時の処理を行う。
154: // 成功すればエントリポイント、失敗すれば 0 を返す。
155: uint32
156: Luna88kPROMEmuDevice::IPL()
157: {
158: uint32 entry = 0;
159:
160: ipl_done = true;
161:
162: // ベクタテーブルを rte で埋めておく
163: for (int i = 0; i < 512; i++) {
164: gRAM->Write32(i * 8, 0xf400fc00 /* rte */);
165: }
166:
167: // ROM の機能テーブル
168: // 0x00001100 からあるようだ
169: // 0x0000110c GETC()
170: // 0x00001110 PUTC(c)
171: // 0x00001114 ビットマッププレーンの有効状態が入っている。
172: // bit0: plane0 有効
173: // bit1..7: plane1..7 有効
174: gRAM->Write32(0x0000110c, 0x00001300);
175: gRAM->Write32(0x00001110, 0x00001400);
176: gRAM->Write32(0x00001114, 0x00000001);
177:
178: // ROM GETC エミュレータ
179: gRAM->Write32(0x00001300, 0xfc000c00); // internal inst getc
180: gRAM->Write32(0x00001304, 0xf400c001); // jmp r1
181:
182: // ROM PUTC エミュレータ
183: gRAM->Write32(0x00001400, 0xfc001000); // internal inst putc
184: gRAM->Write32(0x00001404, 0xf400c001); // jmp r1
185:
1.1.1.3 ! root 186: // XXX このへん romemu_luna と同じところは共通化したほうがいい
! 187:
1.1 root 188: // 初期パレット
1.1.1.3 ! root 189: // 偶数番は白(R/G/B=15/15/15)、奇数番は黒(0/0/0)。
! 190: uint8 val = 0xf0;
! 191: gBT454->Write8(0, 0); // select palette
1.1.1.2 root 192: for (int i = 0; i < 16; i++) {
1.1.1.3 ! root 193: gBT454->Write8(1, val); // R
! 194: gBT454->Write8(1, val); // G
! 195: gBT454->Write8(1, val); // B
! 196: val ^= 0xf0;
1.1.1.2 root 197: }
1.1 root 198:
199: // SCSI
200: // BDID の書き込みによってホストデバイスがバスにアタッチされる構造なので。
201: gSPC->Write8(SPC::BDID, 7);
202:
203: if (gMainApp.host_file) {
204: // ホストのファイルを読み込んでエントリポイントアドレスを
205: // この Read アクセスの読み出し値として返す。
206: entry = gRAM->LoadFile(gMainApp.host_file, AOUT_MID_M88K);
1.1.1.3 ! root 207: if (entry == 0) {
! 208: // XXX まだコンソールがなくて停止できないのでとりあえず終了
! 209: exit(1);
! 210: }
1.1 root 211: }
212:
213: return entry;
214: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.