Skip to content

Commit 1a1de0f

Browse files
[Encore]
Remove GetVideoVirtualDimensions (no longer used) Add System Bus domain Fix deterministic time functionality using timezones when they should not
1 parent 20d7355 commit 1a1de0f

File tree

4 files changed

+228
-4
lines changed

4 files changed

+228
-4
lines changed

Assets/dll/encore.dll

176 KB
Binary file not shown.

src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IMemoryDomains.cs

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
using System.Buffers.Binary;
12
using System.Collections.Generic;
3+
using System.Runtime.InteropServices;
24

5+
using BizHawk.Common;
36
using BizHawk.Emulation.Common;
47

58
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS
@@ -28,6 +31,9 @@ private void InitMemoryDomains()
2831
domains.Add(_n3dsExRam);
2932
}
3033

34+
// extra domain for virtual memory (important for dealing with pointers!)
35+
domains.Add(new EncoreMMU(_context));
36+
3137
_memoryDomains = new MemoryDomainList(domains);
3238
_serviceProvider.Register(_memoryDomains);
3339
WireMemoryDomains();
@@ -47,5 +53,223 @@ void WireDomain(LibEncore.MemoryRegion region, MemoryDomainIntPtr domain)
4753
WireDomain(LibEncore.MemoryRegion.DSP, _dspRam);
4854
WireDomain(LibEncore.MemoryRegion.N3DS, _n3dsExRam);
4955
}
56+
57+
private class EncoreMMU : MemoryDomain
58+
{
59+
private const uint ENCORE_PAGE_SIZE = 0x1000;
60+
private const uint ENCORE_PAGE_MASK = ENCORE_PAGE_SIZE - 1;
61+
62+
private readonly IntPtr _context;
63+
64+
public EncoreMMU(IntPtr context)
65+
{
66+
Name = "System Bus";
67+
Size = 1L << 32;
68+
WordSize = 4;
69+
EndianType = Endian.Little;
70+
Writable = true;
71+
_context = context;
72+
}
73+
74+
private Span<byte> GetPage(uint addr)
75+
{
76+
var pagePointer = _core.Encore_GetPagePointer(_context, addr);
77+
return pagePointer == IntPtr.Zero ? [ ] : Util.UnsafeSpanFromPointer(pagePointer, (int)(ENCORE_PAGE_SIZE - (addr & ENCORE_PAGE_MASK)));
78+
}
79+
80+
public override byte PeekByte(long addr)
81+
{
82+
var page = GetPage((uint)addr);
83+
return page.IsEmpty ? (byte)0 : page[0];
84+
}
85+
86+
public override ushort PeekUshort(long addr, bool bigEndian)
87+
{
88+
// if we cross a page boundary, we need to read multiple pages
89+
if ((addr & ENCORE_PAGE_MASK) > ENCORE_PAGE_MASK - 1)
90+
{
91+
return base.PeekUshort(addr, bigEndian);
92+
}
93+
94+
var page = GetPage((uint)addr);
95+
if (page.IsEmpty)
96+
{
97+
return 0;
98+
}
99+
100+
return bigEndian
101+
? BinaryPrimitives.ReadUInt16BigEndian(page)
102+
: BinaryPrimitives.ReadUInt16LittleEndian(page);
103+
}
104+
105+
public override uint PeekUint(long addr, bool bigEndian)
106+
{
107+
// if we cross a page boundary, we need to read multiple pages
108+
if ((addr & ENCORE_PAGE_MASK) > ENCORE_PAGE_MASK - 3)
109+
{
110+
return base.PeekUint(addr, bigEndian);
111+
}
112+
113+
var page = GetPage((uint)addr);
114+
if (page.IsEmpty)
115+
{
116+
return 0;
117+
}
118+
119+
return bigEndian
120+
? BinaryPrimitives.ReadUInt32BigEndian(page)
121+
: BinaryPrimitives.ReadUInt32LittleEndian(page);
122+
}
123+
124+
public override void PokeByte(long addr, byte val)
125+
{
126+
var page = GetPage((uint)addr);
127+
if (page.IsEmpty)
128+
{
129+
return;
130+
}
131+
132+
page[0] = val;
133+
}
134+
135+
public override void PokeUshort(long addr, ushort val, bool bigEndian)
136+
{
137+
// if we cross a page boundary, we need to write to multiple pages
138+
if ((addr & ENCORE_PAGE_MASK) > ENCORE_PAGE_MASK - 1)
139+
{
140+
base.PokeUshort(addr, val, bigEndian);
141+
return;
142+
}
143+
144+
var page = GetPage((uint)addr);
145+
if (page.IsEmpty)
146+
{
147+
return;
148+
}
149+
150+
if (bigEndian)
151+
{
152+
BinaryPrimitives.WriteUInt16BigEndian(page, val);
153+
}
154+
else
155+
{
156+
BinaryPrimitives.WriteUInt16LittleEndian(page, val);
157+
}
158+
}
159+
160+
public override void PokeUint(long addr, uint val, bool bigEndian)
161+
{
162+
// if we cross a page boundary, we need to write to multiple pages
163+
if ((addr & ENCORE_PAGE_MASK) > ENCORE_PAGE_MASK - 3)
164+
{
165+
base.PokeUint(addr, val, bigEndian);
166+
return;
167+
}
168+
169+
var page = GetPage((uint)addr);
170+
if (page.IsEmpty)
171+
{
172+
return;
173+
}
174+
175+
if (bigEndian)
176+
{
177+
BinaryPrimitives.WriteUInt32BigEndian(page, val);
178+
}
179+
else
180+
{
181+
BinaryPrimitives.WriteUInt32LittleEndian(page, val);
182+
}
183+
}
184+
185+
private void BulkPeekByte(uint startAddr, Span<byte> values)
186+
{
187+
while (!values.IsEmpty)
188+
{
189+
var page = GetPage(startAddr);
190+
var numBytes = Math.Min(values.Length, (int)(ENCORE_PAGE_SIZE - (startAddr & ENCORE_PAGE_MASK)));
191+
if (page.IsEmpty)
192+
{
193+
values[..numBytes].Clear();
194+
}
195+
else
196+
{
197+
page[..numBytes].CopyTo(values);
198+
}
199+
200+
values = values[numBytes..];
201+
startAddr += (uint)numBytes;
202+
}
203+
}
204+
205+
public override void BulkPeekByte(Range<long> addresses, byte[] values)
206+
{
207+
if (addresses is null) throw new ArgumentNullException(paramName: nameof(addresses));
208+
if (values is null) throw new ArgumentNullException(paramName: nameof(values));
209+
210+
if ((long)addresses.Count() != values.Length)
211+
{
212+
throw new InvalidOperationException("Invalid length of values array");
213+
}
214+
215+
BulkPeekByte((uint)addresses.Start, values);
216+
}
217+
218+
public override void BulkPeekUshort(Range<long> addresses, bool bigEndian, ushort[] values)
219+
{
220+
if (addresses is null) throw new ArgumentNullException(paramName: nameof(addresses));
221+
if (values is null) throw new ArgumentNullException(paramName: nameof(values));
222+
223+
var start = addresses.Start;
224+
var end = addresses.EndInclusive + 1;
225+
226+
if ((start & 1) != 0 || (end & 1) != 0)
227+
throw new InvalidOperationException("The API contract doesn't define what to do for unaligned reads and writes!");
228+
229+
if (values.LongLength * 2 != end - start)
230+
{
231+
// a longer array could be valid, but nothing needs that so don't support it for now
232+
throw new InvalidOperationException("Invalid length of values array");
233+
}
234+
235+
BulkPeekByte((uint)addresses.Start, MemoryMarshal.AsBytes(values.AsSpan()));
236+
237+
if (!bigEndian)
238+
{
239+
for (var i = 0; i < values.Length; i++)
240+
{
241+
values[i] = BinaryPrimitives.ReverseEndianness(values[i]);
242+
}
243+
}
244+
}
245+
246+
public override void BulkPeekUint(Range<long> addresses, bool bigEndian, uint[] values)
247+
{
248+
if (addresses is null) throw new ArgumentNullException(paramName: nameof(addresses));
249+
if (values is null) throw new ArgumentNullException(paramName: nameof(values));
250+
251+
var start = addresses.Start;
252+
var end = addresses.EndInclusive + 1;
253+
254+
if ((start & 3) != 0 || (end & 3) != 0)
255+
throw new InvalidOperationException("The API contract doesn't define what to do for unaligned reads and writes!");
256+
257+
if (values.LongLength * 4 != end - start)
258+
{
259+
// a longer array could be valid, but nothing needs that so don't support it for now
260+
throw new InvalidOperationException("Invalid length of values array");
261+
}
262+
263+
BulkPeekByte((uint)addresses.Start, MemoryMarshal.AsBytes(values.AsSpan()));
264+
265+
if (!bigEndian)
266+
{
267+
for (var i = 0; i < values.Length; i++)
268+
{
269+
values[i] = BinaryPrimitives.ReverseEndianness(values[i]);
270+
}
271+
}
272+
}
273+
}
50274
}
51275
}

src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/LibEncore.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,6 @@ public abstract IntPtr Encore_CreateContext(
120120
[BizImport(cc)]
121121
public abstract void Encore_Reset(IntPtr context);
122122

123-
[BizImport(cc)]
124-
public abstract void Encore_GetVideoVirtualDimensions(IntPtr context, out int width, out int height);
125-
126123
[BizImport(cc)]
127124
public abstract void Encore_GetVideoBufferDimensions(IntPtr context, out int width, out int height);
128125

@@ -158,6 +155,9 @@ public enum MemoryRegion
158155
[BizImport(cc)]
159156
public abstract void Encore_GetMemoryRegion(IntPtr context, MemoryRegion region, out IntPtr ptr, out int size);
160157

158+
[BizImport(cc)]
159+
public abstract IntPtr Encore_GetPagePointer(IntPtr context, uint addr);
160+
161161
[BizImport(cc)]
162162
public abstract void Encore_GetTouchScreenLayout(IntPtr context, out int x, out int y, out int width, out int height, out bool rotated, out bool enabled);
163163
}

0 commit comments

Comments
 (0)