|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2021 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: #include "sramedit.h" ! 8: #include <array> ! 9: ! 10: // アクセスヘルパー ! 11: ! 12: uint32 read8(uint32 offset); ! 13: uint32 read16(uint32 offset); ! 14: uint32 read32(uint32 offset); ! 15: void write8(uint32 offset, uint32 val); ! 16: void write16(uint32 offset, uint32 val); ! 17: void write32(uint32 offset, uint32 val); ! 18: uint32 read8(const sraminfo_t&); ! 19: uint32 read16(const sraminfo_t&); ! 20: uint32 read32(const sraminfo_t&); ! 21: void write8(const sraminfo_t&, uint32 val); ! 22: void write16(const sraminfo_t&, uint32 val); ! 23: void write32(const sraminfo_t&, uint32 val); ! 24: int update8(const sraminfo_t&, uint32 val); ! 25: int update16(const sraminfo_t&, uint32 val); ! 26: int update32(const sraminfo_t&, uint32 val); ! 27: ! 28: uint32 ! 29: read8(uint32 offset) ! 30: { ! 31: return sram[offset]; ! 32: } ! 33: ! 34: uint32 ! 35: read16(uint32 offset) ! 36: { ! 37: uint32 h = read8(offset) << 8; ! 38: uint32 l = read8(offset + 1); ! 39: ! 40: return (h | l); ! 41: } ! 42: ! 43: uint32 ! 44: read32(uint32 offset) ! 45: { ! 46: uint32 h = read16(offset) << 16; ! 47: uint32 l = read16(offset + 2); ! 48: ! 49: return (h | l); ! 50: } ! 51: ! 52: void ! 53: write8(uint32 offset, uint32 val) ! 54: { ! 55: sram[offset] = (uint8)val; ! 56: } ! 57: ! 58: void ! 59: write16(uint32 offset, uint32 val) ! 60: { ! 61: write8(offset, val >> 8); ! 62: write8(offset + 1, val & 0xff); ! 63: } ! 64: ! 65: void ! 66: write32(uint32 offset, uint32 val) ! 67: { ! 68: write16(offset, val >> 16); ! 69: write16(offset + 2, val & 0xffff); ! 70: } ! 71: ! 72: uint32 read8(const sraminfo_t& si) { return read8(si.offset); } ! 73: uint32 read16(const sraminfo_t& si) { return read16(si.offset); } ! 74: uint32 read32(const sraminfo_t& si) { return read32(si.offset); } ! 75: void write8(const sraminfo_t& si, uint32 val) { ! 76: return write8(si.offset, val); ! 77: } ! 78: void write16(const sraminfo_t& si, uint32 val) { ! 79: return write16(si.offset, val); ! 80: } ! 81: void write32(const sraminfo_t& si, uint32 val) { ! 82: return write32(si.offset, val); ! 83: } ! 84: ! 85: int ! 86: update8(const sraminfo_t& si, uint32 val) ! 87: { ! 88: if (read8(si) == val) { ! 89: return 0; ! 90: } ! 91: write8(si, val); ! 92: return 1; ! 93: } ! 94: ! 95: int ! 96: update16(const sraminfo_t& si, uint32 val) ! 97: { ! 98: if (read16(si) == val) { ! 99: return 0; ! 100: } ! 101: write16(si, val); ! 102: return 1; ! 103: } ! 104: ! 105: int ! 106: update32(const sraminfo_t& si, uint32 val) ! 107: { ! 108: if (read32(si) == val) { ! 109: return 0; ! 110: } ! 111: write32(si, val); ! 112: return 1; ! 113: } ! 114: ! 115: // ! 116: // 個別処理 ! 117: // ! 118: ! 119: //----- ramsize ! 120: ! 121: static std::string ! 122: r_ramsize(const sraminfo_t& si) ! 123: { ! 124: uint32 v = read32(si); ! 125: std::string res = string_format("$%08x", v); ! 126: if (v % (1024 * 1024) == 0) { ! 127: res += string_format(" (%dMB)", v / 1024 / 1024); ! 128: } ! 129: return res; ! 130: } ! 131: ! 132: static int ! 133: w_ramsize(const sraminfo_t& si, const std::string& input) ! 134: { ! 135: char *end; ! 136: uint32 newval; ! 137: ! 138: errno = 0; ! 139: newval = strtoul(input.c_str(), &end, 10); ! 140: // 後ろに M が付くのだけ許容する? ! 141: if (end == input.c_str() || errno == ERANGE || ! 142: (*end != '\0' && *end != 'm' && *end != 'M')) { ! 143: warnx("%s='%s': bad parameter", si.name, input.c_str()); ! 144: return -1; ! 145: } ! 146: newval *= 1024 * 1024; ! 147: ! 148: return update32(si, newval); ! 149: } ! 150: ! 151: static const std::string ! 152: h_ramsize(const sraminfo_t& si) ! 153: { ! 154: return string_format("%s = { 4..12 }", si.name); ! 155: } ! 156: ! 157: //----- romaddr ! 158: ! 159: static std::string ! 160: r_romaddr(const sraminfo_t& si) ! 161: { ! 162: uint32 v = read32(si); ! 163: std::string res = string_format("$%08x", v); ! 164: if (0xfc0000 <= v && v < 0xfc0020) { ! 165: res += string_format(" (SCSI%d)", (v - 0xfc0000) / 4); ! 166: } ! 167: return res; ! 168: } ! 169: ! 170: static int ! 171: w_romaddr(const sraminfo_t& si, const std::string& input) ! 172: { ! 173: char *end; ! 174: uint32 newval; ! 175: ! 176: errno = 0; ! 177: if (starts_with_ignorecase(input, "scsi")) { ! 178: const char *start = input.c_str() + 4; ! 179: int id = strtoul(start, &end, 10); ! 180: if (end == start || *end != '\0' || errno == ERANGE) { ! 181: warnx("%s='%s': bad SCSI ID", si.name, input.c_str()); ! 182: return -1; ! 183: } ! 184: newval = 0xfc0000 + id * 4; ! 185: } else { ! 186: newval = strtoul(input.c_str(), &end, 16); ! 187: if (end == input.c_str() || *end != '\0' || errno == ERANGE) { ! 188: warnx("%s='%s': bad address", si.name, input.c_str()); ! 189: } ! 190: if (newval > 0xffffff) { ! 191: warnx("%s='%s': bad address", si.name, input.c_str()); ! 192: } ! 193: } ! 194: ! 195: return update32(si, newval); ! 196: } ! 197: ! 198: static const std::string ! 199: h_romaddr(const sraminfo_t& si) ! 200: { ! 201: return string_format("%s = { [0x]<hexaddr> | scsi<0..7> }", si.name); ! 202: } ! 203: ! 204: //--- ! 205: ! 206: static std::string ! 207: r_ramaddr(const sraminfo_t& si) ! 208: { ! 209: uint32 v = read32(si); ! 210: return string_format("$%08x", v); ! 211: } ! 212: ! 213: //----- bootdev ! 214: ! 215: static std::string ! 216: r_bootdev(const sraminfo_t& si) ! 217: { ! 218: uint32 v = read16(si); ! 219: std::string res = string_format("$%04x ", v); ! 220: ! 221: if (v == 0x0000) { ! 222: res += "STD (FD->HD->ROM->RAM)"; ! 223: } else if ((v & 0xf0ff) == 0x8000) { ! 224: res += string_format("SASI%d", (v >> 8) & 0x0f); ! 225: } else if ((v & 0xf0ff) == 0x9070) { ! 226: res += string_format("FD%d", (v >> 8) & 0x0f); ! 227: } else if (v == 0xa000) { ! 228: res += "ROM"; ! 229: } else if (v == 0xb000) { ! 230: res += "RAM"; ! 231: } else { ! 232: res += "?"; ! 233: } ! 234: ! 235: return res; ! 236: } ! 237: ! 238: static int ! 239: w_bootdev(const sraminfo_t& si, const std::string& input) ! 240: { ! 241: const char *start; ! 242: char *end; ! 243: int32 newval; ! 244: ! 245: if (strcasecmp(input.c_str(), "std") == 0) { ! 246: newval = 0x0000; ! 247: } else if (starts_with_ignorecase(input, "sasi")) { ! 248: errno = 0; ! 249: start = input.c_str() + 4; ! 250: int id = strtoul(start, &end, 10); ! 251: if (end == start || *end != '\0' || errno == ERANGE) { ! 252: warnx("%s='%s': bad SASI ID", si.name, input.c_str()); ! 253: return -1; ! 254: } ! 255: newval = 0x8000 + (id << 8); ! 256: } else if (starts_with_ignorecase(input, "fd")) { ! 257: errno = 0; ! 258: start = input.c_str() + 4; ! 259: int id = strtoul(start, &end, 10); ! 260: if (end == start || *end != '\0' || errno == ERANGE) { ! 261: warnx("%s='%s': bad SASI ID", si.name, input.c_str()); ! 262: return -1; ! 263: } ! 264: newval = 0x9070 + (id << 8); ! 265: } else if (strcasecmp(input.c_str(), "rom") == 0) { ! 266: newval = 0xa000; ! 267: } else if (strcasecmp(input.c_str(), "ram") == 0) { ! 268: newval = 0xb000; ! 269: } else { ! 270: warnx("%s='%s': bad parameter", si.name, input.c_str()); ! 271: return -1; ! 272: } ! 273: ! 274: return update16(si, newval); ! 275: } ! 276: ! 277: static const std::string ! 278: h_bootdev(const sraminfo_t& si) ! 279: { ! 280: return string_format("%s = { std | sasi<0..15> | fd<0..3> | rom | ram }", ! 281: si.name); ! 282: } ! 283: ! 284: ! 285: static std::string ! 286: r_rs232c(const sraminfo_t& si) ! 287: { ! 288: uint32 v = read16(si); ! 289: std::string res = string_format("$%04x (", v); ! 290: ! 291: std::array<std::string, 4> stopbit { ! 292: "2", ! 293: "1", ! 294: "1.5", ! 295: "2", ! 296: }; ! 297: res += "stop="; ! 298: res += stopbit[(v >> 14)]; ! 299: res += ','; ! 300: ! 301: std::array<std::string, 4> parity { ! 302: "none", ! 303: "odd", ! 304: "even", ! 305: "none", ! 306: }; ! 307: res += "parity="; ! 308: res += parity[(v >> 12) & 3]; ! 309: res += ','; ! 310: ! 311: res += string_format("%dbit,", ((v >> 10) & 3) + 5); ! 312: ! 313: std::array<int, 9> speed { ! 314: 75, ! 315: 150, ! 316: 300, ! 317: 600, ! 318: 1200, ! 319: 2400, ! 320: 4800, ! 321: 9600, ! 322: 17361, // X68030 only ! 323: }; ! 324: uint32 vs = (v & 0x0f); ! 325: if (vs < speed.size()) { ! 326: res += string_format("%dbps", speed[vs]); ! 327: } else { ! 328: res += "?bps"; ! 329: } ! 330: ! 331: res += ')'; ! 332: return res; ! 333: } ! 334: ! 335: static std::string ! 336: r_led(const sraminfo_t& si) ! 337: { ! 338: uint8 v = read8(si); ! 339: std::string res = string_format("$%02x", v); ! 340: ! 341: std::array<std::string, 8> names { ! 342: "", // b7 ! 343: "Zenkaku", // b6 ! 344: "Hiragana", // b5 ! 345: "INS", // b4 ! 346: "CAPS", // b3 ! 347: "Code", // b2 ! 348: "Roma", // b1 ! 349: "Kana", // b0 ! 350: }; ! 351: std::string map; ! 352: uint8 b = 0x40; ! 353: for (int i = 0; b; i++, b >>= 1) { ! 354: if ((v & b) != 0) { ! 355: if (map.empty() == false) { ! 356: map += ','; ! 357: } ! 358: map += names[i]; ! 359: } ! 360: } ! 361: ! 362: if (map.empty() == false) { ! 363: res += ' '; ! 364: res += map; ! 365: } ! 366: return res; ! 367: } ! 368: ! 369: static std::string ! 370: r_crtmod(const sraminfo_t& si) ! 371: { ! 372: uint8 v = read8(si); ! 373: return string_format("$%02x", v); ! 374: } ! 375: ! 376: static std::string ! 377: r_contrast(const sraminfo_t& si) ! 378: { ! 379: uint8 v = read8(si); ! 380: return string_format("$%02x", v); ! 381: } ! 382: ! 383: static std::string ! 384: r_sram_use(const sraminfo_t& si) ! 385: { ! 386: uint8 v = read8(si); ! 387: std::string res; ! 388: ! 389: if (v == 0) { ! 390: res = "NotUsed"; ! 391: } else if (v == 1) { ! 392: res = "SRAMDISK"; ! 393: } else if (v == 2) { ! 394: res = "Program"; ! 395: } else { ! 396: res = string_format("$%02x ?", v); ! 397: } ! 398: return res; ! 399: } ! 400: ! 401: //----- key_delay, key_repeat ! 402: ! 403: static std::string ! 404: r_key_repeat(const sraminfo_t& si) ! 405: { ! 406: uint8 v = read8(si); ! 407: std::string res = string_format("$%02x ", v); ! 408: ! 409: if (v < 16) { ! 410: int msec; ! 411: if (si.offset == 0x3a) { ! 412: msec = 200 + 100 * v; ! 413: } else { ! 414: msec = 30 + 5 * v * v; ! 415: } ! 416: res += string_format("(%dmsec)", msec); ! 417: } else { ! 418: res += "(??msec)"; ! 419: } ! 420: return res; ! 421: } ! 422: ! 423: static int ! 424: w_key_repeat(const sraminfo_t& si, const std::string& input) ! 425: { ! 426: char *end; ! 427: int newval; ! 428: ! 429: errno = 0; ! 430: newval = strtoul(input.c_str(), &end, 10); ! 431: if (end == input.c_str() || *end != '\0' || errno == ERANGE) { ! 432: warnx("%s='%s': bad parameter", si.name, input.c_str()); ! 433: return 0; ! 434: } ! 435: ! 436: // 値は10進数、直接指定 ! 437: if (newval < 0 || newval > 255) { ! 438: warnx("%s='%d': invalid range", si.name, newval); ! 439: return -1; ! 440: } ! 441: ! 442: return update8(si, newval); ! 443: } ! 444: ! 445: static const std::string ! 446: h_key_repeat(const sraminfo_t& si) ! 447: { ! 448: return string_format("%s = { 0..15 }", si.name); ! 449: } ! 450: ! 451: //----- ! 452: ! 453: static std::string ! 454: r_boottime(const sraminfo_t& si) ! 455: { ! 456: uint32 v = read32(si); ! 457: return string_format("%u (%u:%u)", v, (v / 60), (v % 60)); ! 458: } ! 459: ! 460: static std::string ! 461: r_bootcount(const sraminfo_t& si) ! 462: { ! 463: uint32 v = read32(si); ! 464: return string_format("%d", v); ! 465: } ! 466: ! 467: ! 468: static std::string ! 469: r_debugger(const sraminfo_t& si) ! 470: { ! 471: uint8 v = read8(si); ! 472: std::string res; ! 473: ! 474: if (v == 0x00) { ! 475: res = "off"; ! 476: } else if (v == 0xff) { ! 477: res = "on"; ! 478: } else { ! 479: res = string_format("on? (0x%02x)", v); ! 480: } ! 481: return res; ! 482: } ! 483: ! 484: static int ! 485: w_debugger(const sraminfo_t& si, const std::string& input) ! 486: { ! 487: uint8 newval; ! 488: ! 489: if (strcasecmp(input.c_str(), "off") == 0) { ! 490: newval = 0; ! 491: } else if (strcasecmp(input.c_str(), "on") == 0) { ! 492: newval = 0xff; ! 493: } else { ! 494: warnx("%s='%s': bad parameter", si.name, input.c_str()); ! 495: return -1; ! 496: } ! 497: ! 498: return update8(si, newval); ! 499: } ! 500: ! 501: static const std::string ! 502: h_debugger(const sraminfo_t& si) ! 503: { ! 504: return string_format("%s = { on | off }", si.name); ! 505: } ! 506: ! 507: // パラメータ一覧 ! 508: #define RWH(name) r_##name, w_##name, h_##name ! 509: std::vector<sraminfo_t> sraminfo = { ! 510: // offset name reader writer help ! 511: { 0x08, "ramsize", RWH(ramsize) }, ! 512: { 0x0c, "romaddr", RWH(romaddr) }, ! 513: { 0x10, "ramaddr", r_ramaddr, NULL }, ! 514: { 0x14, "alarm_until?" }, ! 515: { 0x18, "bootdev", RWH(bootdev) }, ! 516: { 0x1a, "rs232c", r_rs232c, NULL }, ! 517: { 0x1c, "led", r_led, NULL }, ! 518: { 0x1d, "crtmod", r_crtmod, NULL }, ! 519: { 0x1e, "alarm_op?" }, ! 520: { 0x22, "alarm_time?" }, ! 521: { 0x26, "alarm_en?" }, ! 522: { 0x27, "tvctrl_en?" }, ! 523: { 0x28, "contrast", r_contrast, NULL }, ! 524: { 0x29, "fd_eject?" }, ! 525: { 0x2a, "tvctrl_code?" }, ! 526: { 0x2b, "keyboard?" }, ! 527: { 0x2c, "calc_font" }, ! 528: { 0x2d, "sram_use", r_sram_use, NULL }, ! 529: { 0x2e, "textpal0" }, ! 530: { 0x30, "textpal1" }, ! 531: { 0x32, "textpal2" }, ! 532: { 0x34, "textpal3" }, ! 533: { 0x36, "textpal4" }, ! 534: { 0x38, "textpal8" }, ! 535: { 0x3a, "key_delay", RWH(key_repeat) }, ! 536: { 0x3b, "key_repeat", RWH(key_repeat) }, ! 537: { 0x3c, "prn_timeout?" }, ! 538: { 0x40, "boottime", r_boottime, NULL }, ! 539: { 0x44, "bootcount",r_bootcount, NULL }, ! 540: { 0x48, "romdisk_fat?" }, ! 541: { 0x58, "debugger", RWH(debugger) }, ! 542: { 0x59, "charmode" }, ! 543: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.