Created
October 20, 2025 14:48
-
-
Save uyjulian/ba9009843223e7e16ae9e5e828dc4ecc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # SPDX-License-Identifier: MIT | |
| # Generates information regarding feature support for Dragon Mechacon firmware. | |
| scmd_support_ranges_start = [0x00, 0x40, 0xC0, 0x80] | |
| # General S-Command support ranges | |
| scmd_support_ranges = { | |
| "5.00" : [0x27, 0x04, 0x00, 0x20], | |
| "5.02" : [0x28, 0x04, 0x00, 0x20], | |
| "5.04" : [0x29, 0x04, 0x00, 0x20], | |
| "5.06" : [0x29, 0x04, 0x00, 0x20], | |
| "5.06.mexico" : [0x37, 0x04, 0x00, 0x20], | |
| "5.10" : [0x36, 0x04, 0x00, 0x20], | |
| "5.12" : [0x29, 0x04, 0x00, 0x20], | |
| "5.14" : [0x3E, 0x04, 0x05, 0x20], | |
| "6.00" : [0x39, 0x04, 0x00, 0x20], | |
| "6.02" : [0x3C, 0x04, 0x00, 0x20], | |
| "6.04" : [0x3C, 0x04, 0x00, 0x20], | |
| "6.06" : [0x3F, 0x04, 0x00, 0x20], | |
| "6.10" : [0x3F, 0x04, 0x00, 0x20], | |
| "6.12" : [0x3F, 0x04, 0x00, 0x20], | |
| } | |
| # S-Command table address | |
| # 4 bytes command handler (lowest bit set -> thumb) | |
| scmd_table_addr = { | |
| "5.00" : 0x33AC0, | |
| "5.02" : 0x34014, | |
| "5.04" : 0x34210, | |
| "5.06" : 0x34218, | |
| "5.06.mexico" : 0x3422C, | |
| "5.10" : 0x3AB0C, | |
| "5.12" : 0x35E08, | |
| "5.14" : 0x3DC90, | |
| "6.00" : 0x35CC0, | |
| "6.02" : 0x36204, | |
| "6.04" : 0x36D04, | |
| "6.06" : 0x37090, | |
| "6.10" : 0x37104, | |
| "6.12" : 0x37F28, | |
| } | |
| # Sub S-Command 03 table address and length | |
| # 4 bytes command handler (lowest bit set -> thumb), 1 byte command number, 1 byte ???, 2 bytes padding | |
| scmd_03_table_addr_len = { | |
| "5.00" : [0x33BEC, 0x38], | |
| "5.02" : [0x34144, 0x38], | |
| "5.04" : [0x34344, 0x39], | |
| "5.06" : [0x3434C, 0x39], | |
| "5.06.mexico" : [0x34398, 0x39], | |
| "5.10" : [0x3AC74, 0x3D], | |
| "5.12" : [0x35F3C, 0x39], | |
| "5.14" : [0x3DE2C, 0x3D], | |
| "6.00" : [0x35E34, 0x3A], | |
| "6.02" : [0x36384, 0x3A], | |
| "6.04" : [0x36E84, 0x3A], | |
| "6.06" : [0x3721C, 0x3A], | |
| "6.10" : [0x37290, 0x3A], | |
| "6.12" : [0x380B4, 0x3A], | |
| } | |
| # TESTMODE command table address and length | |
| # 1 byte command number, 1 byte ???, 2 bytes padding, 4 bytes command handler (lowest bit set -> thumb) | |
| testmode_cmd_addr_len = { | |
| "5.00" : [0x33610, 0x7E], | |
| "5.02" : [0x33B64, 0x7E], | |
| "5.04" : [0x33D50, 0x80], | |
| "5.06" : [0x33D58, 0x80], | |
| "5.06.mexico" : [0x33D6C, 0x80], | |
| "5.10" : [0x3A5C8, 0x8E], | |
| "5.12" : [0x35940, 0x81], | |
| "5.14" : [0x3D73C, 0x90], | |
| "6.00" : [0x35734, 0x86], | |
| "6.02" : [0x35C18, 0x86], | |
| "6.04" : [0x366E4, 0x87], | |
| "6.06" : [0x36A70, 0x87], | |
| "6.10" : [0x36AE4, 0x87], | |
| "6.12" : [0x378E4, 0x87], | |
| } | |
| mecha_bins = {} | |
| for k in sorted(scmd_support_ranges.keys()): | |
| with open(k + ".bin", "rb") as f: | |
| dat = f.read() | |
| if len(dat) != 0x44000: | |
| raise Exception("invalid binary size") | |
| mecha_bins[k] = dat | |
| scmd_support_info = {} | |
| scmd_03_support_info = {} | |
| testmode_cmd_support_info = {} | |
| for k in sorted(mecha_bins.keys()): | |
| v = mecha_bins[k] | |
| scmd_table_addr_cur = scmd_table_addr[k] | |
| scmd_support_ranges_cur = scmd_support_ranges[k] | |
| scmd_handler_addrs = {} | |
| for i1 in range(len(scmd_support_ranges_start)): | |
| st = scmd_support_ranges_start[i1] | |
| for i2 in range(scmd_support_ranges_cur[i1]): | |
| scmd_handler_addrs[st + i2] = int.from_bytes(v[scmd_table_addr_cur:scmd_table_addr_cur + 4], byteorder="little") | |
| scmd_table_addr_cur += 4 | |
| scmd_support = {} | |
| for k1 in sorted(scmd_handler_addrs.keys()): | |
| scmd_support[k1] = "/" if scmd_handler_addrs[k1] == scmd_handler_addrs[0] else "+" | |
| scmd_support_info[k] = scmd_support | |
| scmd_03_table_addr_len_cur = scmd_03_table_addr_len[k] | |
| scmd_03_table_addr_cur = scmd_03_table_addr_len_cur[0] | |
| scmd_03_table_len_cur = scmd_03_table_addr_len_cur[1] | |
| scmd_03_handler_addrs = {} | |
| for i in range(scmd_03_table_len_cur): | |
| xscmd_03_table_addr_cur = scmd_03_table_addr_cur + (i * 8) | |
| scmd_03_handler_addrs[int.from_bytes(v[xscmd_03_table_addr_cur + 4:xscmd_03_table_addr_cur + 5], byteorder="little")] = int.from_bytes(v[xscmd_03_table_addr_cur:xscmd_03_table_addr_cur + 4], byteorder="little") | |
| if int.from_bytes(v[xscmd_03_table_addr_cur + 6:xscmd_03_table_addr_cur + 8], byteorder="little") != 0x0000: | |
| raise Exception("malformed scmd 03 table") | |
| scmd_03_support = {} | |
| for k1 in sorted(scmd_03_handler_addrs.keys()): | |
| scmd_03_support[k1] = "+" | |
| scmd_03_support_info[k] = scmd_03_support | |
| testmode_cmd_addr_len_cur = testmode_cmd_addr_len[k] | |
| testmode_cmd_addr_cur = testmode_cmd_addr_len_cur[0] | |
| testmode_cmd_len_cur = testmode_cmd_addr_len_cur[1] | |
| testmode_cmd_handler_addrs = {} | |
| for i in range(testmode_cmd_len_cur): | |
| xtestmode_cmd_addr_cur = testmode_cmd_addr_cur + (i * 8) | |
| testmode_cmd_handler_addrs[int.from_bytes(v[xtestmode_cmd_addr_cur:xtestmode_cmd_addr_cur + 1], byteorder="little")] = int.from_bytes(v[xtestmode_cmd_addr_cur + 4:xtestmode_cmd_addr_cur + 8], byteorder="little") | |
| if int.from_bytes(v[xtestmode_cmd_addr_cur + 2:xtestmode_cmd_addr_cur + 4], byteorder="little") != 0x0000: | |
| raise Exception("malformed testmode table") | |
| testmode_cmd_support = {} | |
| for k1 in sorted(testmode_cmd_handler_addrs.keys()): | |
| testmode_cmd_support[k1] = "+" | |
| testmode_cmd_support_info[k] = testmode_cmd_support | |
| scmd_support_verinfo = {} | |
| scmd_03_support_verinfo = {} | |
| testmode_cmd_verinfo = {} | |
| for k1 in sorted(scmd_support_info.keys()): | |
| v1 = scmd_support_info[k1] | |
| for k2 in sorted(v1.keys()): | |
| xk2 = "0x%02x" % k2 | |
| if xk2 not in scmd_support_verinfo: | |
| scmd_support_verinfo[xk2] = {} | |
| scmd_support_verinfo[xk2][k1] = v1[k2] | |
| for k1 in sorted(scmd_03_support_info.keys()): | |
| v1 = scmd_03_support_info[k1] | |
| for k2 in sorted(v1.keys()): | |
| xk2 = "0x%02x" % k2 | |
| if xk2 not in scmd_03_support_verinfo: | |
| scmd_03_support_verinfo[xk2] = {} | |
| scmd_03_support_verinfo[xk2][k1] = v1[k2] | |
| for k1 in sorted(testmode_cmd_support_info.keys()): | |
| v1 = testmode_cmd_support_info[k1] | |
| for k2 in sorted(v1.keys()): | |
| xk2 = "0x%02x" % k2 | |
| if xk2 not in testmode_cmd_verinfo: | |
| testmode_cmd_verinfo[xk2] = {} | |
| testmode_cmd_verinfo[xk2][k1] = v1[k2] | |
| if False: | |
| import json | |
| dic = {} | |
| dic["scmd_support_verinfo"] = scmd_support_verinfo | |
| dic["scmd_03_support_verinfo"] = scmd_03_support_verinfo | |
| dic["testmode_cmd_verinfo"] = testmode_cmd_verinfo | |
| xdata = json.dumps(dic, indent=4, sort_keys=True) | |
| with open("00out.json", "w") as f: | |
| f.write(xdata) | |
| def write_wikicreole_prologue(arr, header_name="tmp", header_keys=None): | |
| arr.append('{| class="wikitable" style="text-align:center; margin-left:auto; margin-right:auto;"') | |
| arr.append("|+ " + header_name) | |
| arr.append("! V") | |
| for v in header_keys: | |
| arr.append("! " + v) | |
| bg_color = { | |
| "+" : 'style="background:#9EFF9E"', | |
| "-" : 'style="background:#FFC7C7"', | |
| "/" : 'style="background:#FFD"', | |
| } | |
| def write_wikicreole_item(arr, header_keys=None, item_key=None, dic=None): | |
| arr.append("|-") | |
| arr.append("! " + item_key) | |
| elms = [] | |
| for v in header_keys: | |
| d = "-" | |
| if v in dic: | |
| d = dic[v] | |
| elms.append(bg_color[d] + " | " + d) | |
| arr.append("| " + (" || ".join(elms))) | |
| def write_wikicreole_epilogue(arr): | |
| arr.append("|}") | |
| wikicreole_data = [] | |
| write_wikicreole_prologue(wikicreole_data, header_name="S-Command support", header_keys=sorted(scmd_support_info.keys())) | |
| for k1 in sorted(scmd_support_verinfo.keys()): | |
| write_wikicreole_item(wikicreole_data, header_keys=sorted(scmd_support_info.keys()), item_key=k1, dic=scmd_support_verinfo[k1]) | |
| write_wikicreole_epilogue(wikicreole_data) | |
| write_wikicreole_prologue(wikicreole_data, header_name="S-Command 0x03 support", header_keys=sorted(scmd_03_support_info.keys())) | |
| for k1 in sorted(scmd_03_support_verinfo.keys()): | |
| write_wikicreole_item(wikicreole_data, header_keys=sorted(scmd_03_support_info.keys()), item_key=k1, dic=scmd_03_support_verinfo[k1]) | |
| write_wikicreole_epilogue(wikicreole_data) | |
| write_wikicreole_prologue(wikicreole_data, header_name="TESTMODE command support", header_keys=sorted(testmode_cmd_support_info.keys())) | |
| for k1 in sorted(testmode_cmd_verinfo.keys()): | |
| write_wikicreole_item(wikicreole_data, header_keys=sorted(testmode_cmd_support_info.keys()), item_key=k1, dic=testmode_cmd_verinfo[k1]) | |
| write_wikicreole_epilogue(wikicreole_data) | |
| with open("00out.txt", "w") as f: | |
| f.write("\n".join(wikicreole_data)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment