diff --git a/NESDecompiler.Core/Disassembly/Disassembler.cs b/NESDecompiler.Core/Disassembly/Disassembler.cs index 07bbae0..f42b625 100644 --- a/NESDecompiler.Core/Disassembly/Disassembler.cs +++ b/NESDecompiler.Core/Disassembly/Disassembler.cs @@ -209,6 +209,7 @@ namespace NESDecompiler.Core.Disassembly TraceExecution(); IdentifyFunctions(); GenerateLabels(); + EnsureReferencedAddressesAreDisassembled(); } /// @@ -225,20 +226,23 @@ namespace NESDecompiler.Core.Disassembly /// /// Performs a linear disassembly of the code data /// - private void LinearDisassembly() + private void LinearDisassembly(int offset = 0) { try { - int offset = 0; - ushort baseAddress = 0x8000; while (offset < codeData.Length) { ushort cpuAddress = (ushort)(baseAddress + offset); + if (addressToInstruction.ContainsKey(cpuAddress)) + { + // We have already disassembled this instruction and progressed from here, + // so we can stop. + break; + } byte opcode = codeData[offset]; - var instructionInfo = InstructionSet.GetInstruction(opcode); if (!instructionInfo.IsValid) @@ -280,13 +284,18 @@ namespace NESDecompiler.Core.Disassembly /// /// Traces execution from known entry points /// - private void TraceExecution() + private void TraceExecution(ushort? additionalTraceAddress = null) { try { var toTrace = new Queue(entryPoints); var traced = new HashSet(); + if (additionalTraceAddress != null) + { + toTrace.Enqueue(additionalTraceAddress.Value); + } + while (toTrace.Count > 0) { ushort address = toTrace.Dequeue(); @@ -328,6 +337,7 @@ namespace NESDecompiler.Core.Disassembly if (instruction.Info.Mnemonic == "JMP") { + continue; } } @@ -450,6 +460,26 @@ namespace NESDecompiler.Core.Disassembly } } + private void EnsureReferencedAddressesAreDisassembled() + { + const int baseAddress = 0x8000; + var unknownReferencedAddresses = referencedAddresses + .Where(x => !addressToInstruction.ContainsKey(x)) + .Where(x => x > baseAddress) + .ToArray(); + + foreach (var referencedAddress in unknownReferencedAddresses) + { + var offset = referencedAddress - baseAddress; + LinearDisassembly(offset); + TraceExecution(referencedAddress); + } + + // Update functions and labels + IdentifyFunctions(); + GenerateLabels(); + } + /// /// Returns the disassembly as a formatted string ///