|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.7 root 7: //
1.1.1.9 root 8: // ROM の基本クラス
9: //
10:
1.1.1.7 root 11: // IODevice
12: // |
13: // | +-----------+
14: // +--| ROMDevice | (LoadROM()、ウェイト、マスク等を持つ)
15: // | +-----------+
16: // | |
17: // | +-- PROMDevice (LUNA* の PROM)
18: // | +-- IPLROM1Device (X680x0 の IPLROM 後半)
19: // | +-- IPLROM2Device (X680x0 の IPLROM 前半)
20: // | +-- CGROMDevice (X680x0 の CGROM)
21: // | +-- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分)
22: // | |
1.1.1.11 root 23: // | +-- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション)
24: // | +-- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション)
1.1.1.7 root 25: // |
26: // +-- PROM0Device (LUNA* のブートページ切り替え用プロキシ)
27: // +-- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ)
28:
1.1 root 29: #include "rom.h"
1.1.1.7 root 30: #include "autofd.h"
1.1.1.3 root 31: #include "mainapp.h"
1.1.1.5 root 32: #include "mpu.h"
1.1.1.7 root 33: #include <fcntl.h>
34: #include <unistd.h>
35: #include <sys/stat.h>
1.1 root 36:
37: //
38: // ROM 共通部
39: //
40:
1.1.1.11 root 41: ROMDevice::ROMDevice(int objid_)
42: : inherited(objid_)
1.1 root 43: {
44: mask = 0xffffffff;
45: }
46:
47: ROMDevice::~ROMDevice()
48: {
49: }
50:
51: // name の ROM を探してロードする。
52: // name はパスを含まないファイル名のみ。パスはこちらで探す。
53: // 失敗した場合はエラーメッセージを表示して false を返す。
54: bool
55: ROMDevice::LoadROM(const char *name, int size)
56: {
1.1.1.7 root 57: struct stat st;
58:
59: assert(size > 0);
60:
61: // ファイル名
1.1.1.3 root 62: filename = gMainApp.SearchFile(name);
1.1 root 63: if (filename.empty()) {
1.1.1.2 root 64: warnx("%s not found", name);
1.1 root 65: return false;
66: }
67:
1.1.1.7 root 68: // メモリを確保
69: imagebuf.reset(new uint8 [size]);
70: if ((bool)imagebuf == false) {
71: warnx("ROM \"%s\": Cannot allocate memory (%d bytes)",
72: filename.c_str(), size);
73: return false;
74: }
75:
1.1 root 76: // オープン
1.1.1.7 root 77: autofd fd = open(filename.c_str(), O_RDONLY);
78: if (fd < 0) {
79: warn("ROM \"%s\"", filename.c_str());
1.1 root 80: return false;
81: }
82:
1.1.1.7 root 83: // ファイルサイズを調べる
84: if (fstat(fd, &st) < 0) {
85: warn("ROM \"%s\" stat failed", filename.c_str());
86: return false;
87: }
88:
89: if (st.st_size < size) {
90: warnx("ROM \"%s\" is too short (filesize is expected %d but %jd)",
91: filename.c_str(), size, (intmax_t)st.st_size);
92: return false;
93: }
94: if (st.st_size > size) {
95: // 大きすぎるほうはワーニングだけでいいか
96: warnx("%s is too large (ignore %zd bytes)",
97: filename.c_str(), (ssize_t)st.st_size - size);
98: }
99:
100: // 読み込む
101: ssize_t n = read(fd, &imagebuf[0], size);
102: if (n < 0) {
103: warn("ROM \"%s\" read failed", filename.c_str());
104: return false;
105: }
106: if (n < size) {
107: warnx("ROM \"%s\" read too short", filename.c_str());
108: return false;
109: }
110:
111: fd.Close();
112:
113: mem = &imagebuf[0];
1.1 root 114: return true;
115: }
116:
1.1.1.12! root 117: busdata
1.1 root 118: ROMDevice::Read8(uint32 addr)
119: {
1.1.1.12! root 120: busdata data;
1.1.1.8 root 121: data = mem[addr & mask];
1.1.1.12! root 122: data |= wait;
! 123: putlog(4, "$%08x.B -> $%02x", addr, data.Data());
1.1.1.8 root 124: return data;
1.1 root 125: }
126:
1.1.1.12! root 127: busdata
1.1 root 128: ROMDevice::Read16(uint32 addr)
129: {
1.1.1.12! root 130: busdata data;
1.1.1.10 root 131: data = be16toh(*(const uint16 *)&mem[addr & mask]);
1.1.1.12! root 132: data |= wait;
! 133: putlog(4, "$%08x.W -> $%04x", addr, data.Data());
1.1.1.8 root 134: return data;
1.1 root 135: }
136:
1.1.1.12! root 137: busdata
1.1 root 138: ROMDevice::Read32(uint32 addr)
139: {
1.1.1.12! root 140: busdata data;
1.1.1.10 root 141: data = be32toh(*(const uint32 *)&mem[addr & mask]);
1.1.1.12! root 142: data |= wait;
! 143: putlog(4, "$%08x.L -> $%08x", addr, data.Data());
1.1.1.8 root 144: return data;
1.1 root 145: }
146:
1.1.1.12! root 147: busdata
1.1 root 148: ROMDevice::Write8(uint32 addr, uint32 data)
149: {
1.1.1.12! root 150: busdata r = write_op;
1.1.1.8 root 151: putlog(4, "$%08x.B <- $%02x", addr, data);
1.1.1.12! root 152: r |= wait;
! 153: return r;
1.1 root 154: }
155:
1.1.1.12! root 156: busdata
1.1 root 157: ROMDevice::Write16(uint32 addr, uint32 data)
158: {
1.1.1.12! root 159: busdata r = write_op;
1.1.1.8 root 160: putlog(4, "$%08x.W <- $%04x", addr, data);
1.1.1.12! root 161: r |= wait;
! 162: return r;
1.1 root 163: }
164:
1.1.1.12! root 165: busdata
1.1 root 166: ROMDevice::Write32(uint32 addr, uint32 data)
167: {
1.1.1.12! root 168: busdata r = write_op;
1.1.1.8 root 169: putlog(4, "$%08x.L <- $%08x", addr, data);
1.1.1.12! root 170: r |= wait;
! 171: return r;
1.1 root 172: }
173:
1.1.1.12! root 174: busdata
1.1 root 175: ROMDevice::Peek8(uint32 addr)
176: {
177: return mem[addr & mask];
178: }
1.1.1.10 root 179:
1.1.1.12! root 180: // アクセスウェイト [clock] を設定。
! 181: void
! 182: ROMDevice::SetWait(uint32 wait_)
! 183: {
! 184: uint32 clock_nsec = mpu->GetClock_nsec();
! 185:
! 186: wait = busdata::Wait(wait_ * clock_nsec);
! 187: }
! 188:
1.1.1.10 root 189: // ファイル名を返す。なければ NULL を返す。
190: const char *
191: ROMDevice::GetFilename() const
192: {
193: if (filename.empty()) {
194: return NULL;
195: } else {
196: return filename.c_str();
197: }
198: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.