Skip to content

Commit

Permalink
WIP: non-working: add support for labels with specific databanks
Browse files Browse the repository at this point in the history
- supposed to make it easier when games do weird stuff with databanks but reference the same WRAM address, but.... it's not quite working in all cases
- probably best to just abandon this
  • Loading branch information
binary1230 committed Nov 30, 2024
1 parent d7a1376 commit dedf0fd
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Diz.Core;
using Diz.Core.export;
using Diz.Core.model;
using Diz.Core.model.snes;
using Diz.Core.serialization;
using Diz.Core.serialization.xml_serializer;
using Diz.Core.util;
Expand All @@ -19,6 +20,7 @@
using Diz.Import.bsnes.usagemap;
using Diz.LogWriter;
using Diz.LogWriter.util;
using IX.Library.Collections;
using JetBrains.Annotations;

namespace Diz.Controllers.controllers;
Expand Down Expand Up @@ -257,6 +259,63 @@ public void MarkChanged()
if (Project.Session != null) Project.Session.UnsavedChanges = true;
}

public int NormalizedMirroredAddresses()
{
// crappy but useful hack to deal with mirroring.
// sometimes things like tracelog capture will use mirrored addresses (typically using the DB register)
// to access RAM (or ROM) addresses. if we can detect that is happening, we can switch everything back to
// a normlized address and the exported assembly has a better chance of using the labels correctly.
// this is a little experimental but, should be OK.
//
// Diz3 won't need this because we deal with mirroring better.
if (Project == null || Project.Data.RomBytes.Count <= 0)
return 0;

var modified = 0;
Project.Data.RomBytes
.Where(x => x.TypeFlag == FlagType.Opcode)
.ForEach(opcode =>
{
// check #1: is DB register set to non-zero, and, can we set it back to zero but still generate the same IA?
if (!DataBankCanBeNormalizedToZero(opcode))
return;

opcode.DataBank = 0;
modified++;
});

return modified;
}

private bool DataBankCanBeNormalizedToZero(RomByteData opcode)
{
// NOTE: there may be other interactions with the DB register we should check for too.
// for now, here's just the one

if (opcode.DataBank == 0)
return false; // we're already set to bank 0 so, forget it

// what is the IA normally?
var iaNormal = Project.Data.GetSnesApi()!.GetIntermediateAddress(opcode.Offset, false);
if (iaNormal == -1)
return false;

// what would be the IA if we acted like the databank was actually set to zero (instead of whatever it is)
const int bankZeroOverride = 0;
var iaIfBankZero = Project.Data.GetSnesApi()!.GetIntermediateAddress(opcode.Offset, false, bankZeroOverride);
if (iaIfBankZero == -1)
return false;

// see if our 2 IAs are, in fact, mirrors of the same exact address
// for instance, in LoRom, $009234, $809234, $7E9234 are all just mirrors of the same address.
// we'd prefer then to use $9234 because it would be easier to not have to track a bunch of labels for the same address
var unMirroredNormal = RomUtil.UnmirroredOffset(iaNormal, Project.Data.GetRomSize());
var unMirroredOverride = RomUtil.UnmirroredOffset(iaIfBankZero, Project.Data.GetRomSize());

// if the unmirrored addresses are both valid AND the same, then, it doesn't matter if we set the DB to zero, so, indicate it's OK.
return unMirroredNormal != -1 && unMirroredNormal == unMirroredOverride;
}

public void SelectOffset(int offset, ISnesNavigation.HistoryArgs historyArgs = null) =>
ProjectView.SelectOffset(offset, historyArgs);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public enum ProjectChangedType
bool ExportAssemblyWithCurrentSettings();

void MarkChanged(); // rename to MarkUnsaved or similar in Diz3.0
int NormalizedMirroredAddresses();
}

public interface IProjectOpenerHandler : ILongRunningTaskHandler
Expand Down
2 changes: 1 addition & 1 deletion Diz.Core.Interfaces/ModelInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ public interface ISnesIntermediateAddress
int GetIntermediateAddressOrPointer(int offset);

// -1 if not found
int GetIntermediateAddress(int offset, bool resolve = false);
int GetIntermediateAddress(int offset, bool resolve = false, int overrideDatabank = -1);

