2017-04-14 17:28:23 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
namespace BizHawk.Emulation.Common
|
2016-12-14 15:11:07 +00:00
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A generic implementation of IMemoryDomain that can be used by any core
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <seealso cref="IMemoryDomains" />
|
2017-04-14 17:28:23 +00:00
|
|
|
|
public class MemoryDomainList : ReadOnlyCollection<MemoryDomain>, IMemoryDomains
|
|
|
|
|
{
|
|
|
|
|
private MemoryDomain _mainMemory;
|
|
|
|
|
private MemoryDomain _systemBus;
|
|
|
|
|
|
|
|
|
|
public bool Has(string name)
|
|
|
|
|
{
|
2020-02-26 21:51:29 +00:00
|
|
|
|
return this.Any(md => md.Name == name);
|
2017-04-14 17:28:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public MemoryDomainList(IList<MemoryDomain> domains)
|
|
|
|
|
: base(domains)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-29 18:59:08 +00:00
|
|
|
|
public MemoryDomain this[string name] => this.FirstOrDefault(x => x.Name == name);
|
2017-04-14 17:28:23 +00:00
|
|
|
|
|
|
|
|
|
public MemoryDomain MainMemory
|
|
|
|
|
{
|
2020-02-26 21:51:29 +00:00
|
|
|
|
get => _mainMemory ?? this.First();
|
2019-10-29 18:59:08 +00:00
|
|
|
|
set => _mainMemory = value;
|
2017-04-14 17:28:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-29 18:59:08 +00:00
|
|
|
|
public bool HasSystemBus => _systemBus != null || this.Any(x => x.Name == "System Bus");
|
2017-04-14 17:28:23 +00:00
|
|
|
|
|
|
|
|
|
public MemoryDomain SystemBus
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_systemBus != null)
|
|
|
|
|
{
|
|
|
|
|
return _systemBus;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 15:48:46 +00:00
|
|
|
|
return this.FirstOrDefault(x => x.Name == "System Bus") ?? MainMemory;
|
2017-04-14 17:28:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-29 18:59:08 +00:00
|
|
|
|
set => _systemBus = value;
|
2017-04-14 17:28:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// for core use only
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void MergeList(MemoryDomainList other)
|
|
|
|
|
{
|
|
|
|
|
var domains = this.ToDictionary(m => m.Name);
|
|
|
|
|
foreach (var src in other)
|
|
|
|
|
{
|
2019-10-29 18:59:08 +00:00
|
|
|
|
if (domains.TryGetValue(src.Name, out var dst))
|
2017-04-14 17:28:23 +00:00
|
|
|
|
{
|
|
|
|
|
TryMerge<MemoryDomainByteArray>(dst, src, (d, s) => d.Data = s.Data);
|
|
|
|
|
TryMerge<MemoryDomainIntPtr>(dst, src, (d, s) => d.Data = s.Data);
|
|
|
|
|
TryMerge<MemoryDomainIntPtrSwap16>(dst, src, (d, s) => d.Data = s.Data);
|
|
|
|
|
TryMerge<MemoryDomainDelegate>(dst, src, (d, s) => { d.Peek = s.Peek; d.Poke = s.Poke; });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// big hacks
|
|
|
|
|
/// </summary>
|
2017-04-27 17:53:20 +00:00
|
|
|
|
/// <typeparam name="T">The memory domain type to merge</typeparam>
|
2017-04-14 17:28:23 +00:00
|
|
|
|
private static void TryMerge<T>(MemoryDomain dest, MemoryDomain src, Action<T, T> func)
|
|
|
|
|
where T : MemoryDomain
|
|
|
|
|
{
|
2020-02-26 21:51:29 +00:00
|
|
|
|
if (dest is T d1 && src is T s1)
|
2017-04-14 17:28:23 +00:00
|
|
|
|
{
|
|
|
|
|
func(d1, s1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|