mirror of
https://github.com/ApfelTeeSaft/NESDecompiler.git
synced 2026-08-26 19:33:30 +00:00
Merge pull request #13 from KallDrexx/loopback_instruction_fix
Loopback jumps should occur on the same cpu address of the jump
This commit is contained in:
@@ -32,13 +32,17 @@ public class DecompiledFunction
|
||||
JumpTargets = instructions
|
||||
.Where(x => jumpTargets.Contains(x.CPUAddress))
|
||||
.Where(x => x.Label != null)
|
||||
.Where(x => x.SubAddressOrder == 0) // only real instructions should be jumped to
|
||||
.ToDictionary(x => x.CPUAddress, x => x.Label!);
|
||||
|
||||
// We need to order the instructions so that the starting instruction is the first one encountered.
|
||||
// We can't just rely on the CPU address, because a function may jump to a code point earlier than
|
||||
// the first instruction.
|
||||
var entryPointInstructions = instructions.Where(x => x.CPUAddress == address)
|
||||
.Where(x => x.SubAddressOrder >= 0);
|
||||
|
||||
var initialInstructions = instructions
|
||||
.Where(x => x.CPUAddress >= address)
|
||||
.Where(x => x.CPUAddress > address)
|
||||
.OrderBy(x => x.CPUAddress)
|
||||
.ThenBy(x => x.SubAddressOrder);
|
||||
|
||||
@@ -47,6 +51,17 @@ public class DecompiledFunction
|
||||
.OrderBy(x => x.CPUAddress)
|
||||
.ThenBy(x => x.SubAddressOrder); // real instructions before virtual ones
|
||||
|
||||
OrderedInstructions = initialInstructions.Concat(trailingInstructions).ToArray();
|
||||
// If there was a loopback jump point at the function address, put that here. This is required
|
||||
// because if an emulator is executing a virtual loopback instruction and an IRQ occurs, this
|
||||
// will cause the virtual instruction to be saved to the stack, and that can cause the entry
|
||||
// point to be wrong.
|
||||
var loopbackInstructions = instructions.Where(x => x.CPUAddress == address)
|
||||
.Where(x => x.SubAddressOrder < 0);
|
||||
|
||||
OrderedInstructions = entryPointInstructions
|
||||
.Concat(initialInstructions)
|
||||
.Concat(trailingInstructions)
|
||||
.Concat(loopbackInstructions)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public static class FunctionDecompiler
|
||||
// This means a branch occurred that caused the flow to wrap around to instructions preceding
|
||||
// the function entrance. This usually happens when there is a jump/branch to right before the
|
||||
// entrypoint, usually due to decompiling in the middle of a loop. To fix this, we need to add
|
||||
// a jump back to the function entrypoint
|
||||
// a jump back to the function entrypoint.
|
||||
if (functionAddress == 0x00)
|
||||
{
|
||||
const string message = "Wrap around instruction detected for a function at 0000, but that " +
|
||||
@@ -41,12 +41,12 @@ public static class FunctionDecompiler
|
||||
var jumpInstruction = new DisassembledInstruction
|
||||
{
|
||||
Info = InstructionSet.GetInstruction(0x4C),
|
||||
CPUAddress = (ushort)(nextAddress - 1),
|
||||
CPUAddress = nextAddress,
|
||||
Bytes = [0x4C, (byte)addressLow, (byte)addressHigh],
|
||||
TargetAddress = functionAddress,
|
||||
|
||||
// Make sure they appear after any instruction that already occupies that address
|
||||
SubAddressOrder = 1,
|
||||
// Make sure they appear before the function address
|
||||
SubAddressOrder = -1,
|
||||
};
|
||||
|
||||
instructions.Add(jumpInstruction);
|
||||
@@ -92,7 +92,8 @@ public static class FunctionDecompiler
|
||||
// Add labels for any jump targets
|
||||
foreach (var instruction in instructions)
|
||||
{
|
||||
if (jumpAddresses.Contains(instruction.CPUAddress))
|
||||
// Only real instructions should have a label, virtual ones should not
|
||||
if (jumpAddresses.Contains(instruction.CPUAddress) && instruction.SubAddressOrder == 0)
|
||||
{
|
||||
instruction.Label = $"loc_{instruction.CPUAddress:X4}";
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace NESDecompiler.Core.Disassembly
|
||||
/// address location at runtime. Can be used to add runtime hooks or to work around
|
||||
/// decompilation issues. Should be 0 for all native instructions from a ROM.
|
||||
/// </summary>
|
||||
public byte SubAddressOrder { get; set; }
|
||||
public sbyte SubAddressOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of this instruction
|
||||
|
||||
Reference in New Issue
Block a user