Add tracer + disassembler + get registers + system bus to Ares64, mark Ares64 as released
Squashed commit of the following: commit 2e29aee13276412b2832e8f0efa10d9c57ed9d78 Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Thu Apr 14 22:44:33 2022 -0700 . commit be73cf5e2204405a84b42948fd104d18c75be45a Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Thu Apr 14 22:37:34 2022 -0700 hook up debug stuff + disassembler + tracer, mark Ares64 as released commit fdd440703ecef48c94bb2bb1ad9c2d3dc5c96e42 Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Thu Apr 14 20:36:08 2022 -0700 maybe fix disassembly commit d0808551c60fe3c03506b1ad89766a0d397e06dd Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Thu Apr 14 20:06:36 2022 -0700 system bus commit 60d1df8f33043fb656f90c1cf4ace8788489c3e1 Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Thu Apr 14 16:40:11 2022 -0700 regs commit c64be2df293ea44694868355747061a952bd54aa Author: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Thu Apr 14 15:31:08 2022 -0700 tracing and disasembly for ares, needs to be hooked up to frontend
This commit is contained in:
parent
7d268e244b
commit
20ecfb81ea
Binary file not shown.
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
||||
{
|
||||
public partial class Ares64 : IDebuggable
|
||||
{
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
var ret = new Dictionary<string, RegisterValue>();
|
||||
var data = new ulong[32 + 3]; // GPRs, lo, hi, pc (todo: other regs)
|
||||
_core.GetRegisters(data);
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
ret.Add(_GPRnames[i], data[i]);
|
||||
}
|
||||
|
||||
ret.Add("LO", data[32]);
|
||||
ret.Add("HI", data[33]);
|
||||
ret.Add("PC", (uint)data[34]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private readonly string[] _GPRnames = new string[32]
|
||||
{
|
||||
"R0",
|
||||
"AT",
|
||||
"V0", "V1",
|
||||
"A0", "A1", "A2", "A3",
|
||||
"T0", "T1", "T2", "T3", "T4", "T5", "T6", "T7",
|
||||
"S0", "S1", "S2", "S3", "S4", "S5", "S6", "S7",
|
||||
"T8", "T9",
|
||||
"K0", "K1",
|
||||
"GP",
|
||||
"SP",
|
||||
"S8",
|
||||
"RA",
|
||||
};
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void SetCpuRegister(string register, int value) => throw new NotImplementedException();
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public IMemoryCallbackSystem MemoryCallbacks => throw new NotImplementedException();
|
||||
|
||||
public bool CanStep(StepType type) => false;
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public long TotalExecutedCycles => throw new NotImplementedException();
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void Step(StepType type) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
||||
{
|
||||
public class Ares64Disassembler : VerifiedDisassembler
|
||||
{
|
||||
private readonly LibAres64 _core;
|
||||
private readonly byte[] _disasmbuf = new byte[100]; // todo: is this big enough?
|
||||
|
||||
public Ares64Disassembler(LibAres64 core)
|
||||
{
|
||||
_core = core;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> AvailableCpus => new[] { "R4300", };
|
||||
|
||||
public override string PCRegisterName => "PC";
|
||||
|
||||
public override string Disassemble(MemoryDomain m, uint addr, out int length)
|
||||
{
|
||||
_core.GetDisassembly(addr, m.PeekUint(addr, true), _disasmbuf);
|
||||
length = 4;
|
||||
var ret = Encoding.UTF8.GetString(_disasmbuf);
|
||||
var z = ret.IndexOf('\0');
|
||||
if (z > -1)
|
||||
{
|
||||
ret = ret.Substring(0, z); // remove garbage past null terminator
|
||||
}
|
||||
ret = Regex.Replace(ret, @"\u001b?\[[0-9]{1,2}m", ""); // remove ANSI escape sequences
|
||||
ret = Regex.Replace(ret, @"\{.*\}", ""); // remove any {*} patterns
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ using System.ComponentModel;
|
|||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
||||
{
|
||||
public partial class Ares64 : ISettable<Ares64.Ares64Settings, Ares64.Ares64SyncSettings>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
||||
{
|
||||
public partial class Ares64
|
||||
{
|
||||
private ITraceable Tracer { get; }
|
||||
private readonly LibAres64.TraceCallback _tracecb;
|
||||
|
||||
private void MakeTrace(IntPtr disasm)
|
||||
{
|
||||
var regs = GetCpuFlagsAndRegisters();
|
||||
var regsStr = "";
|
||||
foreach (var r in regs)
|
||||
{
|
||||
if (r.Key is not "PC")
|
||||
{
|
||||
regsStr += r.Key + $":{r.Value.Value:X16} ";
|
||||
}
|
||||
}
|
||||
|
||||
regsStr = regsStr.Remove(regsStr.Length - 1, 1);
|
||||
|
||||
var disasmStr = Mershul.PtrToStringUtf8(disasm);
|
||||
disasmStr = disasmStr.Remove(0, 5); // remove "CPU "
|
||||
disasmStr = disasmStr.Replace("\n", ""); // remove newlines
|
||||
disasmStr = Regex.Replace(disasmStr, @"\{.*\}", ""); // remove any {*} patterns
|
||||
|
||||
Tracer.Put(new(
|
||||
disassembly: disasmStr,
|
||||
registerInfo: regsStr));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,11 +8,12 @@ using BizHawk.Emulation.Cores.Waterbox;
|
|||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
||||
{
|
||||
[PortedCore(CoreNames.Ares64, "ares team, Near", "v127", "https://ares-emulator.github.io/", isReleased: false)]
|
||||
[PortedCore(CoreNames.Ares64, "ares team, Near", "v127", "https://ares-emulator.github.io/")]
|
||||
[ServiceNotApplicable(new[] { typeof(IDriveLight), })]
|
||||
public partial class Ares64 : WaterboxCore, IRegionable
|
||||
{
|
||||
private readonly LibAres64 _core;
|
||||
private readonly Ares64Disassembler _disassembler;
|
||||
|
||||
[CoreConstructor(VSystemID.Raw.N64)]
|
||||
public Ares64(CoreLoadParameters<Ares64Settings, Ares64SyncSettings> lp)
|
||||
|
@ -40,6 +41,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
|||
};
|
||||
|
||||
N64Controller = CreateControllerDefinition(ControllerSettings);
|
||||
_tracecb = MakeTrace;
|
||||
|
||||
_core = PreInit<LibAres64>(new WaterboxOptions
|
||||
{
|
||||
|
@ -51,7 +53,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
|||
MmapHeapSizeKB = 512 * 1024,
|
||||
SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck),
|
||||
SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck),
|
||||
});
|
||||
}, new[] { _tracecb, });
|
||||
|
||||
var rom = lp.Roms[0].RomData;
|
||||
|
||||
|
@ -114,6 +116,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
|||
|
||||
PostInit();
|
||||
|
||||
Tracer = new TraceBuffer("r3400: PC, mnemonic, operands, registers (GPRs, Load/Link Bit, MultHI, MultLO, Implementation/Revision, Control/Status, FGRs)");
|
||||
_serviceProvider.Register(Tracer);
|
||||
|
||||
_disassembler = new(_core);
|
||||
_serviceProvider.Register<IDisassemblable>(_disassembler);
|
||||
|
||||
DeterministicEmulation = lp.DeterministicEmulationRequested || (!_syncSettings.UseRealTime);
|
||||
InitializeRtc(_syncSettings.InitialTime);
|
||||
}
|
||||
|
@ -203,6 +211,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
|||
|
||||
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
|
||||
{
|
||||
_core.SetTraceCallback(Tracer.IsEnabled() ? _tracecb : null);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (ControllerSettings[i] == LibAres64.ControllerType.Rumblepak)
|
||||
|
|
|
@ -99,5 +99,17 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64
|
|||
|
||||
[BizImport(CC)]
|
||||
public abstract bool GetRumbleStatus(int num);
|
||||
|
||||
[BizImport(CC)]
|
||||
public abstract void GetDisassembly(uint address, uint instruction, byte[] buf);
|
||||
|
||||
[UnmanagedFunctionPointer(CC)]
|
||||
public delegate void TraceCallback(IntPtr disasm);
|
||||
|
||||
[BizImport(CC)]
|
||||
public abstract void SetTraceCallback(TraceCallback callback);
|
||||
|
||||
[BizImport(CC)]
|
||||
public abstract void GetRegisters(ulong[] buf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ struct BizPlatform : ares::Platform
|
|||
{
|
||||
auto attach(ares::Node::Object) -> void override;
|
||||
auto pak(ares::Node::Object) -> ares::VFS::Pak override;
|
||||
auto log(string_view) -> void override;
|
||||
auto video(ares::Node::Video::Screen, const u32*, u32, u32, u32) -> void override;
|
||||
auto audio(ares::Node::Audio::Stream) -> void override;
|
||||
auto input(ares::Node::Input::Input) -> void override;
|
||||
|
@ -60,6 +61,7 @@ struct BizPlatform : ares::Platform
|
|||
bool hack = false;
|
||||
void (*inputcb)() = nullptr;
|
||||
bool lagged = true;
|
||||
void (*tracecb)(const char*) = nullptr;
|
||||
};
|
||||
|
||||
auto BizPlatform::attach(ares::Node::Object node) -> void
|
||||
|
@ -75,6 +77,11 @@ auto BizPlatform::pak(ares::Node::Object) -> ares::VFS::Pak
|
|||
return bizpak;
|
||||
}
|
||||
|
||||
auto BizPlatform::log(string_view message) -> void
|
||||
{
|
||||
if (tracecb) tracecb(message.data());
|
||||
}
|
||||
|
||||
auto BizPlatform::video(ares::Node::Video::Screen screen, const u32* data, u32 pitch, u32 width, u32 height) -> void
|
||||
{
|
||||
videobuf = (u32*)data;
|
||||
|
@ -566,17 +573,76 @@ EXPORT bool GetRumbleStatus(u32 num)
|
|||
m[i].Data = c->transferPak.rom.data; \
|
||||
m[i].Name = "GB ROM " #NUM; \
|
||||
m[i].Size = c->transferPak.rom.size; \
|
||||
m[i].Flags = MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE; \
|
||||
m[i].Flags = MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE; \
|
||||
i++; \
|
||||
\
|
||||
m[i].Data = c->transferPak.ram.data; \
|
||||
m[i].Name = "GB SRAM " #NUM; \
|
||||
m[i].Size = c->transferPak.ram.size; \
|
||||
m[i].Flags = MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_SAVERAMMABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE; \
|
||||
m[i].Flags = MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_SAVERAMMABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE; \
|
||||
i++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline u8 GetByteFromWord(u32 word, u32 addr)
|
||||
{
|
||||
switch (addr & 3)
|
||||
{
|
||||
case 0: return (word >> 24) & 0xFF;
|
||||
case 1: return (word >> 16) & 0xFF;
|
||||
case 2: return (word >> 8) & 0xFF;
|
||||
case 3: return (word >> 0) & 0xFF;
|
||||
default: __builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static u8 PeekFunc(u64 address)
|
||||
{
|
||||
address &= 0x1fff'ffff;
|
||||
const u32 addr = address;
|
||||
|
||||
if (addr > 0x0403'ffff && addr <= 0x0407'ffff) // RSP
|
||||
{
|
||||
address = (address & 0x3ffff) >> 2;
|
||||
if (address == 7) // SP_SEMAPHORE
|
||||
{
|
||||
return GetByteFromWord(ares::Nintendo64::rsp.status.semaphore & 1, addr);
|
||||
}
|
||||
}
|
||||
else if (addr > 0x0407'ffff && addr <= 0x040f'ffff) // RSP Status
|
||||
{
|
||||
address = (address & 0x7ffff) >> 2;
|
||||
if (address == 0) // SP_PC_REG
|
||||
{
|
||||
return GetByteFromWord(ares::Nintendo64::rsp.ipu.pc & 0xFFF, addr);
|
||||
}
|
||||
}
|
||||
else if (addr > 0x046f'ffff && addr <= 0x047f'ffff) // RI
|
||||
{
|
||||
address = (address & 0xfffff) >> 2;
|
||||
if (address == 3) // RI_SELECT
|
||||
{
|
||||
return GetByteFromWord(ares::Nintendo64::ri.io.select, addr);
|
||||
}
|
||||
}
|
||||
|
||||
return ares::Nintendo64::bus.read<ares::Nintendo64::Byte>(addr);
|
||||
}
|
||||
|
||||
static void SysBusAccess(u8* buffer, u64 address, u64 count, bool write)
|
||||
{
|
||||
if (write)
|
||||
{
|
||||
while (count--)
|
||||
ares::Nintendo64::bus.write<ares::Nintendo64::Byte>(address++, *buffer++);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (count--)
|
||||
*buffer++ = PeekFunc(address++);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT void GetMemoryAreas(MemoryArea *m)
|
||||
{
|
||||
int i = 0;
|
||||
|
@ -597,6 +663,11 @@ EXPORT void GetMemoryAreas(MemoryArea *m)
|
|||
ADD_GB_DOMAINS(2);
|
||||
ADD_GB_DOMAINS(3);
|
||||
ADD_GB_DOMAINS(4);
|
||||
|
||||
m[i].Data = (void*)SysBusAccess;
|
||||
m[i].Name = "System Bus";
|
||||
m[i].Size = 1ull << 32;
|
||||
m[i].Flags = MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_FUNCTIONHOOK;
|
||||
}
|
||||
|
||||
struct MyFrameInfo : public FrameInfo
|
||||
|
@ -698,3 +769,27 @@ EXPORT void SetInputCallback(void (*callback)())
|
|||
{
|
||||
platform->inputcb = callback;
|
||||
}
|
||||
|
||||
EXPORT void GetDisassembly(u32 address, u32 instruction, char* buf)
|
||||
{
|
||||
auto s = ares::Nintendo64::cpu.disassembler.disassemble(address, instruction).strip();
|
||||
strcpy(buf, s.data());
|
||||
}
|
||||
|
||||
EXPORT void SetTraceCallback(void (*callback)(const char*))
|
||||
{
|
||||
ares::Nintendo64::cpu.debugger.tracer.instruction->setEnabled(!!callback);
|
||||
platform->tracecb = callback;
|
||||
}
|
||||
|
||||
EXPORT void GetRegisters(u64* buf)
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
buf[i] = ares::Nintendo64::cpu.ipu.r[i].u64;
|
||||
}
|
||||
|
||||
buf[32] = ares::Nintendo64::cpu.ipu.lo.u64;
|
||||
buf[33] = ares::Nintendo64::cpu.ipu.hi.u64;
|
||||
buf[34] = ares::Nintendo64::cpu.ipu.pc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue