import json import tempfile import unittest from pathlib import Path from h8536.model import Instruction from h8536.pseudocode import PseudocodeOptions, generate_pseudocode from h8536.render import format_listing, write_json from h8536.rom import Rom from h8536.serial_reconstruction import analyze_serial_reconstruction def ins(address: int, mnemonic: str, operands: str = "", references: list[int] | None = None) -> Instruction: return Instruction(address, b"", mnemonic, operands, references=references or []) class SerialReconstructionIntegrationTest(unittest.TestCase): def test_listing_json_and_pseudocode_include_candidate_frame_reconstruction(self): instructions = { 0x3000: ins(0x3000, "MOV:G.B", "@H'F858, R0", [0xF858]), 0x3004: ins(0x3004, "MOV:G.B", "R0, @SCI1_TDR", [0xFEDB]), 0x3008: ins(0x3008, "MOV:G.B", "#1, @H'F9C2", [0xF9C2]), 0x3010: ins(0x3010, "MOV:E.B", "#H'5A, R0", []), 0x3014: ins(0x3014, "XOR.B", "@H'F858, R0", [0xF858]), 0x3018: ins(0x3018, "XOR.B", "@H'F859, R0", [0xF859]), 0x301C: ins(0x301C, "XOR.B", "@H'F85A, R0", [0xF85A]), 0x3020: ins(0x3020, "XOR.B", "@H'F85B, R0", [0xF85B]), 0x3024: ins(0x3024, "XOR.B", "@H'F85C, R0", [0xF85C]), 0x3028: ins(0x3028, "MOV:G.B", "R0, @H'F85D", [0xF85D]), 0x3030: ins(0x3030, "MOV:G.B", "@H'F9C2, R1", [0xF9C2]), 0x3034: ins(0x3034, "MOV:G.B", "@(-H'07A8,R1), R0", []), 0x3038: ins(0x3038, "MOV:G.B", "R0, @SCI1_TDR", [0xFEDB]), 0x303C: ins(0x303C, "ADD:Q.B", "#1, @H'F9C2", [0xF9C2]), 0x3040: ins(0x3040, "CMP:G.B", "#6, @H'F9C2", [0xF9C2]), } analysis = analyze_serial_reconstruction(instructions) listing = format_listing( Path("rom.bin"), Rom(b"\xFF" * 0x20), instructions, {}, {}, "min", traced=False, serial_reconstruction=analysis, ) self.assertIn("; Serial Protocol Reconstruction", listing) self.assertIn("TX candidate: 6 bytes", listing) self.assertIn("candidate/evidence-supported SCI1 6-byte TX frame", listing) with tempfile.TemporaryDirectory() as tmp: path = Path(tmp) / "out.json" write_json(path, instructions, {}, {}, serial_reconstruction=analysis) payload = json.loads(path.read_text(encoding="utf-8")) self.assertEqual(payload["serial_reconstruction"]["candidates"][0]["frame_length"], 6) tdr_instruction = next(item for item in payload["instructions"] if item["address"] == 0x3038) self.assertIn("serial_reconstruction", tdr_instruction) pseudocode = generate_pseudocode( payload, options=PseudocodeOptions(include_addresses=False, include_asm=False, structured=False), ) self.assertIn("candidate/evidence-supported SCI1 6-byte TX frame", pseudocode) if __name__ == "__main__": unittest.main()