waterbox - expose read-only information about the guest memory page table
This commit is contained in:
parent
e778e5248d
commit
1c606c1eb6
Binary file not shown.
Binary file not shown.
|
@ -437,5 +437,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
|||
_exe.LoadStateBinary(reader);
|
||||
_core.PostLoadState();
|
||||
}
|
||||
|
||||
public MemoryDomain GetPagesDomain()
|
||||
{
|
||||
return _exe.GetPagesDomain();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
|||
MakeMemoryDomain("SGB CARTRAM", LibsnesApi.SNES_MEMORY.SGB_CARTRAM, MemoryDomain.Endian.Little);
|
||||
}
|
||||
|
||||
|
||||
_memoryDomainList.Add(Api.GetPagesDomain());
|
||||
|
||||
_memoryDomains = new MemoryDomainList(_memoryDomainList);
|
||||
((BasicServiceProvider) ServiceProvider).Register(_memoryDomains);
|
||||
|
|
|
@ -94,6 +94,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
mm.Add(s68Bus);
|
||||
}
|
||||
mm.Add(_elf.GetPagesDomain());
|
||||
|
||||
_memoryDomains = new MemoryDomainList(mm) { SystemBus = m68Bus };
|
||||
((BasicServiceProvider) ServiceProvider).Register(_memoryDomains);
|
||||
|
|
|
@ -73,8 +73,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
var primaryDomain = memoryDomains
|
||||
.Where(md => md.Definition.Flags.HasFlag(LibWaterboxCore.MemoryDomainFlags.Primary))
|
||||
.Single();
|
||||
|
||||
var mdl = new MemoryDomainList(memoryDomains.Cast<MemoryDomain>().ToList());
|
||||
|
||||
var mdl = new MemoryDomainList(
|
||||
memoryDomains.Cast<MemoryDomain>()
|
||||
.Concat(new[] { _exe.GetPagesDomain() })
|
||||
.ToList()
|
||||
);
|
||||
mdl.MainMemory = primaryDomain;
|
||||
_serviceProvider.Register<IMemoryDomains>(mdl);
|
||||
|
||||
|
|
|
@ -218,11 +218,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
return ms.ToArray();
|
||||
}
|
||||
|
||||
// public class MissingFileResult
|
||||
// {
|
||||
// public byte[] data;
|
||||
// public bool writable;
|
||||
// }
|
||||
#if false
|
||||
public class MissingFileResult
|
||||
{
|
||||
public byte[] data;
|
||||
public bool writable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be set by the frontend and will be called if the core attempts to open a missing file.
|
||||
|
@ -233,29 +234,65 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
/// if it was for firmware only.
|
||||
/// writable == false is equivalent to AddReadonlyFile, writable == true is equivalent to AddTransientFile
|
||||
/// </summary>
|
||||
// public Func<string, MissingFileResult> MissingFileCallback
|
||||
// {
|
||||
// set
|
||||
// {
|
||||
// // TODO
|
||||
// using (this.EnterExit())
|
||||
// {
|
||||
// var mfc_o = value == null ? null : new WaterboxHostNative.MissingFileCallback
|
||||
// {
|
||||
// callback = (_unused, name) =>
|
||||
// {
|
||||
// var res = value(name);
|
||||
// }
|
||||
// };
|
||||
public Func<string, MissingFileResult> MissingFileCallback
|
||||
{
|
||||
set
|
||||
{
|
||||
// TODO
|
||||
using (this.EnterExit())
|
||||
{
|
||||
var mfc_o = value == null ? null : new WaterboxHostNative.MissingFileCallback
|
||||
{
|
||||
callback = (_unused, name) =>
|
||||
{
|
||||
var res = value(name);
|
||||
}
|
||||
};
|
||||
|
||||
// NativeImpl.wbx_set_missing_file_callback(_activatedNativeHost, value == null
|
||||
// ? null
|
||||
// : )
|
||||
// }
|
||||
// }
|
||||
// get => _syscalls.MissingFileCallback;
|
||||
// set => _syscalls.MissingFileCallback = value;
|
||||
// }
|
||||
NativeImpl.wbx_set_missing_file_callback(_activatedNativeHost, value == null
|
||||
? null
|
||||
: )
|
||||
}
|
||||
}
|
||||
get => _syscalls.MissingFileCallback;
|
||||
set => _syscalls.MissingFileCallback = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
public MemoryDomain GetPagesDomain()
|
||||
{
|
||||
return new WaterboxPagesDomain(this);
|
||||
}
|
||||
|
||||
private class WaterboxPagesDomain : MemoryDomain
|
||||
{
|
||||
protected readonly WaterboxHost _host;
|
||||
public WaterboxPagesDomain(WaterboxHost host)
|
||||
{
|
||||
_host = host;
|
||||
|
||||
var retobj = new ReturnData();
|
||||
NativeImpl.wbx_get_page_len(_host._nativeHost, retobj);
|
||||
|
||||
Name = "Waterbox PageData";
|
||||
Size = (long)retobj.GetDataOrThrow();
|
||||
WordSize = 1;
|
||||
EndianType = Endian.Unknown;
|
||||
Writable = false;
|
||||
}
|
||||
|
||||
public override byte PeekByte(long addr)
|
||||
{
|
||||
var retobj = new ReturnData();
|
||||
NativeImpl.wbx_get_page_data(_host._nativeHost, Z.SU(addr), retobj);
|
||||
return (byte)retobj.GetDataOrThrow();
|
||||
}
|
||||
|
||||
public override void PokeByte(long addr, byte val)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter bw)
|
||||
{
|
||||
|
|
|
@ -235,5 +235,24 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
/// </summary>
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void wbx_set_always_evict_blocks(bool val);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the number of pages of guest memory that this host is tracking
|
||||
/// </summary>
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void wbx_get_page_len(IntPtr /*WaterboxHost*/ obj, ReturnData /*UIntPtr*/ ret);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve basic information for a tracked guest page. Index should be in 0..wbx_get_page_len().
|
||||
/// 1 - readable, implies allocated
|
||||
/// 2 - writable
|
||||
/// 4 - executable
|
||||
/// 0x10 - stack
|
||||
/// 0x20 - allocated but not readable (guest-generated "guard")
|
||||
/// 0x40 - invisible
|
||||
/// 0x80 - dirty
|
||||
/// </summary>
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void wbx_get_page_data(IntPtr /*WaterboxHost*/ obj, UIntPtr index, ReturnData /*byte*/ ret);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -354,3 +354,26 @@ pub extern fn wbx_set_always_evict_blocks(_val: bool) {
|
|||
unsafe { ALWAYS_EVICT_BLOCKS = _val; }
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the number of pages of guest memory that this host is tracking
|
||||
#[no_mangle]
|
||||
pub extern fn wbx_get_page_len(obj: &mut WaterboxHost, ret: &mut Return<usize>) {
|
||||
ret.put(Ok(obj.page_len()))
|
||||
}
|
||||
|
||||
/// Retrieve basic information for a tracked guest page. Index should be in 0..wbx_get_page_len().
|
||||
/// 1 - readable, implies allocated
|
||||
/// 2 - writable
|
||||
/// 4 - executable
|
||||
/// 0x10 - stack
|
||||
/// 0x20 - allocated but not readable (guest-generated "guard")
|
||||
/// 0x40 - invisible
|
||||
/// 0x80 - dirty
|
||||
#[no_mangle]
|
||||
pub extern fn wbx_get_page_data(obj: &mut WaterboxHost, index: usize, ret: &mut Return<u8>) {
|
||||
if index >= obj.page_len() {
|
||||
ret.put(Err(anyhow!("Index out of range")))
|
||||
} else {
|
||||
ret.put(Ok(obj.page_info(index)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,14 @@ impl WaterboxHost {
|
|||
pub fn run_guest_simple(&mut self, entry_point: usize) {
|
||||
context::call_guest_simple(entry_point, &mut self.context);
|
||||
}
|
||||
|
||||
pub fn page_len(&self) -> usize {
|
||||
self.memory_block.page_len()
|
||||
}
|
||||
|
||||
pub fn page_info(&self, index: usize) -> u8 {
|
||||
self.memory_block.page_info(index)
|
||||
}
|
||||
}
|
||||
|
||||
const SAVE_START_MAGIC: &str = "ActivatedWaterboxHost_v1";
|
||||
|
|
|
@ -492,6 +492,32 @@ impl MemoryBlock {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn page_len(&self) -> usize {
|
||||
self.pages.len()
|
||||
}
|
||||
|
||||
pub fn page_info(&self, index: usize) -> u8 {
|
||||
let p = &self.pages[index];
|
||||
let mut res = match p.status {
|
||||
PageAllocation::Free => 0,
|
||||
PageAllocation::Allocated(prot) => match prot {
|
||||
Protection::None => 0x20,
|
||||
Protection::R => 1,
|
||||
Protection::RW => 3,
|
||||
Protection::RX => 5,
|
||||
Protection::RWX => 7,
|
||||
Protection::RWStack => 0x13,
|
||||
}
|
||||
};
|
||||
if p.dirty {
|
||||
res |= 0x80;
|
||||
}
|
||||
if p.invisible {
|
||||
res |= 0x40;
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MemoryBlock {
|
||||
|
|
Loading…
Reference in New Issue