"""AGE (Eushully SYS4/SYS5) opcode + operand-type tables. Transcribed verbatim from Kelebek1/Eushully-Decompiler `age-shared.cpp` (vm-map/kelebek1-age-shared.cpp). Validated against all 476 Himegari SYS4 scripts: every instruction decodes with zero unknown opcodes when the code stream is walked as ` + argc*()`, instruction length = 1 + 2*argc dwords. Handler labels `u004XXXXX` are AGE.EXE addresses from Kelebek's reference title (a later AGE game); the opcode NUMBER + argument_count are the stable ABI and are correct for Himegari. Bare-hex/`dev_ukn` labels = unnamed semantics. """ from __future__ import annotations # op_code -> (label, argument_count) OPCODES: dict[int, tuple[str, int]] = { 0x0001: ('u004149C0', 0), # error 0x0002: ('exit', 0), 0x0003: ('call-script', 1), # call another script, param = SYSTEM4.bin index 0x0004: ('u00417E30', 2), 0x0005: ('ret', 0), 0x0006: ('u00417E80', 2), 0x0007: ('u00417F90', 1), 0x0008: ('u00417FC0', 1), 0x0009: ('exit-script', 0), 0x000a: ('u00424170', 2), 0x000b: ('u00418090', 11), 0x000c: ('u004149E0', 0), 0x000d: ('u004181A0', 4), 0x000e: ('u00418200', 12), 0x000f: ('u00418300', 1), 0x0010: ('u00414A00', 4), 0x0011: ('u00418330', 9), 0x0012: ('u004183F0', 1), 0x0013: ('u00418420', 4), 0x0014: ('u00414A20', 0), 0x0015: ('u00418490', 5), 0x0016: ('u00418520', 2), 0x0017: ('u00418560', 2), 0x001e: ('u004185B0', 8), 0x001f: ('u00418690', 12), 0x0020: ('u004187C0', 6), 0x0021: ('u00418860', 2), 0x0022: ('u00418920', 2), 0x0023: ('u004189D0', 2), 0x0024: ('u00418A90', 2), 0x0025: ('u00418B40', 3), 0x0026: ('u00418C00', 4), 0x0027: ('u00418CC0', 4), 0x0028: ('u00418D90', 4), 0x002a: ('u00418E60', 4), 0x002b: ('u00418F30', 5), 0x002c: ('u00419010', 5), 0x002d: ('u004190A0', 12), 0x002e: ('u004194B0', 5), 0x002f: ('u004195A0', 4), 0x0030: ('u00419670', 5), 0x0031: ('u00419750', 4), 0x0032: ('u004197C0', 10), 0x0033: ('u00419900', 6), 0x0034: ('u004199C0', 12), 0x0035: ('u00419AF0', 11), 0x0036: ('u00419C00', 3), 0x0037: ('u00419C90', 11), 0x0038: ('u00419DA0', 12), 0x0050: ('add', 3), # add. param1 = param2 + param3 0x0051: ('sub', 3), # sub. param1 = param2 - param3 0x0052: ('mul', 3), # mul. param1 = param2 * param3 0x0053: ('div', 3), # div. param1 = param2 / param3 0x0054: ('mod', 3), # mod. param1 = param2 % param3 0x0055: ('mov', 2), # mov. param1 = param2 0x0056: ('and', 3), # and. param1 = param2 & param3 0x0057: ('or', 3), # or. param1 = param2 | param3 0x0058: ('sar', 3), # sar. param1 = param2 >> param3 0x0059: ('shl', 3), # shl. param1 = param2 << param3 0x005a: ('eq', 3), # eq. param1 = param2 == param3 0x005b: ('ne', 3), # ne. param1 = param2 != param3 0x005c: ('lt', 3), # lt. param1 = param2 < param3 0x005d: ('lte', 3), # lte. param1 = param2 <= param3 0x005e: ('gr', 3), # gr. param1 = param2 > param3 0x005f: ('gre', 3), # gre. param1 = param2 >= param3 0x0060: ('u0041A270', 2), 0x0061: ('lookup-array', 3), # lookup. param1 = param2[param3] 0x0062: ('u0041A360', 3), 0x0063: ('u00414A60', 2), 0x0064: ('copy-local-array', 2), 0x0065: ('u00414AA0', 2), 0x0066: ('u00414AE0', 3), 0x0067: ('u00414B20', 3), 0x0068: ('u00414B60', 3), 0x0069: ('u00414BA0', 3), 0x006a: ('u00414BE0', 3), 0x006b: ('u00414C20', 3), 0x006c: ('copy-to-global', 2), # loop copy local value to global array, param1 = array start, param2 = count 0x006d: ('u00416960', 0), 0x006e: ('show-text', 2), 0x006f: ('end-text-line', 1), 0x0070: ('u0041A750', 5), 0x0071: ('u0041A7B0', 1), 0x0072: ('wait-for-input', 1), 0x0073: ('u0041AB30', 10), 0x0074: ('u0041AC00', 1), 0x0075: ('u0041AC30', 1), 0x0076: ('u0041AC60', 1), 0x0077: ('u0041ACB0', 1), 0x0078: ('u0041AD00', 1), 0x0079: ('u0041AD30', 3), 0x007a: ('u0041AD70', 3), 0x007b: ('u0041ADB0', 2), # ukn, both args point to code locations 0x007c: ('u00416A90', 0), 0x007d: ('u0041AE00', 2), 0x007e: ('u0041AEA0', 1), 0x007f: ('u00414C60', 1), 0x0080: ('u0041AF00', 1), 0x0081: ('u0041AF30', 1), 0x0082: ('u0041AF80', 5), 0x0083: ('u00414C90', 3), 0x0084: ('u0041AFE0', 1), 0x0085: ('u00414CF0', 0), 0x0086: ('u0041B210', 1), 0x0087: ('u00414D10', 0), 0x0088: ('u0041B290', 1), 0x0089: ('u0041B2E0', 4), 0x008a: ('u0041B330', 6), 0x008b: ('u0041B3D0', 1), 0x008c: ('jmp', 1), 0x008d: ('u0041BCE0', 2), 0x008e: ('u0041BD60', 1), 0x008f: ('call', 1), 0x0090: ('u0041BEB0', 7), # ukn, args 5, 6 and 7 point to code locations 0x0091: ('u0041BFB0', 1), 0x0092: ('u0041C030', 2), 0x0093: ('u00415040', 0), 0x0094: ('u00415090', 0), 0x0095: ('u0041C0C0', 2), 0x0096: ('u004150C0', 0), 0x0097: ('u0041C150', 5), 0x00a0: ('jcc', 3), 0x00a1: ('u00427C00', 0), 0x00a2: ('u00427FD0', 2), 0x00a3: ('u004244D0', 2), 0x00aa: ('u0041C270', 2), 0x00ab: ('u0041C330', 2), 0x00ac: ('u0041C3E0', 9), 0x00ad: ('u00415110', 0), 0x00ae: ('u00415130', 0), 0x00af: ('u00415480', 0), 0x00b0: ('u0041C530', 1), 0x00b1: ('u0041C560', 1), 0x00b2: ('u0041C590', 2), 0x00b3: ('u004154B0', 0), 0x00b4: ('play-sound-effect', 2), # play a sound effect/ambient. param1 = file index, param2 = play mode? 0x00b5: ('u0041D050', 1), 0x00b6: ('u0041D080', 1), 0x00b7: ('u0041D0E0', 1), 0x00b8: ('u00415520', 0), 0x00b9: ('u0041D140', 1), 0x00ba: ('u0041D0B0', 1), 0x00bb: ('u0041D250', 1), 0x00bc: ('u0041D280', 1), 0x00bd: ('u00415570', 1), 0x00be: ('u004155E0', 1), 0x00bf: ('play-bgm', 1), # param1 = bgm number 0x00c0: ('u00415620', 1), 0x00c1: ('u00415650', 0), 0x00c2: ('u0041D2B0', 2), 0x00c3: ('u0041D390', 1), 0x00c4: ('play-voice', 1), 0x00c5: ('u0041D4A0', 2), 0x00c6: ('u0041D5D0', 2), 0x00c7: ('u0041D760', 2), 0x00c8: ('sleep', 1), # param1 = sleep time? 0x00c9: ('u00415770', 0), 0x00ca: ('u004157A0', 0), 0x00cb: ('u00415800', 1), 0x00cc: ('mouse_callback', 2), # sets mouse/keyboard callback location, param1 = id, param2 = offset (minus header, not multiplied by 4) 0x00cd: ('get-input-type', 0), # get input type, mouse, keyboard, pad etc 0x00ce: ('u0041E0B0', 3), 0x00cf: ('u00416D40', 0), 0x00d0: ('u00415830', 1), 0x00d1: ('u00415860', 0), 0x00d2: ('u0041E110', 1), 0x00d3: ('u00425960', 0), 0x00d4: ('u004266F0', 4), # seems to setup some kind of looping function calls. param1 = ukn, param2 = loop count, param3 = function location?, param4 = function location? 0x00d5: ('u004262C0', 1), 0x00d6: ('u004267D0', 6), 0x00d7: ('u0041E1A0', 1), 0x00d8: ('u0041E150', 2), 0x00d9: ('u00415880', 0), 0x00da: ('u004158B0', 6), 0x00fa: ('u00415940', 0), 0x00fb: ('joy_callback', 2), # sets code callback for joystick inputs. ID 0-4= left thumb up/down/left/right, 4 = X on Xbox controller etc. param1 = id, param2 = offset (minus header, not multiplied by 4) 0x00fc: ('u004159F0', 0), 0x00fd: ('u0041E2D0', 2), 0x00fe: ('u0041E360', 1), 0x00ff: ('u00415A10', 0), 0x0100: ('u00415A60', 0), 0x0101: ('u00415BF0', 0), # joystick input? 0x0102: ('u0041E3C0', 3), 0x0103: ('u0041E4A0', 1), 0x0104: ('u00415C50', 0), 0x0105: ('u0041E4D0', 1), 0x0106: ('u00415E40', 1), 0x0107: ('u0041E500', 2), 0x0108: ('u00415E70', 1), 0x0109: ('u00415EC0', 2), 0x010a: ('u0041E540', 2), 0x010b: ('u0041E5A0', 2), 0x010c: ('u0041E5E0', 2), 0x010d: ('u00415F10', 1), 0x010e: ('u0041E650', 2), 0x010f: ('u0041E690', 1), 0x012c: ('lookup-array-2d', 5), # 2d array lookup. param1 = param2[(param3 * param4) + param5] 0x012d: ('u0041E720', 7), 0x012e: ('u0041E940', 8), 0x012f: ('u0041ECB0', 4), 0x0130: ('u00415F40', 1), 0x0131: ('u00415F70', 1), 0x0132: ('u0041EF00', 1), 0x0133: ('u0041EFF0', 2), 0x0134: ('u0041F050', 3), 0x0135: ('bit-set', 2), # bts, param1 = param1 OR param2 0x0136: ('bit-reset', 2), # btr, param1 = param1 NOR param2 0x0137: ('u0041F1C0', 1), 0x0138: ('u0041F2B0', 2), 0x0139: ('u0041F310', 3), 0x013a: ('u0041F3A0', 6), 0x013b: ('u0041F440', 7), 0x013c: ('u0041F7E0', 1), 0x013d: ('u0041F840', 3), 0x013e: ('u0041F8D0', 2), 0x013f: ('check-bit', 3), # param1 = param2 & (1 << param3). Neg, sbb, neg to get the result as a bool 0x0140: ('u0041F9C0', 4), 0x0141: ('u0041FAA0', 1), 0x0142: ('u0041FB10', 1), 0x0143: ('u00415FB0', 0), 0x0144: ('u004259D0', 2), 0x0145: ('u00416040', 1), 0x0146: ('u0041FB40', 1), 0x0147: ('u0041FB80', 6), 0x0148: ('u004160A0', 1), 0x0149: ('u0041FCE0', 1), 0x014a: ('u0041FD10', 7), 0x014b: ('u0041FF50', 1), 0x014c: ('set-agerc-export', 2), # binds an agerc.dll export name to the given number 0x014d: ('call-agerc-export', 6), # call the param1 agerc exported function 0x0190: ('u0041C5E0', 2), 0x0191: ('u0041A4A0', 2), 0x0192: ('set-string', 2), # u004252D0 : set-string. param1 = param2 0x0193: ('concat', 3), # u00425370 : concat. param1 = param2.concat(param3) 0x0194: ('u00425480', 3), 0x0195: ('u00425580', 3), 0x0196: ('display-furigana', 3), # u0041B400 : display-furigana. param1 = text, param2 = furigana 0x0197: ('u0041B510', 1), 0x0198: ('u0041B540', 3), 0x0199: ('u00414D50', 0), 0x019a: ('u00414E50', 1), 0x019b: ('u00414E80', 0), 0x019c: ('u00414EC0', 0), 0x019d: ('u0041C680', 2), 0x019e: ('u0041C6E0', 2), 0x019f: ('u0041C860', 2), 0x01a0: ('u0041C9B0', 9), 0x01a1: ('u0041CB40', 2), 0x01a2: ('u00428010', 1), 0x01a3: ('string-lookup-set', 1), # check the value given exists in save/current data and set. param1 = strings[param1] 0x01a4: ('u0041B580', 2), 0x01a5: ('set-font', 1), # set-font 0x01a6: ('halve-strlen', 2), # halve-strlen? param1 = param2.length() / 2 (rounded down) 0x01a7: ('comment', 1), # Developer debug comment 0x01a8: ('dev_ukn', 0), # Developer debug something, no function in-game 0x01a9: ('u00428090', 1), 0x01aa: ('u00425920', 1), 0x01ab: ('u0041CCA0', 2), 0x01ac: ('u0041CD80', 3), 0x01ad: ('u004154F0', 0), 0x01ae: ('u0041CED0', 3), 0x01af: ('u004245C0', 3), 0x01b0: ('u0041A510', 3), 0x01b1: ('u0041B5C0', 1), 0x01b2: ('u00425790', 1), # to string table? 0x01b3: ('u004257D0', 0), 0x01b4: ('u004237C0', 0), 0x01b5: ('u0041B5F0', 1), 0x01b6: ('u00414F60', 1), 0x01b7: ('u0041B640', 1), 0x01b8: ('u0041B670', 2), 0x01b9: ('u0041B710', 2), 0x01ba: ('u0041D850', 2), 0x01bb: ('u0041B7B0', 1), 0x01bc: ('u00415670', 0), 0x01bd: ('u0041D910', 1), 0x01be: ('u0041D9D0', 2), 0x01bf: ('u004156C0', 0), 0x01c0: ('u0041DB70', 1), 0x01c1: ('u0041B820', 3), 0x01c2: ('u0041B860', 2), 0x01c3: ('u0041B8A0', 2), 0x01c4: ('u00415720', 1), 0x01c5: ('u00425800', 4), 0x01c6: ('u0041DD80', 2), 0x01c7: ('u00414F90', 1), 0x01c8: ('toString', 2), # u00425680 : toString 0x01c9: ('u0041B8E0', 3), 0x01ca: ('u0041B9B0', 1), 0x01cb: ('u00414FD0', 1), 0x01cc: ('u00415010', 1), 0x01cd: ('u0041A560', 2), 0x01ce: ('u0041B9F0', 1), 0x01cf: ('u0041DA10', 1), 0x01d0: ('u0041BA80', 3), 0x01d1: ('u0041BAE0', 5), 0x01d2: ('u0041BB40', 2), 0x01d3: ('u0041BB90', 5), 0x01d4: ('u0041BC00', 4), 0x01d5: ('u00415700', 0), 0x01d6: ('u0041DA40', 2), 0x01d7: ('u0041DA80', 2), 0x01d8: ('u0041DAD0', 3), 0x01d9: ('u0041DB20', 2), 0x01f4: ('u004160D0', 0), 0x01f5: ('u00416120', 0), 0x01f6: ('u00416170', 0), 0x01f7: ('u00420270', 2), 0x01f8: ('create-texture', 4), # create a new drawable rect. param1 = id, param2 = sizeX, param3 = sizeY, param4 = ukn 0x01f9: ('set-texture', 3), # set a texture to a given ID. param1 = file index, param2 = id, param3 = ? 0x01fa: ('u00420480', 1), 0x01fb: ('draw-texture', 8), # draw a texture. param1 = UI element id?, param2 = textureID, param3 = texX, param4 = texY, param5 = width, param6 = height, param7 = drawX, param8 = drawY 0x01fc: ('u004205F0', 1), 0x01fd: ('u00420620', 4), 0x01fe: ('u004206C0', 5), 0x01ff: ('u00420770', 4), 0x0200: ('u00420800', 1), 0x0201: ('u00416190', 1), 0x0202: ('u00420880', 5), 0x0203: ('u00420950', 4), 0x0204: ('draw-string', 4), # u00420A10 : place-string. param1 = id? param2 = x, param3 = y, param4 = string 0x0205: ('u00420A60', 6), 0x0206: ('u004161C0', 7), 0x0207: ('u00420B00', 8), 0x0208: ('u00420BF0', 3), 0x0209: ('u00420C50', 5), 0x020a: ('u00420CE0', 1), 0x020b: ('u00420D50', 7), 0x020c: ('u00416200', 0), 0x020d: ('u00420E10', 1), 0x020e: ('u00416250', 0), 0x020f: ('u00420E40', 3), 0x0210: ('u00420FF0', 1), 0x0211: ('u00421060', 1), 0x0212: ('u00421090', 2), 0x0213: ('u004210D0', 3), 0x0214: ('u00421120', 2), 0x0215: ('u00421160', 2), 0x0216: ('u004211A0', 2), 0x0217: ('u004211E0', 4), 0x0218: ('u00421270', 4), 0x0219: ('u004212E0', 4), 0x021a: ('u00421370', 4), 0x021b: ('u004213E0', 1), 0x021c: ('u00416270', 0), 0x021d: ('u00421410', 2), 0x021e: ('u00421450', 6), 0x021f: ('u00421510', 7), 0x0220: ('u004215D0', 6), 0x0221: ('u00421670', 4), 0x0222: ('u004216C0', 2), 0x0223: ('u00421700', 8), 0x0224: ('u00416290', 0), 0x0225: ('u00421780', 2), 0x0226: ('u004217D0', 5), 0x0227: ('u00421880', 6), 0x0228: ('u00421940', 5), 0x0229: ('u004219E0', 5), 0x022a: ('u00421A90', 3), 0x022b: ('u00421B30', 4), 0x022c: ('u00421BD0', 3), 0x022d: ('u00421C60', 5), 0x022e: ('u00421D10', 6), 0x022f: ('u00421DD0', 5), 0x0230: ('u00421E70', 1), 0x0231: ('u00421EA0', 4), 0x0232: ('u00421EF0', 4), 0x0233: ('u00421FB0', 5), 0x0234: ('u00422060', 5), 0x0235: ('u00422100', 5), 0x0236: ('u004221A0', 4), 0x0237: ('u00422350', 2), 0x0238: ('u00422390', 1), 0x0239: ('u004223C0', 6), 0x023a: ('u00422420', 2), 0x023b: ('u00422460', 7), 0x023c: ('u004162B0', 0), 0x023d: ('u004162F0', 0), 0x023e: ('u004228C0', 2), 0x023f: ('u00422930', 2), 0x0240: ('u004229A0', 4), 0x0241: ('u00422B80', 5), 0x0242: ('u00422D60', 2), 0x0243: ('u00417070', 0), 0x0244: ('u00416360', 0), 0x0245: ('u00422DA0', 2), 0x0246: ('u00422E10', 2), 0x0247: ('u00416390', 1), 0x0248: ('u00422E80', 1), 0x0249: ('u00422EB0', 3), 0x024a: ('u004163C0', 3), 0x024d: ('u00422E90', 12), 0x024e: ('u00422EA0', 1), 0x024f: ('u00422ED0', 10), 0x0250: ('u00422F60', 10), 0x0251: ('u00422FF0', 12), 0x0252: ('u00423000', 1), 0x0253: ('u00423019', 2), 0x0254: ('u00423049', 5), 0x0256: ('u00423050', 5), 0x0257: ('257', 5), # Sankai no Yubiwa 0x0258: ('u00422FE0', 2), 0x0259: ('u00416410', 0), 0x025a: ('u00423120', 1), 0x025b: ('25B', 1), # Kami no Rhapsody 0x025c: ('u00423122', 8), 0x025d: ('u00423123', 3), 0x025e: ('u00423124', 5), 0x025f: ('u00423125', 4), 0x0260: ('u00423126', 4), 0x0261: ('u00423127', 1), 0x0262: ('262', 1), # Amayui 2 0x0263: ('263', 1), # Amayui 2 0x0264: ('264', 5), # Hyakusen 0x02bc: ('u00423020', 11), 0x02bd: ('u00423100', 1), 0x02be: ('u00423140', 1), 0x02bf: ('u00423180', 3), 0x02c0: ('u004231C0', 3), 0x02c1: ('u00425BC0', 1), 0x02c2: ('u00425CD0', 6), 0x02c3: ('u00423200', 2), 0x02c4: ('u00416450', 0), # using as a way to test logging, originally u00416450 0x02c5: ('strlen', 2), # u0042B5D0 : strlen. param1 = param2.length() 0x02c6: ('u0042B5E0', 2), 0x02c7: ('u0042B5F0', 4), 0x02c8: ('u0042B610', 4), 0x02c9: ('2C9', 3), # Sankai no Yubiwa 0x02cc: ('2CC', 1), # Sankai no Yubiwa 0x02cd: ('2CD', 1), # Sankai no Yubiwa 0x02ce: ('u0042B616', 1), 0x02cf: ('u0042B617', 1), 0x02d0: ('u0042B940', 3), 0x02d1: ('u0042B950', 3), 0x02d2: ('u0042B960', 3), 0x02d3: ('u0042B970', 3), 0x02d5: ('u0042B990', 2), 0x02d7: ('u0042B9B0', 2), 0x02d8: ('set-array-to', 3), # Set a given array to the given value x times. loop: param1[param3] = param2; param3++ 0x02d9: ('u0042BA30', 2), 0x02da: ('u004234E0', 8), 0x02db: ('u004235C0', 1), 0x02dc: ('u0042BA80', 1), 0x02dd: ('u0042D880', 2), 0x02de: ('u0042BAC0', 2), 0x02df: ('u0042BAC1', 3), 0x02e0: ('u0042CE0F', 3), 0x02e1: ('u0042CE10', 3), 0x02e2: ('u0042CE11', 3), 0x02e3: ('u0042CE30', 3), 0x02e4: ('u0042CE31', 3), 0x02e5: ('u0042CE50', 1), 0x02e6: ('u0042CE60', 2), 0x02e7: ('u0042CE70', 2), 0x02e8: ('u0042CE80', 1), 0x02e9: ('u0042CE90', 1), 0x02ea: ('u0042CEA0', 1), 0x02eb: ('u0042CEB0', 1), 0x02ec: ('u0042CEC0', 2), 0x02ee: ('u0042CEC2', 1), 0x02ef: ('u0042CEC3', 11), 0x02f0: ('u0042CEC4', 9), 0x02f1: ('u0042CEC5', 7), 0x02f2: ('u0042CEC6', 6), 0x02f3: ('2F3', 6), # La Dea 0x02f4: ('2F4', 3), # La Dea 0x02f5: ('2F5', 4), # La Dea 0x02f6: ('2F6', 1), # La Dea 0x02f7: ('2F7', 1), # La Dea 0x02f8: ('2F8', 2), # La Dea 0x02f9: ('2F9', 7), # La Dea 0x02fa: ('2FA', 1), # La Dea 0x02fb: ('2FB', 1), # La Dea 0x02fc: ('2FC', 5), # Kami no Rhapsody 0x02fd: ('2FD', 6), # Kami no Rhapsody 0x02fe: ('2FE', 1), # Sankai no Yubiwa 0x02ff: ('2FF', 2), # Sankai no Yubiwa 0x0300: ('300', 3), # Sankai no Yubiwa 0x0301: ('301', 1), # Sankai no Yubiwa 0x0302: ('302', 2), # Sankai no Yubiwa 0x0303: ('303', 3), # Sankai no Yubiwa 0x0304: ('304', 0), # Sankai no Yubiwa 0x0305: ('305', 0), # Sankai no Yubiwa 0x0306: ('306', 1), # Sankai no Yubiwa 0x0307: ('307', 1), # Sankai no Yubiwa 0x0308: ('308', 1), # Amayui Alchemy Meister 0x030a: ('30A', 2), # Amayui Alchemy Meister 0x030c: ('30C', 1), # Tenmei no Conquista 0x0320: ('u0043AA20', 10), 0x0321: ('u0043AA30', 3), 0x0322: ('u0043AA40', 4), 0x0323: ('u0043AA50', 5), 0x0324: ('u0043AA60', 0), 0x0325: ('u0043AA70', 2), 0x0326: ('u0043AA80', 4), 0x0327: ('u0043AA90', 1), 0x0328: ('u0043AAA0', 3), 0x0329: ('u0043AAB0', 2), 0x032a: ('32A', 1), # Kami no Rhapsody 0x032b: ('u0043AAD0', 0), 0x032c: ('u0043AAE0', 6), 0x032d: ('u0043AAF0', 2), 0x032e: ('u0043AB10', 11), 0x032f: ('u0043AB11', 1), 0x0330: ('u0043AB12', 2), 0x0332: ('u0043AB14', 4), 0x0334: ('u0043AB16', 1), 0x0335: ('u0043AB17', 4), 0x0337: ('u0043AB19', 4), 0x033b: ('u0043AB1D', 4), 0x033d: ('u0043AB1E', 3), 0x033e: ('u0043AB1F', 5), 0x033f: ('u0043AB20', 3), 0x0340: ('340', 1), # Sankai no Yubiwa 0x0341: ('341', 2), # Amayui Alchemy Meister 0x0342: ('342', 1), # Amayui Alchemy Meister 0x0344: ('344', 2), # Amayui Alchemy Meister 0x0345: ('345', 3), # Amayui Alchemy Meister 0x0349: ('349', 4), # Amayui Alchemy Meister 0x034d: ('34D', 6), # Amayui Alchemy Meister 0x034e: ('34E', 4), # Amayui Alchemy Meister 0x0352: ('352', 3), # Amayui Alchemy Meister 0x0353: ('353', 2), # Fuukan no Gransesta 0x0354: ('354', 2), # Fuukan no Gransesta 0x0358: ('358', 5), # Amayui 2 0x035a: ('35A', 5), # Amayui 2 0x035b: ('35B', 2), # Fuukan no Gransesta 0x035c: ('35C', 2), # Fuukan no Gransesta 0x035d: ('35D', 3), # Fuukan no Gransesta 0x035f: ('35F', 3), # Fuukan no Gransesta 0x0360: ('360', 3), # Fuukan no Gransesta 0x0361: ('361', 2), # Fuukan no Gransesta 0x0363: ('363', 3), # Amayui 2 0x0364: ('364', 3), # Amayui 2 0x0384: ('384', 3), # Tenmei no Conquista 0x0386: ('386', 11), # Tenmei no Conquista 0x0387: ('387', 8), # Tenmei no Conquista 0x0388: ('388', 3), # Tenmei no Conquista 0x0389: ('389', 6), # Tenmei no Conquista 0x038f: ('38F', 6), # Tenmei no Conquista 0x0390: ('390', 7), # Tenmei no Conquista 0x0391: ('391', 2), # Amayui 2 0x0392: ('392', 1), # Tenmei no Conquista 0x0393: ('393', 6), # Amayui 2 0x0396: ('396', 5), # Tenmei no Conquista 0x0398: ('398', 3), # Amayui 2 0x0399: ('399', 7), # Tenmei no Conquista 0x039b: ('39B', 5), # Amayui 2 } # argument type tag -> human label (from disassembler.cpp get_type_label) ARG_TYPES: dict[int, str] = { 0x0000: 'imm', 0x0001: 'float', 0x0002: 'string', 0x0003: 'global-int', 0x0004: 'global-float', 0x0005: 'global-string', 0x0006: 'global-ptr', 0x0008: 'global-string-ptr', 0x0009: 'local-int', 0x000a: 'local-float', 0x000b: 'local-string', 0x000c: 'local-ptr', 0x000d: 'local-float-ptr', 0x000e: 'local-string-ptr', 0x8003: 'type-0x8003', 0x8005: 'type-0x8005', 0x8009: 'type-0x8009', 0x800b: 'type-0x800B', } # opcodes whose (some) operands are code offsets (label targets), from age-shared.h CONTROL_FLOW = frozenset({0x8C, 0x8F, 0xA0, 0xCC, 0xFB, 0xD4, 0x90, 0x7B}) # opcode 0x64 arg #1 references an array stored in the footer (not inline) ARRAY_OPCODE = 0x64 def is_label_argument(op: int, arg_index: int, raw_value: int) -> bool: """Mirror of age-shared.h is_label_argument: is this operand a code-offset label?""" if raw_value == 0xFFFFFFFF: return False if op in (0x8C, 0x8F): return True if op == 0xA0: return arg_index > 0 if op in (0xCC, 0xFB): return arg_index > 0 if op == 0xD4: return arg_index >= 2 if op == 0x90: return arg_index >= 4 if op == 0x7B: return True return False