bool IsMatchingIntermediateAddress(int intermediateAddress, int addressToMatch);
}
Expand Down
17 changes: 13 additions & 4 deletions Diz.Cpu.65816/src/CPU65C816.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ public int MarkAsOpcodeAndOperandsStartingAt(

// input: ROM offset
// return: a SNES address
public override int GetIntermediateAddress(TByteSource data, int offset, bool resolve)
// if override_databank is not -1, then [if the instruction would look at it] then recorded databank is ignored and this one is used instead.
public override int GetIntermediateAddress(TByteSource data, int offset, bool resolve, int overrideDatabank = -1)
{
int bank;
int programCounter;
Expand Down Expand Up @@ -183,9 +184,17 @@ public override int GetIntermediateAddress(TByteSource data, int offset, bool re
case Cpu65C816Constants.AddressMode.AddressYIndex:
case Cpu65C816Constants.AddressMode.AddressXIndexIndirect:
{
bank = opcode is 0x20 or 0x4C or 0x7C or 0xFC
? data.ConvertPCtoSnes(offset) >> 16
: data.GetDataBank(offset);
if (opcode is 0x20 or 0x4C or 0x7C or 0xFC)
{
bank = data.ConvertPCtoSnes(offset) >> 16;
}
else
{
bank = overrideDatabank == -1
? data.GetDataBank(offset) // normal
: overrideDatabank; // special case (not normally used)
}

var operand = data.GetRomWord(offset + 1);
if (!operand.HasValue)
return -1;
Expand Down
2 changes: 1 addition & 1 deletion Diz.Cpu.65816/src/Cpu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class Cpu<TByteSource> where TByteSource : IRomByteFlagsGettable, IRomByt


public virtual int GetInstructionLength(TByteSource data, int offset) => 1;
public virtual int GetIntermediateAddress(TByteSource data, int offset, bool resolve) => -1;
public virtual int GetIntermediateAddress(TByteSource data, int offset, bool resolve, int overrideDatabank = -1) => -1;
public virtual void MarkInOutPoints(TByteSource data, int offset) {} // nop
public virtual int CalculateInOutPointsFromOffset(
TByteSource data,
Expand Down
4 changes: 2 additions & 2 deletions Diz.Cpu.65816/src/SnesData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ public void MarkAsOpcodeAndOperandsStartingAt(int offset, int? dataBank = null,
}

// FIX ME: log and generation of dp opcodes. search references
public int GetIntermediateAddress(int offset, bool resolve = false) =>
GetCpu(offset).GetIntermediateAddress(this, offset, resolve);
public int GetIntermediateAddress(int offset, bool resolve = false, int overrideDatabank = -1) =>
GetCpu(offset).GetIntermediateAddress(this, offset, resolve, overrideDatabank);

public string GetInstruction(int offset) =>
GetCpu(offset).GetInstruction(this, offset);
Expand Down
2 changes: 1 addition & 1 deletion Diz.LogWriter
14 changes: 14 additions & 0 deletions DiztinGUIsh/window/MainWindow.Actions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Diz.Core.util;
using Diz.Cpu._65816;
using Diz.Ui.Winforms.dialogs;
using Diz.Ui.Winforms.util;
using DiztinGUIsh.Properties;

namespace DiztinGUIsh.window;
Expand Down Expand Up @@ -290,6 +291,19 @@ private void UiFixMisalignedInstructions()
RefreshUi();
ShowInfo($"Modified {countModified} flags!", "Done!");
}

// Diz3 won't need this. but for us, we want it.
private void UiNormalizedMirroredAddresses()
{
GuiUtil.PromptToConfirmAction("Normalize mirrored databank addresses",
$"WARNING: EXPERIMENTAL: PLEASE SAVE FIRST.\nThis will analyze all recorded databank registers and set to zero if the IA isn't affected. (makes for easier labelling). Please be sure to inspect output data after use for correctness, this is a bit of a guess and could have unforseen side effects.",
() => true);

var countModified = ProjectController.NormalizedMirroredAddresses();

RefreshUi();
ShowInfo($"Normalized {countModified} instructions!", "Done!");
}

private void UiRescanForInOut()
{
Expand Down
4 changes: 4 additions & 0 deletions DiztinGUIsh/window/MainWindow.MainTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ private void table_KeyDown(object sender, KeyEventArgs e)
GoToNextUnreachedInPoint(offset);
break;

case Keys.F6:
UiNormalizedMirroredAddresses();
break;

case Keys.Home: case Keys.PageUp: case Keys.Up:
case Keys.End: case Keys.PageDown: case Keys.Down:
ScrollVertically(offset, e.KeyCode switch
Expand Down

0 comments on commit dedf0fd

Please sign in to comment.