|
|
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.10! root 17: #include "ram.h"
! 18: #include <array>
1.1.1.9 root 19:
20: // グローバル参照用
21: SRAMDevice *gSRAM;
1.1 root 22:
1.1.1.9 root 23: // コンストラクタ
1.1 root 24: SRAMDevice::SRAMDevice()
1.1.1.7 root 25: : inherited("SRAM")
1.1 root 26: {
27: devaddr = baseaddr;
1.1.1.4 root 28: devlen = 0x4000;
1.1 root 29: }
30:
1.1.1.9 root 31: // デストラクタ
1.1 root 32: SRAMDevice::~SRAMDevice()
33: {
1.1.1.9 root 34: gSRAM = NULL;
1.1 root 35: }
36:
37: bool
38: SRAMDevice::Init()
39: {
1.1.1.10! root 40: filename = gMainApp.GetVMDir() + "SRAM.DAT";
1.1.1.4 root 41: file.SetFilename(filename);
42: file.SetDispname(string_format("SRAM \"%s\"", filename.c_str()));
43: mem = file.OpenCreate(16 * 1024);
44: if (mem == NULL) {
1.1 root 45: return false;
46: }
47:
1.1.1.10! root 48: // SRAM の RAM 容量欄を設定値に同期させる。
! 49: // この処理はアプリケーション起動時に一回行われるのみで、
! 50: // その後の VM 内のリセット等では動作しない。
! 51: bool sync = gConfig->Find("sram-sync-ramsize").AsInt();
! 52: if (sync) {
! 53: SyncRAMSize();
! 54: }
! 55:
1.1 root 56: return true;
57: }
58:
1.1.1.9 root 59: // リセット
1.1.1.6 root 60: void
1.1.1.9 root 61: SRAMDevice::ResetHard(bool poweron)
1.1.1.6 root 62: {
63: // XXX 未調査
64: writeable = false;
65: }
66:
1.1.1.10! root 67: // SRAM の RAM 容量欄を設定値に同期させる。
! 68: void
! 69: SRAMDevice::SyncRAMSize()
! 70: {
! 71: // SRAM の内容が無効なら何もしない。
! 72: static const std::array<uint8, 7> magic {
! 73: 0x82, 0x77, '6', '8', '0', '0', '0'
! 74: };
! 75: for (int i = 0; i < magic.size(); i++) {
! 76: if (mem[i] != magic[i]) {
! 77: return;
! 78: }
! 79: }
! 80:
! 81: uint32 ramsize = gRAM->GetSize();
! 82:
! 83: // 値が違う時だけ表示したいので一旦読み出して比較
! 84: uint32 cursize;
! 85: cursize = mem[0x08] << 24;
! 86: cursize |= mem[0x09] << 16;
! 87: cursize |= mem[0x0a] << 8;
! 88: cursize |= mem[0x0b];
! 89: if (cursize != ramsize) {
! 90: // ここは Init() なので putmsg() は使えない
! 91: warnx("SRAM: Update ramsize %dMB", ramsize / 1024 / 1024);
! 92:
! 93: mem[0x08] = ramsize >> 24;
! 94: mem[0x09] = ramsize >> 16;
! 95: mem[0x0a] = ramsize >> 8;
! 96: mem[0x0b] = ramsize;
! 97: }
! 98: }
! 99:
1.1.1.3 root 100: // アドレスデコーダ
101: inline uint64
102: SRAMDevice::Decoder(uint32 addr) const
103: {
1.1.1.4 root 104: uint32 offset = addr - baseaddr;
105: assertmsg(offset < file.GetMemSize(),
106: "offset=%x memlen=%x", offset, (int)file.GetMemSize());
107: return offset;
1.1.1.3 root 108: }
109:
1.1 root 110: uint64
111: SRAMDevice::Read8(uint32 addr)
112: {
1.1.1.3 root 113: uint32 offset = Decoder(addr);
1.1.1.4 root 114: uint32 data;
115:
116: // ホストファイル起動モードなら起動アドレスとして Pluto-X を見せる。
1.1.1.8 root 117: if (gMainApp.exec_file) {
1.1.1.4 root 118: data = PeekHostBoot(offset);
119: if ((int32)data >= 0) {
120: if ((offset & 1) == 0) {
121: data = data >> 8;
122: } else {
123: data = data & 0xff;
124: }
125: return data;
126: }
127: }
128:
129: data = mem[offset];
130: return data;
1.1 root 131: }
132:
133: uint64
134: SRAMDevice::Read16(uint32 addr)
135: {
1.1.1.3 root 136: uint32 offset = Decoder(addr);
1.1.1.4 root 137: uint32 data;
138:
139: // ホストファイル起動モードなら起動アドレスとして Pluto-X を見せる。
1.1.1.8 root 140: if (gMainApp.exec_file) {
1.1.1.4 root 141: data = PeekHostBoot(offset);
142: if ((int32)data >= 0) {
143: return data;
144: }
145: }
146:
147: data = be16toh(*(uint16 *)&mem[offset]);
148: return data;
1.1 root 149: }
150:
151: uint64
152: SRAMDevice::Write8(uint32 addr, uint32 data)
153: {
1.1.1.3 root 154: uint32 offset = Decoder(addr);
155:
1.1 root 156: if (writeable) {
1.1.1.3 root 157: if (offset < 0x100) {
1.1.1.10! root 158: putlog(1, "$%06x.B <- $%02x", addr, data);
1.1 root 159: }
1.1.1.3 root 160: mem[offset] = data;
1.1 root 161: } else {
1.1.1.10! root 162: putlog(1, "Write protected $%06x.B <- $%02x", addr, data);
1.1 root 163: }
164: return 0;
165: }
166:
167: uint64
168: SRAMDevice::Write16(uint32 addr, uint32 data)
169: {
1.1.1.3 root 170: uint32 offset = Decoder(addr);
171:
1.1 root 172: if (writeable) {
1.1.1.3 root 173: if (offset < 0x100) {
1.1.1.10! root 174: putlog(1, "$%06x.W <- $%04x", addr, data);
1.1 root 175: }
1.1.1.3 root 176: *(uint16 *)&mem[offset] = htobe16(data);
1.1 root 177: } else {
1.1.1.10! root 178: putlog(1, "Write protected $%06x.W <- $%04x", addr, data);
1.1 root 179: }
180: return 0;
181: }
182:
183: uint64
184: SRAMDevice::Peek8(uint32 addr)
185: {
1.1.1.3 root 186: uint32 offset = Decoder(addr);
1.1.1.4 root 187:
188: // ホストファイル起動モードなら起動アドレスとして Pluto-X を見せる。
1.1.1.8 root 189: if (gMainApp.exec_file) {
1.1.1.4 root 190: uint32 data = PeekHostBoot(offset);
191: if ((int32)data >= 0) {
192: if ((offset & 1) == 0) {
193: data = data >> 8;
194: } else {
195: data = data & 0xff;
196: }
197: return data;
198: }
199: }
200:
1.1.1.3 root 201: return mem[offset];
1.1 root 202: }
203:
204: void
205: SRAMDevice::write_enable(bool value)
206: {
207: if (writeable == false && value == true) {
1.1.1.10! root 208: putlog(1, "Write Enable");
1.1 root 209: } else if (writeable == true && value == false) {
1.1.1.10! root 210: putlog(1, "Write Disable");
1.1 root 211: }
212:
213: writeable = value;
214: }
1.1.1.4 root 215:
216: // ホストファイル起動用の読み出し値を返す。
217: // offset はワード境界であること。戻り値はホストバイトオーダのワード値。
218: // 本来の SRAM の値を読み出してよいところについては (uint32)-1 を返す。
219: //
220: // mem[] は SRAM.DAT を直接 mmap(2) しており書き換えておくことは出来ないため、
221: // ホストファイル起動モードなら読み出し時に動的に値を返す。
222: uint32
223: SRAMDevice::PeekHostBoot(uint32 offset) const
224: {
225: switch (offset) {
226: case 0x0c: // ROM 起動アドレス(H)
227: return (plutoaddr >> 16);
228: case 0x0e: // ROM 起動アドレス(L)
229: return (plutoaddr & 0xffff);
230: case 0x18: // 起動デバイスを ROM にする
231: return 0xa000;
232: default:
233: break;
234: }
235: return (uint32)-1;
236: }
1.1.1.10! root 237:
! 238: // SRAM $ed000c.L ROM 起動アドレスを返す
! 239: uint32
! 240: SRAMDevice::GetROMAddr() const
! 241: {
! 242: uint32 data;
! 243:
! 244: data = mem[0x0c] << 24;
! 245: data |= mem[0x0d] << 16;
! 246: data |= mem[0x0e] << 8;
! 247: data |= mem[0x0f];
! 248:
! 249: return data;
! 250: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.