|
|
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:
186: // 初期パレット
1.1.1.2 ! root 187: // 偶数が 0xf, 奇数が 0
! 188: for (int i = 0; i < 16; i++) {
! 189: gBT454->Write8(0, i << 4); // select palette
! 190: uint32 c = ((i & 1) ? 0 : 0xf) << 4;
! 191: gBT454->Write8(1, c); // R
! 192: gBT454->Write8(1, c); // G
! 193: gBT454->Write8(1, c); // B
! 194: }
1.1 root 195:
196: // SCSI
197: // BDID の書き込みによってホストデバイスがバスにアタッチされる構造なので。
198: gSPC->Write8(SPC::BDID, 7);
199:
200: if (gMainApp.host_file) {
201: // ホストのファイルを読み込んでエントリポイントアドレスを
202: // この Read アクセスの読み出し値として返す。
203: entry = gRAM->LoadFile(gMainApp.host_file, AOUT_MID_M88K);
204: }
205:
206: return entry;
207: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.