pce - implement most memory domains our existing core does
The mednafen debugger system makes this easy, unfortunately that has a lot of other baggage, so do it this way
This commit is contained in:
parent
1000b74f2d
commit
f9b5b9e374
|
@ -27,5 +27,8 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCE
|
||||||
};
|
};
|
||||||
DoInit<LibNymaCore>(game, null, discs, "pce.wbx", null, firmwares);
|
DoInit<LibNymaCore>(game, null, discs, "pce.wbx", null, firmwares);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pce always has two layers, sgx always has 4, and mednafen knows this
|
||||||
|
public override string SystemId => SettingsInfo.LayerNames.Count == 4 ? "SGX" : "PCE";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,13 +90,17 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
/// for a yuge endian domain, if true, bytes are stored word-swapped from their native ordering
|
/// for a yuge endian domain, if true, bytes are stored word-swapped from their native ordering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Swapped = 512,
|
Swapped = 512,
|
||||||
|
/// <summary>
|
||||||
|
/// If true, Data is a function to call and not a pointer
|
||||||
|
/// </summary>
|
||||||
|
FunctionHook = 1024,
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct MemoryArea
|
public struct MemoryArea
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// pointer to the data in memory
|
/// pointer to the data in memory, or a function hook to call
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IntPtr Data;
|
public IntPtr Data;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -110,99 +114,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
public MemoryDomainFlags Flags;
|
public MemoryDomainFlags Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CC)]
|
||||||
|
public delegate void MemoryFunctionHook(IntPtr buffer, long address, long count, bool write);
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CC)]
|
[UnmanagedFunctionPointer(CC)]
|
||||||
public delegate void EmptyCallback();
|
public delegate void EmptyCallback();
|
||||||
|
|
||||||
public unsafe class WaterboxMemoryDomain : MemoryDomain
|
|
||||||
{
|
|
||||||
private readonly IntPtr _data;
|
|
||||||
private readonly IMonitor _monitor;
|
|
||||||
private readonly long _addressMangler;
|
|
||||||
|
|
||||||
public override byte PeekByte(long addr)
|
|
||||||
{
|
|
||||||
if ((ulong)addr < (ulong)Size)
|
|
||||||
{
|
|
||||||
using (_monitor.EnterExit())
|
|
||||||
{
|
|
||||||
return ((byte*)_data)[addr ^ _addressMangler];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void PokeByte(long addr, byte val)
|
|
||||||
{
|
|
||||||
if (Writable)
|
|
||||||
{
|
|
||||||
if ((ulong)addr < (ulong)Size)
|
|
||||||
{
|
|
||||||
using (_monitor.EnterExit())
|
|
||||||
{
|
|
||||||
((byte*)_data)[addr ^ _addressMangler] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(addr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void BulkPeekByte(Range<long> addresses, byte[] values)
|
|
||||||
{
|
|
||||||
if (_addressMangler != 0)
|
|
||||||
{
|
|
||||||
base.BulkPeekByte(addresses, values);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var start = (ulong)addresses.Start;
|
|
||||||
var count = addresses.Count();
|
|
||||||
|
|
||||||
if (start < (ulong)Size && (start + count) <= (ulong)Size)
|
|
||||||
{
|
|
||||||
using (_monitor.EnterExit())
|
|
||||||
{
|
|
||||||
Marshal.Copy(Z.US((ulong)_data + start), values, 0, (int)count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(addresses));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public WaterboxMemoryDomain(MemoryArea m, IMonitor monitor)
|
|
||||||
{
|
|
||||||
Name = Mershul.PtrToStringUtf8(m.Name);
|
|
||||||
EndianType = (m.Flags & MemoryDomainFlags.YugeEndian) != 0 ? Endian.Big : Endian.Little;
|
|
||||||
_data = m.Data;
|
|
||||||
Size = m.Size;
|
|
||||||
Writable = (m.Flags & MemoryDomainFlags.Writable) != 0;
|
|
||||||
if ((m.Flags & MemoryDomainFlags.WordSize1) != 0)
|
|
||||||
WordSize = 1;
|
|
||||||
else if ((m.Flags & MemoryDomainFlags.WordSize2) != 0)
|
|
||||||
WordSize = 2;
|
|
||||||
else if ((m.Flags & MemoryDomainFlags.WordSize4) != 0)
|
|
||||||
WordSize = 4;
|
|
||||||
else if ((m.Flags & MemoryDomainFlags.WordSize8) != 0)
|
|
||||||
WordSize = 8;
|
|
||||||
else
|
|
||||||
throw new InvalidOperationException("Unknown word size for memory domain");
|
|
||||||
_monitor = monitor;
|
|
||||||
if ((m.Flags & MemoryDomainFlags.Swapped) != 0 && EndianType == Endian.Big)
|
|
||||||
{
|
|
||||||
_addressMangler = WordSize - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_addressMangler = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[BizImport(CC)]
|
[BizImport(CC)]
|
||||||
public abstract void FrameAdvance([In, Out] FrameInfo frame);
|
public abstract void FrameAdvance([In, Out] FrameInfo frame);
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
.ToArray();
|
.ToArray();
|
||||||
_saveramSize = (int)_saveramAreas.Sum(a => a.Size);
|
_saveramSize = (int)_saveramAreas.Sum(a => a.Size);
|
||||||
|
|
||||||
var memoryDomains = _memoryAreas.Select(a => new LibWaterboxCore.WaterboxMemoryDomain(a, _exe));
|
var memoryDomains = _memoryAreas.Select(a => WaterboxMemoryDomain.Create(a, _exe));
|
||||||
var primaryIndex = _memoryAreas
|
var primaryIndex = _memoryAreas
|
||||||
.Select((a, i) => new { a, i })
|
.Select((a, i) => new { a, i })
|
||||||
.Single(a => (a.a.Flags & LibWaterboxCore.MemoryDomainFlags.Primary) != 0).i;
|
.Single(a => (a.a.Flags & LibWaterboxCore.MemoryDomainFlags.Primary) != 0).i;
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using BizHawk.BizInvoke;
|
||||||
|
using BizHawk.Common;
|
||||||
|
using BizHawk.Emulation.Common;
|
||||||
|
using static BizHawk.Emulation.Cores.Waterbox.LibWaterboxCore;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
|
{
|
||||||
|
public abstract unsafe class WaterboxMemoryDomain : MemoryDomain
|
||||||
|
{
|
||||||
|
protected readonly IntPtr _data;
|
||||||
|
protected readonly IMonitor _monitor;
|
||||||
|
protected readonly long _addressMangler;
|
||||||
|
|
||||||
|
public static MemoryDomain Create(MemoryArea m, IMonitor monitor)
|
||||||
|
{
|
||||||
|
return m.Flags.HasFlag(MemoryDomainFlags.FunctionHook)
|
||||||
|
? (MemoryDomain)new WaterboxMemoryDomainFunc(m, monitor)
|
||||||
|
: new WaterboxMemoryDomainPointer(m, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WaterboxMemoryDomain(MemoryArea m, IMonitor monitor)
|
||||||
|
{
|
||||||
|
Name = Mershul.PtrToStringUtf8(m.Name);
|
||||||
|
EndianType = (m.Flags & MemoryDomainFlags.YugeEndian) != 0 ? Endian.Big : Endian.Little;
|
||||||
|
_data = m.Data;
|
||||||
|
Size = m.Size;
|
||||||
|
Writable = (m.Flags & MemoryDomainFlags.Writable) != 0;
|
||||||
|
if ((m.Flags & MemoryDomainFlags.WordSize1) != 0)
|
||||||
|
WordSize = 1;
|
||||||
|
else if ((m.Flags & MemoryDomainFlags.WordSize2) != 0)
|
||||||
|
WordSize = 2;
|
||||||
|
else if ((m.Flags & MemoryDomainFlags.WordSize4) != 0)
|
||||||
|
WordSize = 4;
|
||||||
|
else if ((m.Flags & MemoryDomainFlags.WordSize8) != 0)
|
||||||
|
WordSize = 8;
|
||||||
|
else
|
||||||
|
throw new InvalidOperationException("Unknown word size for memory domain");
|
||||||
|
_monitor = monitor;
|
||||||
|
if ((m.Flags & MemoryDomainFlags.Swapped) != 0 && EndianType == Endian.Big)
|
||||||
|
{
|
||||||
|
_addressMangler = WordSize - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_addressMangler = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe class WaterboxMemoryDomainPointer : WaterboxMemoryDomain
|
||||||
|
{
|
||||||
|
internal WaterboxMemoryDomainPointer(MemoryArea m, IMonitor monitor)
|
||||||
|
: base(m, monitor)
|
||||||
|
{
|
||||||
|
if (m.Flags.HasFlag(MemoryDomainFlags.FunctionHook))
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte PeekByte(long addr)
|
||||||
|
{
|
||||||
|
if ((ulong)addr < (ulong)Size)
|
||||||
|
{
|
||||||
|
using (_monitor.EnterExit())
|
||||||
|
{
|
||||||
|
return ((byte*)_data)[addr ^ _addressMangler];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PokeByte(long addr, byte val)
|
||||||
|
{
|
||||||
|
if (Writable)
|
||||||
|
{
|
||||||
|
if ((ulong)addr < (ulong)Size)
|
||||||
|
{
|
||||||
|
using (_monitor.EnterExit())
|
||||||
|
{
|
||||||
|
((byte*)_data)[addr ^ _addressMangler] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BulkPeekByte(Range<long> addresses, byte[] values)
|
||||||
|
{
|
||||||
|
if (_addressMangler != 0)
|
||||||
|
{
|
||||||
|
base.BulkPeekByte(addresses, values);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var start = (ulong)addresses.Start;
|
||||||
|
var count = addresses.Count();
|
||||||
|
|
||||||
|
if (start < (ulong)Size && (start + count) <= (ulong)Size)
|
||||||
|
{
|
||||||
|
using (_monitor.EnterExit())
|
||||||
|
{
|
||||||
|
Marshal.Copy(Z.US((ulong)_data + start), values, 0, (int)count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(addresses));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For private use only! Don't touch
|
||||||
|
/// </summary>
|
||||||
|
public abstract class MemoryDomainAccessStub
|
||||||
|
{
|
||||||
|
[BizImport(CallingConvention.Cdecl)]
|
||||||
|
public abstract void Access(IntPtr buffer, long address, long count, bool write);
|
||||||
|
|
||||||
|
private class StubResolver : IImportResolver
|
||||||
|
{
|
||||||
|
private readonly IntPtr _p;
|
||||||
|
public StubResolver(IntPtr p)
|
||||||
|
{
|
||||||
|
_p = p;
|
||||||
|
}
|
||||||
|
public IntPtr GetProcAddrOrThrow(string entryPoint) => _p;
|
||||||
|
public IntPtr GetProcAddrOrZero(string entryPoint) => _p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MemoryDomainAccessStub Create(IntPtr p, IMonitor monitor)
|
||||||
|
{
|
||||||
|
return BizInvoker.GetInvoker<MemoryDomainAccessStub>(new StubResolver(p), monitor, CallingConventionAdapters.Waterbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe class WaterboxMemoryDomainFunc : WaterboxMemoryDomain
|
||||||
|
{
|
||||||
|
private readonly MemoryDomainAccessStub _access;
|
||||||
|
|
||||||
|
internal WaterboxMemoryDomainFunc(MemoryArea m, IMonitor monitor)
|
||||||
|
: base(m, monitor)
|
||||||
|
{
|
||||||
|
if (!m.Flags.HasFlag(MemoryDomainFlags.FunctionHook))
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
_access = MemoryDomainAccessStub.Create(m.Data, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte PeekByte(long addr)
|
||||||
|
{
|
||||||
|
if ((ulong)addr < (ulong)Size)
|
||||||
|
{
|
||||||
|
byte ret = 0;
|
||||||
|
_access.Access((IntPtr)(byte*)&ret, addr, 1, false);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PokeByte(long addr, byte val)
|
||||||
|
{
|
||||||
|
if (Writable)
|
||||||
|
{
|
||||||
|
if ((ulong)addr < (ulong)Size)
|
||||||
|
{
|
||||||
|
_access.Access((IntPtr)(byte*)&val, addr, 1, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BulkPeekByte(Range<long> addresses, byte[] values)
|
||||||
|
{
|
||||||
|
if (_addressMangler != 0)
|
||||||
|
{
|
||||||
|
base.BulkPeekByte(addresses, values);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var start = (ulong)addresses.Start;
|
||||||
|
var count = addresses.Count();
|
||||||
|
|
||||||
|
if (start < (ulong)Size && (start + count) <= (ulong)Size)
|
||||||
|
{
|
||||||
|
fixed(byte* p = values)
|
||||||
|
_access.Access((IntPtr)p, (long)start, (long)count, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(addresses));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,40 +1,43 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t* VideoBuffer;
|
uint32_t* VideoBuffer;
|
||||||
int16_t* SoundBuffer;
|
int16_t* SoundBuffer;
|
||||||
int64_t Cycles;
|
int64_t Cycles;
|
||||||
int32_t Width;
|
int32_t Width;
|
||||||
int32_t Height;
|
int32_t Height;
|
||||||
int32_t Samples;
|
int32_t Samples;
|
||||||
int32_t Lagged;
|
int32_t Lagged;
|
||||||
} FrameInfo;
|
} FrameInfo;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
void* Data;
|
void* Data;
|
||||||
const char* Name;
|
const char* Name;
|
||||||
int64_t Size;
|
int64_t Size;
|
||||||
int64_t Flags;
|
int64_t Flags;
|
||||||
} MemoryArea;
|
} MemoryArea;
|
||||||
|
|
||||||
#define MEMORYAREA_FLAGS_WRITABLE 1
|
typedef void (*MemoryFunctionHook)(uint8_t* buffer, int64_t address, int64_t count, bool write);
|
||||||
#define MEMORYAREA_FLAGS_SAVERAMMABLE 2
|
|
||||||
#define MEMORYAREA_FLAGS_ONEFILLED 4
|
#define MEMORYAREA_FLAGS_WRITABLE 1
|
||||||
#define MEMORYAREA_FLAGS_PRIMARY 8
|
#define MEMORYAREA_FLAGS_SAVERAMMABLE 2
|
||||||
#define MEMORYAREA_FLAGS_YUGEENDIAN 16
|
#define MEMORYAREA_FLAGS_ONEFILLED 4
|
||||||
#define MEMORYAREA_FLAGS_WORDSIZE1 32
|
#define MEMORYAREA_FLAGS_PRIMARY 8
|
||||||
#define MEMORYAREA_FLAGS_WORDSIZE2 64
|
#define MEMORYAREA_FLAGS_YUGEENDIAN 16
|
||||||
#define MEMORYAREA_FLAGS_WORDSIZE4 128
|
#define MEMORYAREA_FLAGS_WORDSIZE1 32
|
||||||
#define MEMORYAREA_FLAGS_WORDSIZE8 256
|
#define MEMORYAREA_FLAGS_WORDSIZE2 64
|
||||||
#define MEMORYAREA_FLAGS_SWAPPED 512
|
#define MEMORYAREA_FLAGS_WORDSIZE4 128
|
||||||
|
#define MEMORYAREA_FLAGS_WORDSIZE8 256
|
||||||
#ifdef __cplusplus
|
#define MEMORYAREA_FLAGS_SWAPPED 512
|
||||||
}
|
#define MEMORYAREA_FLAGS_FUNCTIONHOOK 1024
|
||||||
#endif
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -190,14 +190,6 @@ ECL_EXPORT void SetLayers(uint64_t layers)
|
||||||
Game->SetLayerEnableMask(layers);
|
Game->SetLayerEnableMask(layers);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECL_EXPORT void GetMemoryAreas(MemoryArea* m)
|
|
||||||
{
|
|
||||||
m[0].Data = (void*)pixels;
|
|
||||||
m[0].Name = "PEWP";
|
|
||||||
m[0].Size = Game->fb_width * Game->fb_height * 4;
|
|
||||||
m[0].Flags = MEMORYAREA_FLAGS_PRIMARY | MEMORYAREA_FLAGS_WORDSIZE4;
|
|
||||||
}
|
|
||||||
|
|
||||||
ECL_EXPORT void SetInputCallback(void (*cb)())
|
ECL_EXPORT void SetInputCallback(void (*cb)())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
#include "nyma.h"
|
#include "nyma.h"
|
||||||
#include <emulibc.h>
|
#include <emulibc.h>
|
||||||
#include "mednafen/src/pce/pce.h"
|
#include "mednafen/src/pce/pce.h"
|
||||||
|
#include <waterboxcore.h>
|
||||||
|
#include "mednafen/src/pce/pcecd.h"
|
||||||
|
#include "mednafen/src/pce/huc.h"
|
||||||
|
#include "mednafen/src/hw_misc/arcade_card/arcade_card.h"
|
||||||
|
|
||||||
using namespace MDFN_IEN_PCE;
|
using namespace MDFN_IEN_PCE;
|
||||||
|
|
||||||
|
@ -11,3 +15,124 @@ void SetupMDFNGameInfo()
|
||||||
{
|
{
|
||||||
Mednafen::MDFNGameInfo = &EmulatedPCE;
|
Mednafen::MDFNGameInfo = &EmulatedPCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsSgx()
|
||||||
|
{
|
||||||
|
return strcmp(EmulatedPCE.LayerNames, "BG0") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<auto ReadFunc, auto WriteFunc>
|
||||||
|
// static void AccessFunc(uint8_t* buffer, int64_t address, int64_t count, bool write)
|
||||||
|
// {
|
||||||
|
// if (write)
|
||||||
|
// {
|
||||||
|
// while (count--)
|
||||||
|
// WriteFunc(address++, *buffer++);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// while (count--)
|
||||||
|
// *buffer++ = ReadFunc(address++);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
#define DEFUN(N,R,W)\
|
||||||
|
static void Access##N(uint8_t* buffer, int64_t address, int64_t count, bool write)\
|
||||||
|
{\
|
||||||
|
if (write)\
|
||||||
|
{\
|
||||||
|
while (count--)\
|
||||||
|
W(address++, *buffer++);\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
while (count--)\
|
||||||
|
*buffer++ = R(address++);\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
#define DEFRG(N,R,W)\
|
||||||
|
static void Access##N(uint8_t* buffer, int64_t address, int64_t count, bool write)\
|
||||||
|
{\
|
||||||
|
if (write)\
|
||||||
|
{\
|
||||||
|
W(address, count, buffer);\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
R(address, count, buffer);\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MDFN_IEN_PCE
|
||||||
|
{
|
||||||
|
extern ArcadeCard* arcade_card;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(ShortBus, HuCPU.PeekLogical, HuCPU.PokeLogical);
|
||||||
|
DEFUN(LongBus, HuCPU.PeekPhysical, HuCPU.PokePhysical);
|
||||||
|
DEFUN(MainMemory, PCE_PeekMainRAM, PCE_PokeMainRAM);
|
||||||
|
DEFUN(BRAM, HuC_PeekBRAM, HuC_PokeBRAM);
|
||||||
|
DEFRG(ADPCM, ADPCM_PeekRAM, ADPCM_PokeRAM);
|
||||||
|
DEFRG(Arcade, arcade_card->PeekRAM, arcade_card->PokeRAM);
|
||||||
|
|
||||||
|
ECL_EXPORT void GetMemoryAreas(MemoryArea* m)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
m[i].Data = (void*)(MemoryFunctionHook)AccessLongBus;
|
||||||
|
m[i].Name = "System Bus (21 bit)";
|
||||||
|
m[i].Size = 1 << 21;
|
||||||
|
m[i].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_FUNCTIONHOOK;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
m[i].Data = (void*)(MemoryFunctionHook)AccessShortBus;
|
||||||
|
m[i].Name = "System Bus";
|
||||||
|
m[i].Size = 1 << 16;
|
||||||
|
m[i].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_FUNCTIONHOOK;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
m[i].Data = (void*)(MemoryFunctionHook)AccessMainMemory;
|
||||||
|
m[i].Name = "Main Memory";
|
||||||
|
m[i].Size = IsSgx() ? 32768 : 8192;
|
||||||
|
m[i].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_FUNCTIONHOOK | MEMORYAREA_FLAGS_PRIMARY;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// TODO: "ROM"
|
||||||
|
|
||||||
|
if (HuC_IsBRAMAvailable())
|
||||||
|
{
|
||||||
|
m[i].Data = (void*)(MemoryFunctionHook)AccessBRAM;
|
||||||
|
m[i].Name = "Battery RAM";
|
||||||
|
m[i].Size = 2048;
|
||||||
|
m[i].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_FUNCTIONHOOK | MEMORYAREA_FLAGS_SAVERAMMABLE;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PCE_IsCD)
|
||||||
|
{
|
||||||
|
// TODO: "TurboCD RAM" (var CDRAM)
|
||||||
|
|
||||||
|
m[i].Data = (void*)(MemoryFunctionHook)AccessADPCM;
|
||||||
|
m[i].Name = "ADPCM RAM";
|
||||||
|
m[i].Size = 1 << 16;
|
||||||
|
m[i].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_FUNCTIONHOOK;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// TODO: "Super System Card RAM"
|
||||||
|
// if (HuCPU.ReadMap[0x68] == SysCardRAMRead)
|
||||||
|
// {}
|
||||||
|
|
||||||
|
if (arcade_card)
|
||||||
|
{
|
||||||
|
m[i].Data = (void*)(MemoryFunctionHook)AccessArcade;
|
||||||
|
m[i].Name = "Arcade Card RAM";
|
||||||
|
m[i].Size = 1 << 16;
|
||||||
|
m[i].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_FUNCTIONHOOK;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: "Cart Battery RAM"
|
||||||
|
// if (IsPopulous)
|
||||||
|
// {}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue