2017-11-29 21:30:54 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The abstract class that all emulated models will inherit from
|
|
|
|
|
/// * Memory *
|
|
|
|
|
/// </summary>
|
|
|
|
|
public abstract partial class SpectrumBase
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// ROM Banks
|
|
|
|
|
/// </summary>
|
|
|
|
|
public byte[] ROM0 = new byte[0x4000];
|
|
|
|
|
public byte[] ROM1 = new byte[0x4000];
|
|
|
|
|
public byte[] ROM2 = new byte[0x4000];
|
|
|
|
|
public byte[] ROM3 = new byte[0x4000];
|
2018-03-05 16:12:19 +00:00
|
|
|
|
|
2017-11-29 21:30:54 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// RAM Banks
|
|
|
|
|
/// </summary>
|
|
|
|
|
public byte[] RAM0 = new byte[0x4000]; // Bank 0
|
|
|
|
|
public byte[] RAM1 = new byte[0x4000]; // Bank 1
|
|
|
|
|
public byte[] RAM2 = new byte[0x4000]; // Bank 2
|
|
|
|
|
public byte[] RAM3 = new byte[0x4000]; // Bank 3
|
|
|
|
|
public byte[] RAM4 = new byte[0x4000]; // Bank 4
|
|
|
|
|
public byte[] RAM5 = new byte[0x4000]; // Bank 5
|
|
|
|
|
public byte[] RAM6 = new byte[0x4000]; // Bank 6
|
|
|
|
|
public byte[] RAM7 = new byte[0x4000]; // Bank 7
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Represents the addressable memory space of the spectrum
|
|
|
|
|
/// All banks for the emulated system should be added during initialisation
|
|
|
|
|
/// </summary>
|
|
|
|
|
public Dictionary<int, byte[]> Memory = new Dictionary<int, byte[]>();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Simulates reading from the bus
|
|
|
|
|
/// Paging should be handled here
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="addr"></param>
|
|
|
|
|
/// <returns></returns>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
public abstract byte ReadBus(ushort addr);
|
2017-11-29 21:30:54 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
/// Pushes a value onto the data bus that should be valid as long as the interrupt is true
|
2017-11-29 21:30:54 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="addr"></param>
|
|
|
|
|
/// <returns></returns>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
public virtual byte PushBus()
|
2017-11-29 21:30:54 +00:00
|
|
|
|
{
|
2017-12-05 10:02:57 +00:00
|
|
|
|
return 0xFF;
|
2017-11-29 21:30:54 +00:00
|
|
|
|
}
|
2017-12-05 10:02:57 +00:00
|
|
|
|
|
2017-11-29 21:30:54 +00:00
|
|
|
|
/// <summary>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
/// Simulates writing to the bus
|
|
|
|
|
/// Paging should be handled here
|
2017-11-29 21:30:54 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="addr"></param>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
public virtual void WriteBus(ushort addr, byte value)
|
2017-11-29 21:30:54 +00:00
|
|
|
|
{
|
2017-12-05 10:02:57 +00:00
|
|
|
|
throw new NotImplementedException("Must be overriden");
|
2017-11-29 21:30:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
/// Reads a byte of data from a specified memory address
|
2017-11-29 21:30:54 +00:00
|
|
|
|
/// (with memory contention if appropriate)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="addr"></param>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public abstract byte ReadMemory(ushort addr);
|
2017-11-29 21:30:54 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Writes a byte of data to a specified memory address
|
2017-12-05 10:02:57 +00:00
|
|
|
|
/// (with memory contention if appropriate)
|
2017-11-29 21:30:54 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="addr"></param>
|
|
|
|
|
/// <param name="value"></param>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
public abstract void WriteMemory(ushort addr, byte value);
|
2017-11-29 21:30:54 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sets up the ROM
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer"></param>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
public abstract void InitROM(RomData romData);
|
2017-11-29 21:30:54 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// ULA reads the memory at the specified address
|
|
|
|
|
/// (No memory contention)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="addr"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public virtual byte FetchScreenMemory(ushort addr)
|
|
|
|
|
{
|
|
|
|
|
var value = ReadBus((ushort)((addr & 0x3FFF) + 0x4000));
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Helper function to refresh memory array (probably not the best way to do things)
|
|
|
|
|
/// </summary>
|
2017-12-05 10:02:57 +00:00
|
|
|
|
public abstract void ReInitMemory();
|
2018-03-12 14:37:45 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Detects whether the 48k rom is resident (or paged in) at 0x0001
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public virtual bool IsIn48kMode()
|
|
|
|
|
{
|
|
|
|
|
var data = ReadBus(0x0001);
|
|
|
|
|
if (data == 0xaf)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-12-11 14:08:00 +00:00
|
|
|
|
|
2017-11-29 21:30:54 +00:00
|
|
|
|
}
|
|
|
|
|
}
|