|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: //
8: // SRAM
9: //
1.1.1.9 root 10:
1.1 root 11: // SRAM はビッグエンディアンのままメモリに置かれるので、
12: // 必要ならアクセス時に都度変換すること。
13:
1.1.1.9 root 14: #include "sram.h"
1.1.1.10 root 15: #include "config.h"
1.1.1.9 root 16: #include "mainapp.h"
1.1.1.11 root 17: #include "mainram.h"
1.1.1.13 root 18: #include <sys/mman.h>
1.1.1.9 root 19:
20: // コンストラクタ
1.1 root 21: SRAMDevice::SRAMDevice()
1.1.1.11 root 22: : inherited(OBJ_SRAM)
1.1 root 23: {
24: }
25:
1.1.1.9 root 26: // デストラクタ
1.1 root 27: SRAMDevice::~SRAMDevice()
28: {
1.1.1.13 root 29: if ((bool)file) {
30: // この場合は mem は file が管理している。
31: file.reset();
32: } else {
33: if (mem) {
34: munmap(mem, sramsize);
35: }
36: }
1.1 root 37: }
38:
1.1.1.11 root 39: // 初期化
1.1 root 40: bool
41: SRAMDevice::Init()
42: {
1.1.1.13 root 43: // SRAM ファイルをオープン。
44: if (gMainApp.GetVMDir().empty()) {
1.1.1.16 root 45: // VM ディレクトリ指定がなければ、オンメモリに初期値を用意する。
46: // Human68k モードで VM ディレクトリを指定しない場合に起きる。
1.1.1.13 root 47: void *m = mmap(NULL, sramsize, PROT_READ | PROT_WRITE,
48: MAP_ANON | MAP_SHARED, -1, 0);
49: if (m == MAP_FAILED) {
1.1.1.17! root 50: warn("%s: mmap", __method__);
1.1.1.13 root 51: return false;
52: }
53: mem = (uint8 *)m;
1.1.1.16 root 54: memcpy(mem, &initialdata[0], initialdata.size());
1.1.1.13 root 55: } else {
1.1.1.16 root 56: // VM ディレクトリ指定があれば、ファイルを開く。
1.1.1.13 root 57: filename = gMainApp.GetVMDir() + "SRAM.DAT";
1.1.1.15 root 58: try {
59: file.reset(new MappedFile());
60: } catch (...) { }
61: if ((bool)file == false) {
62: warnx("Failed to initialize MappedFile at %s", __method__);
63: return false;
64: }
1.1.1.13 root 65: file->SetFilename(filename);
66: file->SetDispname(string_format("SRAM \"%s\"", filename.c_str()));
1.1.1.16 root 67: mem = file->OpenCreate(sramsize, &initialdata[0], initialdata.size());
1.1.1.13 root 68: if (mem == NULL) {
1.1.1.17! root 69: // エラーメッセージは表示済み。
1.1.1.13 root 70: return false;
71: }
1.1 root 72: }
73:
1.1.1.10 root 74: // SRAM の RAM 容量欄を設定値に同期させる。
75: // この処理はアプリケーション起動時に一回行われるのみで、
76: // その後の VM 内のリセット等では動作しない。
1.1.1.17! root 77: if (gConfig->Find("sram-sync-ramsize").AsBool()) {
1.1.1.10 root 78: SyncRAMSize();
79: }
80:
1.1 root 81: return true;
82: }
83:
1.1.1.9 root 84: // リセット
1.1.1.6 root 85: void
1.1.1.9 root 86: SRAMDevice::ResetHard(bool poweron)
1.1.1.6 root 87: {
88: // XXX 未調査
89: writeable = false;
90: }
91:
1.1.1.10 root 92: // SRAM の RAM 容量欄を設定値に同期させる。
93: void
94: SRAMDevice::SyncRAMSize()
95: {
96: // SRAM の内容が無効なら何もしない。
97: static const std::array<uint8, 7> magic {
98: 0x82, 0x77, '6', '8', '0', '0', '0'
99: };
100: for (int i = 0; i < magic.size(); i++) {
101: if (mem[i] != magic[i]) {
102: return;
103: }
104: }
105:
1.1.1.15 root 106: uint32 ramsize = (uint32)GetMainRAMDevice()->GetSize();
1.1.1.10 root 107:
108: // 値が違う時だけ表示したいので一旦読み出して比較
109: uint32 cursize;
110: cursize = mem[0x08] << 24;
111: cursize |= mem[0x09] << 16;
112: cursize |= mem[0x0a] << 8;
113: cursize |= mem[0x0b];
114: if (cursize != ramsize) {
1.1.1.13 root 115: if (gMainApp.GetVMDir().empty()) {
116: // Human68k モードで -c のない時は表示不要。ダミー SRAM なので。
117: } else {
118: warnx("SRAM: Update ramsize %uMB", ramsize / 1024 / 1024);
119: }
1.1.1.10 root 120:
121: mem[0x08] = ramsize >> 24;
122: mem[0x09] = ramsize >> 16;
123: mem[0x0a] = ramsize >> 8;
124: mem[0x0b] = ramsize;
125: }
126: }
127:
1.1.1.3 root 128: // アドレスデコーダ
1.1.1.12 root 129: inline uint32
1.1.1.3 root 130: SRAMDevice::Decoder(uint32 addr) const
131: {
1.1.1.4 root 132: uint32 offset = addr - baseaddr;
1.1.1.13 root 133: assertmsg(offset < file->GetMemSize(),
134: "offset=%x memlen=%x", offset, (uint)file->GetMemSize());
1.1.1.4 root 135: return offset;
1.1.1.3 root 136: }
137:
1.1.1.12 root 138: busdata
1.1.1.13 root 139: SRAMDevice::Read(busaddr addr)
1.1 root 140: {
1.1.1.13 root 141: uint32 offset = Decoder(addr.Addr());
142: busdata data;
1.1.1.4 root 143:
1.1.1.13 root 144: data = Get16(offset & ~1U);
145: data |= BusData::Size2;
146: putlog(2, "$%06x -> $%04x", addr.Addr() & ~1U, data.Data());
1.1.1.4 root 147: return data;
1.1 root 148: }
149:
1.1.1.12 root 150: busdata
1.1.1.13 root 151: SRAMDevice::Write(busaddr addr, uint32 data)
1.1 root 152: {
1.1.1.13 root 153: uint32 offset = Decoder(addr.Addr());
154: uint32 reqsize = addr.GetSize();
155: uint32 datasize = std::min(2 - (offset & 1), reqsize);
156: data >>= (reqsize - datasize) * 8;
1.1.1.3 root 157:
1.1 root 158: if (writeable) {
1.1.1.3 root 159: if (offset < 0x100) {
1.1.1.13 root 160: putlog(1, "$%06x.%c <- $%0*x", addr.Addr(),
161: (datasize == 1 ? 'B' : 'W'), datasize * 2, data);
162: }
163: if (datasize == 1) {
164: mem[offset] = data;
165: } else {
166: *(uint16 *)&mem[offset] = htobe16(data);
1.1 root 167: }
168: } else {
1.1.1.13 root 169: putlog(1, "Write protected $%06x.%c <- $%0*x", addr.Addr(),
170: (datasize == 1 ? 'B' : 'W'), datasize * 2, data);
1.1 root 171: }
1.1.1.13 root 172:
173: busdata r = busdata::Size(datasize);
174: return r;
1.1 root 175: }
176:
1.1.1.12 root 177: busdata
1.1.1.13 root 178: SRAMDevice::Peek1(uint32 addr)
1.1 root 179: {
1.1.1.3 root 180: uint32 offset = Decoder(addr);
1.1.1.13 root 181: uint32 data = Get16(offset & ~1U);
1.1.1.3 root 182:
1.1.1.13 root 183: if ((offset & 1) == 0) {
184: return data >> 8;
1.1 root 185: } else {
1.1.1.13 root 186: return data & 0xff;
1.1 root 187: }
1.1.1.11 root 188: }
1.1.1.4 root 189:
1.1.1.12 root 190: bool
1.1.1.13 root 191: SRAMDevice::Poke1(uint32 addr, uint32 data)
1.1.1.11 root 192: {
193: // WriteEnable() に関わらず変更する。
194: // また Get8()、Get16() はこの変更の影響を受けないことに注意。
195:
196: if ((int32)data >= 0) {
197: uint32 offset = Decoder(addr);
198: mem[offset] = data;
199: }
1.1.1.12 root 200: return true;
1.1 root 201: }
202:
203: void
1.1.1.11 root 204: SRAMDevice::WriteEnable(bool value)
1.1 root 205: {
206: if (writeable == false && value == true) {
1.1.1.10 root 207: putlog(1, "Write Enable");
1.1 root 208: } else if (writeable == true && value == false) {
1.1.1.10 root 209: putlog(1, "Write Disable");
1.1 root 210: }
211:
212: writeable = value;
213: }
1.1.1.4 root 214:
1.1.1.11 root 215: // SRAM から副作用なく読み出す。
216: // ただしホストファイル起動モードなら改変した値を返す。
1.1.1.4 root 217: uint32
1.1.1.13 root 218: SRAMDevice::Get16(uint32 offset) const
1.1.1.4 root 219: {
1.1.1.11 root 220: if (gMainApp.exec_file) {
221: switch (offset) {
222: case 0x0c: // ROM 起動アドレス(.L)
1.1.1.13 root 223: return (plutoaddr >> 16) & 0xffff;
1.1.1.11 root 224: case 0x0e:
1.1.1.13 root 225: return plutoaddr & 0xffff;
1.1.1.11 root 226:
227: case 0x18: // 起動デバイス(.W) を ROM($a000) にする
1.1.1.13 root 228: return 0xa000;
1.1.1.11 root 229:
230: default:
231: break;
232: }
1.1.1.4 root 233: }
1.1.1.11 root 234:
235: // 他は SRAM から
1.1.1.13 root 236: uint32 data = *(uint16 *)&mem[offset];
237: return be16toh(data);
1.1.1.4 root 238: }
1.1.1.10 root 239:
1.1.1.11 root 240: // SRAM から副作用なくロングワードで読み出す。
241: // ただしホストファイル起動モードなら改変した値を返す。
1.1.1.10 root 242: uint32
1.1.1.11 root 243: SRAMDevice::Get32(uint32 offset) const
1.1.1.10 root 244: {
245: uint32 data;
246:
1.1.1.11 root 247: data = Get16(offset) << 16;
248: data |= Get16(offset + 2);
1.1.1.10 root 249:
250: return data;
251: }
1.1.1.11 root 252:
1.1.1.16 root 253: // X68030 が初期化した SRAM の初期値。
1.1.1.11 root 254: //
255: // 0000: 82 77 36 38 30 30 30 57 00 40 00 00 00 fc 00 00 |.w68000W.@......|
256: // 0010: 00 ed 01 00 ff ff ff ff 00 00 4e 07 00 10 00 00 |..........N.....|
257: // 0020: 00 00 ff ff 00 00 07 00 0e 00 0d 00 00 00 00 00 |................|
258: // 0030: f8 3e ff c0 ff fe de 6c 40 22 03 02 00 08 00 00 |.>.....l@"......|
259: // 0040: 00 00 00 00 00 00 00 00 00 ff f4 00 04 00 01 01 |................|
1.1.1.16 root 260: // 0050: 00 00 00 20 00 03 f9 01 (00 00 00 00 00 00 00 00) |... ............|
261: /*static*/ std::array<uint8, 0x58>
262: SRAMDevice::initialdata {
1.1.1.11 root 263: 0x82, 0x77, 0x36, 0x38, 0x30, 0x30, 0x30, 0x57,
264: 0x00, 0x40, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
265: 0x00, 0xed, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
266: 0x00, 0x00, 0x4e, 0x07, 0x00, 0x10, 0x00, 0x00,
267: 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00,
268: 0x0e, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
269: 0xf8, 0x3e, 0xff, 0xc0, 0xff, 0xfe, 0xde, 0x6c,
270: 0x40, 0x22, 0x03, 0x02, 0x00, 0x08, 0x00, 0x00,
271: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272: 0x00, 0xff, 0xf4, 0x00, 0x04, 0x00, 0x01, 0x01,
273: 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0xf9, 0x01,
274: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.