|
|
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.13 root 41: ROMDevice::ROMDevice(uint objid_)
1.1.1.11 root 42: : inherited(objid_)
1.1 root 43: {
44: mask = 0xffffffff;
45: }
46:
47: ROMDevice::~ROMDevice()
48: {
49: }
50:
1.1.1.14 root 51: // ROM 用の領域を用意する。
1.1.1.15! root 52: // 失敗した場合は warn 系でエラーメッセージを表示して false を返す。
1.1.1.14 root 53: bool
54: ROMDevice::AllocROM(uint len, uint8 fill)
55: {
56: imagebuf.reset(new(std::nothrow) uint8 [len]);
57: if ((bool)imagebuf == false) {
1.1.1.15! root 58: warnx("Could not allocate %u bytes at %s", len, __method__);
1.1.1.14 root 59: return false;
60: }
61: memset(&imagebuf[0], fill, len);
62: mem = &imagebuf[0];
63: mask = len - 1;
64:
65: return true;
66: }
67:
1.1 root 68: // name の ROM を探してロードする。
69: // name はパスを含まないファイル名のみ。パスはこちらで探す。
1.1.1.15! root 70: // 失敗した場合は warn 系でエラーメッセージを表示して false を返す。
1.1 root 71: bool
1.1.1.13 root 72: ROMDevice::LoadROM(const char *name, uint size)
1.1 root 73: {
1.1.1.7 root 74: struct stat st;
75:
1.1.1.13 root 76: assert(size != 0);
1.1.1.7 root 77:
78: // ファイル名
1.1.1.3 root 79: filename = gMainApp.SearchFile(name);
1.1 root 80: if (filename.empty()) {
1.1.1.2 root 81: warnx("%s not found", name);
1.1 root 82: return false;
83: }
84:
1.1.1.7 root 85: // メモリを確保
1.1.1.14 root 86: imagebuf.reset(new(std::nothrow) uint8 [size]);
1.1.1.7 root 87: if ((bool)imagebuf == false) {
1.1.1.15! root 88: warnx("ROM \"%s\": Could not allocate %u bytes",
1.1.1.7 root 89: filename.c_str(), size);
90: return false;
91: }
92:
1.1 root 93: // オープン
1.1.1.7 root 94: autofd fd = open(filename.c_str(), O_RDONLY);
95: if (fd < 0) {
96: warn("ROM \"%s\"", filename.c_str());
1.1 root 97: return false;
98: }
99:
1.1.1.7 root 100: // ファイルサイズを調べる
101: if (fstat(fd, &st) < 0) {
102: warn("ROM \"%s\" stat failed", filename.c_str());
103: return false;
104: }
105:
106: if (st.st_size < size) {
1.1.1.13 root 107: warnx("ROM \"%s\" is too short (filesize is expected %u but %jd)",
1.1.1.7 root 108: filename.c_str(), size, (intmax_t)st.st_size);
109: return false;
110: }
111: if (st.st_size > size) {
112: // 大きすぎるほうはワーニングだけでいいか
1.1.1.13 root 113: warnx("%s is too large (ignore %zu bytes)",
114: filename.c_str(), (size_t)st.st_size - size);
1.1.1.7 root 115: }
116:
117: // 読み込む
118: ssize_t n = read(fd, &imagebuf[0], size);
119: if (n < 0) {
120: warn("ROM \"%s\" read failed", filename.c_str());
121: return false;
122: }
123: if (n < size) {
124: warnx("ROM \"%s\" read too short", filename.c_str());
125: return false;
126: }
127:
128: fd.Close();
129:
130: mem = &imagebuf[0];
1.1 root 131: return true;
132: }
133:
1.1.1.12 root 134: busdata
1.1.1.13 root 135: ROMDevice::Read(busaddr addr)
1.1 root 136: {
1.1.1.12 root 137: busdata data;
1.1 root 138:
1.1.1.13 root 139: uint32 paddr = addr.Addr() & ~3U;
140: data = be32toh(*(const uint32 *)&mem[paddr & mask]);
1.1.1.12 root 141: data |= wait;
1.1.1.13 root 142: data |= BusData::Size4;
143: putlog(4, "$%08x -> $%08x", paddr, data.Data());
1.1.1.8 root 144: return data;
1.1 root 145: }
146:
1.1.1.12 root 147: busdata
1.1.1.13 root 148: ROMDevice::Write(busaddr addr, uint32 data)
1.1 root 149: {
1.1.1.12 root 150: busdata r = write_op;
1.1.1.13 root 151: putlog(4, "$%08x.%u <- $%0*x", addr.Addr(), addr.GetSize(),
152: addr.GetSize() * 2, data);
1.1.1.12 root 153: r |= wait;
1.1.1.13 root 154: r |= BusData::Size4;
1.1.1.12 root 155: return r;
1.1 root 156: }
157:
1.1.1.12 root 158: busdata
1.1.1.13 root 159: ROMDevice::Peek1(uint32 addr)
1.1 root 160: {
161: return mem[addr & mask];
162: }
1.1.1.10 root 163:
1.1.1.12 root 164: // アクセスウェイト [clock] を設定。
165: void
166: ROMDevice::SetWait(uint32 wait_)
167: {
1.1.1.15! root 168: wait = busdata::Wait(wait_ * mpu->GetClock_tsec());
1.1.1.12 root 169: }
170:
1.1.1.10 root 171: // ファイル名を返す。なければ NULL を返す。
172: const char *
173: ROMDevice::GetFilename() const
174: {
175: if (filename.empty()) {
176: return NULL;
177: } else {
178: return filename.c_str();
179: }
180: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.