lynx mah boi https://www.youtube.com/watch?v=bNpLXo55yfw
This commit is contained in:
parent
ed4c715a9f
commit
28a37a57da
|
@ -45,7 +45,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{ "C64", "C64" },
|
{ "C64", "C64" },
|
||||||
{ "GEN", "Genesis" },
|
{ "GEN", "Genesis" },
|
||||||
{ "SMS", "Sega Master System" },
|
{ "SMS", "Sega Master System" },
|
||||||
{ "PSX", "Sony PlayStation" }
|
{ "PSX", "Sony PlayStation" },
|
||||||
|
{ "LYNX", "Atari Lynx" },
|
||||||
};
|
};
|
||||||
|
|
||||||
public string TargetSystem = null;
|
public string TargetSystem = null;
|
||||||
|
|
|
@ -331,6 +331,10 @@ namespace BizHawk.Emulation.Common
|
||||||
case ".WSC":
|
case ".WSC":
|
||||||
game.System = "WSWAN";
|
game.System = "WSWAN";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ".LNX":
|
||||||
|
game.System = "LYNX";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
game.Name = Path.GetFileNameWithoutExtension(fileName).Replace('_', ' ');
|
game.Name = Path.GetFileNameWithoutExtension(fileName).Replace('_', ' ');
|
||||||
|
|
|
@ -39,6 +39,9 @@ namespace BizHawk.Emulation.Common
|
||||||
Option("GBA", "Bios", GBA_JDebug);
|
Option("GBA", "Bios", GBA_JDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FirmwareAndOption("e4ed47fae31693e016b081c6bda48da5b70d7ccb", "LYNX", "Boot", "lynxboot.img", "Boot Rom");
|
||||||
|
|
||||||
|
|
||||||
//FirmwareAndOption("24F67BDEA115A2C847C8813A262502EE1607B7DF", "NDS", "Bios_Arm7", "biosnds7.rom", "ARM7 Bios");
|
//FirmwareAndOption("24F67BDEA115A2C847C8813A262502EE1607B7DF", "NDS", "Bios_Arm7", "biosnds7.rom", "ARM7 Bios");
|
||||||
//FirmwareAndOption("BFAAC75F101C135E32E2AAF541DE6B1BE4C8C62D", "NDS", "Bios_Arm9", "biosnds9.rom", "ARM9 Bios");
|
//FirmwareAndOption("BFAAC75F101C135E32E2AAF541DE6B1BE4C8C62D", "NDS", "Bios_Arm9", "biosnds9.rom", "ARM9 Bios");
|
||||||
FirmwareAndOption("5A65B922B562CB1F57DAB51B73151283F0E20C7A", "INTV", "EROM", "erom.bin", "Executive Rom");
|
FirmwareAndOption("5A65B922B562CB1F57DAB51B73151283F0E20C7A", "INTV", "EROM", "erom.bin", "Executive Rom");
|
||||||
|
|
|
@ -223,6 +223,8 @@
|
||||||
<Compile Include="Consoles\Atari\7800\Atari7800.Core.cs" />
|
<Compile Include="Consoles\Atari\7800\Atari7800.Core.cs" />
|
||||||
<Compile Include="Consoles\Atari\7800\Atari7800.cs" />
|
<Compile Include="Consoles\Atari\7800\Atari7800.cs" />
|
||||||
<Compile Include="Consoles\Atari\7800\Atari7800Control.cs" />
|
<Compile Include="Consoles\Atari\7800\Atari7800Control.cs" />
|
||||||
|
<Compile Include="Consoles\Atari\lynx\LibLynx.cs" />
|
||||||
|
<Compile Include="Consoles\Atari\lynx\Lynx.cs" />
|
||||||
<Compile Include="Consoles\Coleco\ColecoVision.cs" />
|
<Compile Include="Consoles\Coleco\ColecoVision.cs" />
|
||||||
<Compile Include="Consoles\Coleco\Input.cs" />
|
<Compile Include="Consoles\Coleco\Input.cs" />
|
||||||
<Compile Include="Consoles\Coleco\MemoryMap.cs" />
|
<Compile Include="Consoles\Coleco\MemoryMap.cs" />
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||||
|
{
|
||||||
|
public static class LibLynx
|
||||||
|
{
|
||||||
|
const string dllname = "bizlynx.dll";
|
||||||
|
const CallingConvention cc = CallingConvention.Cdecl;
|
||||||
|
|
||||||
|
[DllImport(dllname, CallingConvention = cc)]
|
||||||
|
public static extern IntPtr Create(byte[] game, int gamesize, byte[] bios, int biossize, int pagesize0, int pagesize1, bool lowpass);
|
||||||
|
|
||||||
|
[DllImport(dllname, CallingConvention = cc)]
|
||||||
|
public static extern void Destroy(IntPtr s);
|
||||||
|
|
||||||
|
[DllImport(dllname, CallingConvention = cc)]
|
||||||
|
public static extern void Reset(IntPtr s);
|
||||||
|
|
||||||
|
[DllImport(dllname, CallingConvention = cc)]
|
||||||
|
public static extern void Advance(IntPtr s, int buttons, int[] vbuff, short[] sbuff, ref int sbuffsize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,287 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using BizHawk.Common;
|
||||||
|
using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||||
|
{
|
||||||
|
[CoreAttributes("Handy", "K. Wilkins", true, false, "mednafen 0-9-34-1", "http://mednafen.sourceforge.net/")]
|
||||||
|
public class Lynx : IEmulator, IVideoProvider, ISyncSoundProvider
|
||||||
|
{
|
||||||
|
IntPtr Core;
|
||||||
|
|
||||||
|
[CoreConstructor("LYNX")]
|
||||||
|
public Lynx(byte[] file, GameInfo game, CoreComm comm)
|
||||||
|
{
|
||||||
|
CoreComm = comm;
|
||||||
|
|
||||||
|
byte[] bios = CoreComm.CoreFileProvider.GetFirmware("LYNX", "Boot", true, "Boot rom is required");
|
||||||
|
if (bios.Length != 512)
|
||||||
|
throw new MissingFirmwareException("Lynx Bootrom must be 512 bytes!");
|
||||||
|
|
||||||
|
int pagesize0 = 0;
|
||||||
|
int pagesize1 = 0;
|
||||||
|
byte[] realfile = null;
|
||||||
|
|
||||||
|
{
|
||||||
|
var ms = new MemoryStream(file, false);
|
||||||
|
var br = new BinaryReader(ms);
|
||||||
|
string header = Encoding.ASCII.GetString(br.ReadBytes(4));
|
||||||
|
int p0 = br.ReadUInt16();
|
||||||
|
int p1 = br.ReadUInt16();
|
||||||
|
int ver = br.ReadUInt16();
|
||||||
|
string cname = Encoding.ASCII.GetString(br.ReadBytes(32)).Trim();
|
||||||
|
string mname = Encoding.ASCII.GetString(br.ReadBytes(16)).Trim();
|
||||||
|
int rot = br.ReadByte();
|
||||||
|
|
||||||
|
ms.Position = 6;
|
||||||
|
string bs93 = Encoding.ASCII.GetString(br.ReadBytes(6));
|
||||||
|
if (bs93 == "BS93")
|
||||||
|
throw new InvalidOperationException("Unsupported BS93 Lynx ram image");
|
||||||
|
|
||||||
|
if (header == "LYNX" && (ver & 255) == 1)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Processing Handy-Lynx header");
|
||||||
|
pagesize0 = p0;
|
||||||
|
pagesize1 = p1;
|
||||||
|
Console.WriteLine("TODO: Rotate {0}", rot);
|
||||||
|
Console.WriteLine("Cart: {0} Manufacturer: {1}", cname, mname);
|
||||||
|
realfile = new byte[file.Length - 64];
|
||||||
|
Buffer.BlockCopy(file, 64, realfile, 0, realfile.Length);
|
||||||
|
Console.WriteLine("Header Listed banking: {0} {1}", p0, p1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("No Handy-Lynx header found! Assuming raw rom image.");
|
||||||
|
realfile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.OptionPresent("pagesize0"))
|
||||||
|
{
|
||||||
|
pagesize0 = int.Parse(game.OptionValue("pagesize0"));
|
||||||
|
pagesize1 = int.Parse(game.OptionValue("pagesize1"));
|
||||||
|
Console.WriteLine("Loading banking options {0} {1} from gamedb", pagesize0, pagesize1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesize0 == 0 && pagesize1 == 0)
|
||||||
|
{
|
||||||
|
switch (realfile.Length)
|
||||||
|
{
|
||||||
|
// these are untested
|
||||||
|
case 0x10000: pagesize0 = 0x100; break;
|
||||||
|
case 0x20000: pagesize0 = 0x200; break;
|
||||||
|
case 0x40000: pagesize0 = 0x400; break;
|
||||||
|
case 0x80000: pagesize0 = 0x800; break;
|
||||||
|
|
||||||
|
case 0x30000: pagesize0 = 0x200; pagesize1 = 0x100; break;
|
||||||
|
case 0x60000: pagesize0 = 0x400; pagesize1 = 0x200; break;
|
||||||
|
case 0xc0000: pagesize0 = 0x800; pagesize1 = 0x400; break;
|
||||||
|
case 0x100000: pagesize0 = 0x800; pagesize1 = 0x800; break;
|
||||||
|
|
||||||
|
}
|
||||||
|
Console.WriteLine("Auto-guessed banking options {0} {1}", pagesize0, pagesize1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Core = LibLynx.Create(realfile, realfile.Length, bios, bios.Length, pagesize0, pagesize1, false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FrameAdvance(bool render, bool rendersound = true)
|
||||||
|
{
|
||||||
|
Frame++;
|
||||||
|
|
||||||
|
if (Controller["Power"])
|
||||||
|
LibLynx.Reset(Core);
|
||||||
|
|
||||||
|
int samples = soundbuff.Length;
|
||||||
|
LibLynx.Advance(Core, 0, videobuff, soundbuff, ref samples);
|
||||||
|
numsamp = samples;
|
||||||
|
Console.WriteLine(numsamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Frame { get; private set; }
|
||||||
|
public int LagCount { get; set; }
|
||||||
|
public bool IsLagFrame { get; private set; }
|
||||||
|
|
||||||
|
public string SystemId { get { return "LYNX"; } }
|
||||||
|
|
||||||
|
public bool DeterministicEmulation { get { return true; } }
|
||||||
|
|
||||||
|
public void ResetCounters()
|
||||||
|
{
|
||||||
|
Frame = 0;
|
||||||
|
LagCount = 0;
|
||||||
|
IsLagFrame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BoardName { get { return null; } }
|
||||||
|
|
||||||
|
public CoreComm CoreComm { get; private set; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Core != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
LibLynx.Destroy(Core);
|
||||||
|
Core = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region debugging
|
||||||
|
|
||||||
|
public Dictionary<string, int> GetCpuFlagsAndRegisters()
|
||||||
|
{
|
||||||
|
return new Dictionary<string, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCpuRegister(string register, int value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Controller
|
||||||
|
|
||||||
|
public ControllerDefinition ControllerDefinition { get { return NullEmulator.NullController; } }
|
||||||
|
public IController Controller { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region savestates
|
||||||
|
|
||||||
|
public void SaveStateText(TextWriter writer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadStateText(TextReader reader)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveStateBinary(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadStateBinary(BinaryReader reader)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] SaveStateBinary()
|
||||||
|
{
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool BinarySaveStatesPreferred
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region saveram
|
||||||
|
|
||||||
|
public byte[] CloneSaveRam()
|
||||||
|
{
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StoreSaveRam(byte[] data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearSaveRam()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SaveRamModified
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region VideoProvider
|
||||||
|
|
||||||
|
const int WIDTH = 160;
|
||||||
|
const int HEIGHT = 102;
|
||||||
|
|
||||||
|
int[] videobuff = new int[WIDTH * HEIGHT];
|
||||||
|
|
||||||
|
public IVideoProvider VideoProvider { get { return this; } }
|
||||||
|
public int[] GetVideoBuffer() { return videobuff; }
|
||||||
|
public int VirtualWidth { get { return WIDTH; } }
|
||||||
|
public int VirtualHeight { get { return HEIGHT; } }
|
||||||
|
public int BufferWidth { get { return WIDTH; } }
|
||||||
|
public int BufferHeight { get { return HEIGHT; } }
|
||||||
|
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region SoundProvider
|
||||||
|
|
||||||
|
short[] soundbuff = new short[1000000]; // todo: make this smaller once frame loop is resolved
|
||||||
|
int numsamp;
|
||||||
|
|
||||||
|
public ISoundProvider SoundProvider { get { return null; } }
|
||||||
|
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||||
|
public bool StartAsyncSound() { return false; }
|
||||||
|
public void EndAsyncSound() { }
|
||||||
|
|
||||||
|
public void GetSamples(out short[] samples, out int nsamp)
|
||||||
|
{
|
||||||
|
samples = soundbuff;
|
||||||
|
nsamp = numsamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DiscardSamples()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Settings
|
||||||
|
|
||||||
|
public object GetSettings()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetSyncSettings()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool PutSettings(object o)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool PutSyncSettings(object o)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual Studio 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bizlynx", "bizlynx.vcxproj", "{C8DC23FF-551E-45DE-852D-22F66EDBACB9}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C8DC23FF-551E-45DE-852D-22F66EDBACB9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{C8DC23FF-551E-45DE-852D-22F66EDBACB9}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{C8DC23FF-551E-45DE-852D-22F66EDBACB9}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{C8DC23FF-551E-45DE-852D-22F66EDBACB9}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{C8DC23FF-551E-45DE-852D-22F66EDBACB9}</ProjectGuid>
|
||||||
|
<RootNamespace>bizlynx</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>..\msvc</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\..\output\dll\$(TargetFileName)</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<AdditionalIncludeDirectories>..\msvc</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\..\output\dll\$(TargetFileName)</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\c65c02.cpp" />
|
||||||
|
<ClCompile Include="..\cart.cpp" />
|
||||||
|
<ClCompile Include="..\cinterface.cpp" />
|
||||||
|
<ClCompile Include="..\memmap.cpp" />
|
||||||
|
<ClCompile Include="..\mikie.cpp" />
|
||||||
|
<ClCompile Include="..\ram.cpp" />
|
||||||
|
<ClCompile Include="..\rom.cpp" />
|
||||||
|
<ClCompile Include="..\sound\Blip_Buffer.cpp" />
|
||||||
|
<ClCompile Include="..\sound\Stereo_Buffer.cpp" />
|
||||||
|
<ClCompile Include="..\susie.cpp" />
|
||||||
|
<ClCompile Include="..\system.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\c6502mak.h" />
|
||||||
|
<ClInclude Include="..\c65c02.h" />
|
||||||
|
<ClInclude Include="..\cart.h" />
|
||||||
|
<ClInclude Include="..\lynxbase.h" />
|
||||||
|
<ClInclude Include="..\lynxdef.h" />
|
||||||
|
<ClInclude Include="..\machine.h" />
|
||||||
|
<ClInclude Include="..\mednafen.h" />
|
||||||
|
<ClInclude Include="..\memmap.h" />
|
||||||
|
<ClInclude Include="..\mikie.h" />
|
||||||
|
<ClInclude Include="..\ram.h" />
|
||||||
|
<ClInclude Include="..\rom.h" />
|
||||||
|
<ClInclude Include="..\sound\Blip_Buffer.h" />
|
||||||
|
<ClInclude Include="..\sound\Stereo_Buffer.h" />
|
||||||
|
<ClInclude Include="..\susie.h" />
|
||||||
|
<ClInclude Include="..\sysbase.h" />
|
||||||
|
<ClInclude Include="..\system.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,108 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\sound">
|
||||||
|
<UniqueIdentifier>{676beda4-1fca-49a2-acc8-67df1ab69690}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\sound">
|
||||||
|
<UniqueIdentifier>{7790947c-e33d-4f9b-a3bd-c72d9932bd76}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\c65c02.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cart.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\memmap.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\mikie.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\ram.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\rom.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\susie.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\system.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\sound\Blip_Buffer.cpp">
|
||||||
|
<Filter>Source Files\sound</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\sound\Stereo_Buffer.cpp">
|
||||||
|
<Filter>Source Files\sound</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cinterface.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\c65c02.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\c6502mak.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\cart.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\lynxbase.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\lynxdef.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\machine.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\memmap.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\mikie.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\ram.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\rom.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\susie.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\sysbase.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\system.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\mednafen.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\sound\Blip_Buffer.h">
|
||||||
|
<Filter>Header Files\sound</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\sound\Stereo_Buffer.h">
|
||||||
|
<Filter>Header Files\sound</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,694 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 65C02 Macro definitions //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This file contains all of the required address mode and operand //
|
||||||
|
// macro definitions for the 65C02 emulation //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//
|
||||||
|
// Addressing mode decoding
|
||||||
|
//
|
||||||
|
|
||||||
|
#define xIMMEDIATE() {mOperand=mPC;mPC++;}
|
||||||
|
#define xABSOLUTE() {mOperand=CPU_PEEKW(mPC);mPC+=2;}
|
||||||
|
#define xZEROPAGE() {mOperand=CPU_PEEK(mPC);mPC++;}
|
||||||
|
#define xZEROPAGE_X() {mOperand=CPU_PEEK(mPC)+mX;mPC++;mOperand&=0xff;}
|
||||||
|
#define xZEROPAGE_Y() {mOperand=CPU_PEEK(mPC)+mY;mPC++;mOperand&=0xff;}
|
||||||
|
#define xABSOLUTE_X() {mOperand=CPU_PEEKW(mPC);mPC+=2;mOperand+=mX;mOperand&=0xffff;}
|
||||||
|
#define xABSOLUTE_Y() {mOperand=CPU_PEEKW(mPC);mPC+=2;mOperand+=mY;mOperand&=0xffff;}
|
||||||
|
#define xINDIRECT_ABSOLUTE_X() {mOperand=CPU_PEEKW(mPC);mPC+=2;mOperand+=mX;mOperand&=0xffff;mOperand=CPU_PEEKW(mOperand);}
|
||||||
|
#define xRELATIVE() {mOperand=CPU_PEEK(mPC);mPC++;mOperand=(mPC+mOperand)&0xffff;}
|
||||||
|
#define xINDIRECT_X() {mOperand=CPU_PEEK(mPC);mPC++;mOperand=mOperand+mX;mOperand&=0x00ff;mOperand=CPU_PEEKW(mOperand);}
|
||||||
|
#define xINDIRECT_Y() {mOperand=CPU_PEEK(mPC);mPC++;mOperand=CPU_PEEKW(mOperand);mOperand=mOperand+mY;mOperand&=0xffff;}
|
||||||
|
#define xINDIRECT_ABSOLUTE() {mOperand=CPU_PEEKW(mPC);mPC+=2;mOperand=CPU_PEEKW(mOperand);}
|
||||||
|
#define xINDIRECT() {mOperand=CPU_PEEK(mPC);mPC++;mOperand=CPU_PEEKW(mOperand);}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper Macros
|
||||||
|
//
|
||||||
|
//#define SET_Z(m) { mZ=(m)?false:true; }
|
||||||
|
//#define SET_N(m) { mN=(m&0x80)?true:false; }
|
||||||
|
//#define SET_NZ(m) SET_Z(m) SET_N(m)
|
||||||
|
#define SET_Z(m) { mZ=!(m); }
|
||||||
|
#define SET_N(m) { mN=(m)&0x80; }
|
||||||
|
#define SET_NZ(m) { mZ=!(m); mN=(m)&0x80; }
|
||||||
|
#define PULL(m) { mSP++; mSP&=0xff; m=CPU_PEEK(mSP+0x0100); }
|
||||||
|
#define PUSH(m) { CPU_POKE(0x0100+mSP,m); mSP--; mSP&=0xff; }
|
||||||
|
//
|
||||||
|
// Opcode execution
|
||||||
|
//
|
||||||
|
|
||||||
|
#define xADC()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
if(mD)\
|
||||||
|
{\
|
||||||
|
int c = mC?1:0;\
|
||||||
|
int lo = (mA & 0x0f) + (value & 0x0f) + c;\
|
||||||
|
int hi = (mA & 0xf0) + (value & 0xf0);\
|
||||||
|
mV=0;\
|
||||||
|
mC=0;\
|
||||||
|
if (lo > 0x09)\
|
||||||
|
{\
|
||||||
|
hi += 0x10;\
|
||||||
|
lo += 0x06;\
|
||||||
|
}\
|
||||||
|
if (~(mA^value) & (mA^hi) & 0x80) mV=1;\
|
||||||
|
if (hi > 0x90) hi += 0x60;\
|
||||||
|
if (hi & 0xff00) mC=1;\
|
||||||
|
mA = (lo & 0x0f) + (hi & 0xf0);\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
int c = mC?1:0;\
|
||||||
|
int sum = mA + value + c;\
|
||||||
|
mV=0;\
|
||||||
|
mC=0;\
|
||||||
|
if (~(mA^value) & (mA^sum) & 0x80) mV=1;\
|
||||||
|
if (sum & 0xff00) mC=1;\
|
||||||
|
mA = (uint8) sum;\
|
||||||
|
}\
|
||||||
|
SET_NZ(mA)\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xAND()\
|
||||||
|
{\
|
||||||
|
mA&=CPU_PEEK(mOperand);\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xASL()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
mC=value&0x80;\
|
||||||
|
value<<=1;\
|
||||||
|
value&=0xff;\
|
||||||
|
SET_NZ(value);\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xASLA()\
|
||||||
|
{\
|
||||||
|
mC=mA&0x80;\
|
||||||
|
mA<<=1;\
|
||||||
|
mA&=0xff;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBCC()\
|
||||||
|
{\
|
||||||
|
if(!mC)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBCS()\
|
||||||
|
{\
|
||||||
|
if(mC)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBEQ()\
|
||||||
|
{\
|
||||||
|
if(mZ)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
// This version of bit, not setting N and V status flags in immediate, seems to be correct.
|
||||||
|
// The same behaviour is reported on the 65C02 used in old Apple computers, at least.
|
||||||
|
// (From a pragmatic sense, using the normal version of bit for immediate
|
||||||
|
// mode breaks the title screen of "California Games" in a subtle way.)
|
||||||
|
#define xBIT()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
SET_Z(mA&value);\
|
||||||
|
\
|
||||||
|
if(mOpcode!=0x89)\
|
||||||
|
{\
|
||||||
|
mN=value&0x80;\
|
||||||
|
mV=value&0x40;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
#define xBMI()\
|
||||||
|
{\
|
||||||
|
if(mN)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBNE()\
|
||||||
|
{\
|
||||||
|
if(!mZ)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBPL()\
|
||||||
|
{\
|
||||||
|
if(!mN)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBRA()\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBRK()\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
PUSH(mPC>>8);\
|
||||||
|
PUSH(mPC&0xff);\
|
||||||
|
PUSH(PS()|0x10);\
|
||||||
|
\
|
||||||
|
mD=FALSE;\
|
||||||
|
mI=TRUE;\
|
||||||
|
\
|
||||||
|
mPC=CPU_PEEKW(IRQ_VECTOR);\
|
||||||
|
}
|
||||||
|
// KW 4/11/98 B flag needed to be set IN the stack status word = 0x10.
|
||||||
|
|
||||||
|
#define xBVC()\
|
||||||
|
{\
|
||||||
|
if(!mV)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xBVS()\
|
||||||
|
{\
|
||||||
|
if(mV)\
|
||||||
|
{\
|
||||||
|
int offset=(signed char)CPU_PEEK(mPC);\
|
||||||
|
mPC++;\
|
||||||
|
mPC+=offset;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
mPC++;\
|
||||||
|
mPC&=0xffff;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xCLC()\
|
||||||
|
{\
|
||||||
|
mC=FALSE;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xCLD()\
|
||||||
|
{\
|
||||||
|
mD=FALSE;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xCLI()\
|
||||||
|
{\
|
||||||
|
mI=FALSE;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xCLV()\
|
||||||
|
{\
|
||||||
|
mV=FALSE;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xCMP()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
mC=0;\
|
||||||
|
if (mA >= value) mC=1;\
|
||||||
|
SET_NZ((uint8)(mA - value))\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xCPX()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
mC=0;\
|
||||||
|
if (mX >= value) mC=1;\
|
||||||
|
SET_NZ((uint8)(mX - value))\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xCPY()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
mC=0;\
|
||||||
|
if (mY >= value) mC=1;\
|
||||||
|
SET_NZ((uint8)(mY - value))\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xDEC()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand)-1;\
|
||||||
|
value&=0xff;\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
SET_NZ(value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xDECA()\
|
||||||
|
{\
|
||||||
|
mA--;\
|
||||||
|
mA&=0xff;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xDEX()\
|
||||||
|
{\
|
||||||
|
mX--;\
|
||||||
|
mX&=0xff;\
|
||||||
|
SET_NZ(mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xDEY()\
|
||||||
|
{\
|
||||||
|
mY--;\
|
||||||
|
mY&=0xff;\
|
||||||
|
SET_NZ(mY);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xEOR()\
|
||||||
|
{\
|
||||||
|
mA^=CPU_PEEK(mOperand);\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xINC()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand)+1;\
|
||||||
|
value&=0xff;\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
SET_NZ(value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xINCA()\
|
||||||
|
{\
|
||||||
|
mA++;\
|
||||||
|
mA&=0xff;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xINX()\
|
||||||
|
{\
|
||||||
|
mX++;\
|
||||||
|
mX&=0xff;\
|
||||||
|
SET_NZ(mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xINY()\
|
||||||
|
{\
|
||||||
|
mY++;\
|
||||||
|
mY&=0xff;\
|
||||||
|
SET_NZ(mY);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xJMP()\
|
||||||
|
{\
|
||||||
|
mPC=mOperand;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xJSR()\
|
||||||
|
{\
|
||||||
|
PUSH((mPC-1)>>8);\
|
||||||
|
PUSH((mPC-1)&0xff);\
|
||||||
|
mPC=mOperand;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xLDA()\
|
||||||
|
{\
|
||||||
|
mA=CPU_PEEK(mOperand);\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xLDX()\
|
||||||
|
{\
|
||||||
|
mX=CPU_PEEK(mOperand);\
|
||||||
|
SET_NZ(mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xLDY()\
|
||||||
|
{\
|
||||||
|
mY=CPU_PEEK(mOperand);\
|
||||||
|
SET_NZ(mY);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xLSR()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
mC=value&0x01;\
|
||||||
|
value=(value>>1)&0x7f;\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
SET_NZ(value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xLSRA()\
|
||||||
|
{\
|
||||||
|
mC=mA&0x01;\
|
||||||
|
mA=(mA>>1)&0x7f;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xNOP()\
|
||||||
|
{\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xORA()\
|
||||||
|
{\
|
||||||
|
mA|=CPU_PEEK(mOperand);\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPHA()\
|
||||||
|
{\
|
||||||
|
PUSH(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPHP()\
|
||||||
|
{\
|
||||||
|
PUSH(PS());\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPHX()\
|
||||||
|
{\
|
||||||
|
PUSH(mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPHY()\
|
||||||
|
{\
|
||||||
|
PUSH(mY);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPLA()\
|
||||||
|
{\
|
||||||
|
PULL(mA);\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPLP()\
|
||||||
|
{\
|
||||||
|
int P;\
|
||||||
|
PULL(P);\
|
||||||
|
PS(P);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPLX()\
|
||||||
|
{\
|
||||||
|
PULL(mX);\
|
||||||
|
SET_NZ(mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xPLY()\
|
||||||
|
{\
|
||||||
|
PULL(mY);\
|
||||||
|
SET_NZ(mY);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xROL()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
int oldC=mC;\
|
||||||
|
mC=value&0x80;\
|
||||||
|
value=(value<<1)|(oldC?1:0);\
|
||||||
|
value&=0xff;\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
SET_NZ(value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xROLA()\
|
||||||
|
{\
|
||||||
|
int oldC=mC;\
|
||||||
|
mC=mA&0x80;\
|
||||||
|
mA=(mA<<1)|(oldC?1:0);\
|
||||||
|
mA&=0xff;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xROR()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
int oldC=mC;\
|
||||||
|
mC=value&0x01;\
|
||||||
|
value=((value>>1)&0x7f)|(oldC?0x80:0x00);\
|
||||||
|
value&=0xff;\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
SET_NZ(value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xRORA()\
|
||||||
|
{\
|
||||||
|
int oldC=mC;\
|
||||||
|
mC=mA&0x01;\
|
||||||
|
mA=((mA>>1)&0x7f)|(oldC?0x80:0x00);\
|
||||||
|
mA&=0xff;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xRTI()\
|
||||||
|
{\
|
||||||
|
int tmp;\
|
||||||
|
PULL(tmp);\
|
||||||
|
PS(tmp);\
|
||||||
|
PULL(mPC);\
|
||||||
|
PULL(tmp);\
|
||||||
|
mPC|=tmp<<8;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xRTS()\
|
||||||
|
{\
|
||||||
|
int tmp;\
|
||||||
|
PULL(mPC);\
|
||||||
|
PULL(tmp);\
|
||||||
|
mPC|=tmp<<8;\
|
||||||
|
mPC++;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSBC()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
if (mD)\
|
||||||
|
{\
|
||||||
|
int c = mC?0:1;\
|
||||||
|
int sum = mA - value - c;\
|
||||||
|
int lo = (mA & 0x0f) - (value & 0x0f) - c;\
|
||||||
|
int hi = (mA & 0xf0) - (value & 0xf0);\
|
||||||
|
mV=0;\
|
||||||
|
mC=0;\
|
||||||
|
if ((mA^value) & (mA^sum) & 0x80) mV=1;\
|
||||||
|
if (lo & 0xf0) lo -= 6;\
|
||||||
|
if (lo & 0x80) hi -= 0x10;\
|
||||||
|
if (hi & 0x0f00) hi -= 0x60;\
|
||||||
|
if ((sum & 0xff00) == 0) mC=1;\
|
||||||
|
mA = (lo & 0x0f) + (hi & 0xf0);\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
{\
|
||||||
|
int c = mC?0:1;\
|
||||||
|
int sum = mA - value - c;\
|
||||||
|
mV=0;\
|
||||||
|
mC=0;\
|
||||||
|
if ((mA^value) & (mA^sum) & 0x80) mV=1;\
|
||||||
|
if ((sum & 0xff00) == 0) mC=1;\
|
||||||
|
mA = (uint8) sum;\
|
||||||
|
}\
|
||||||
|
SET_NZ(mA)\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSEC()\
|
||||||
|
{\
|
||||||
|
mC=true;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSED()\
|
||||||
|
{\
|
||||||
|
mD=true;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSEI()\
|
||||||
|
{\
|
||||||
|
mI=true;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSTA()\
|
||||||
|
{\
|
||||||
|
CPU_POKE(mOperand,mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSTP()\
|
||||||
|
{\
|
||||||
|
mSystem.gSystemCPUSleep=TRUE;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSTX()\
|
||||||
|
{\
|
||||||
|
CPU_POKE(mOperand,mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSTY()\
|
||||||
|
{\
|
||||||
|
CPU_POKE(mOperand,mY);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xSTZ()\
|
||||||
|
{\
|
||||||
|
CPU_POKE(mOperand,0);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTAX()\
|
||||||
|
{\
|
||||||
|
mX=mA;\
|
||||||
|
SET_NZ(mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTAY()\
|
||||||
|
{\
|
||||||
|
mY=mA;\
|
||||||
|
SET_NZ(mY);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTRB()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
SET_Z(mA&value);\
|
||||||
|
value=value&(mA^0xff);\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTSB()\
|
||||||
|
{\
|
||||||
|
int value=CPU_PEEK(mOperand);\
|
||||||
|
SET_Z(mA&value);\
|
||||||
|
value=value|mA;\
|
||||||
|
CPU_POKE(mOperand,value);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTSX()\
|
||||||
|
{\
|
||||||
|
mX=mSP;\
|
||||||
|
SET_NZ(mX);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTXA()\
|
||||||
|
{\
|
||||||
|
mA=mX;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTXS()\
|
||||||
|
{\
|
||||||
|
mSP=mX;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xTYA()\
|
||||||
|
{\
|
||||||
|
mA=mY;\
|
||||||
|
SET_NZ(mA);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xWAI()\
|
||||||
|
{\
|
||||||
|
mSystem.gSystemCPUSleep=TRUE;\
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,229 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 65C02 Emulation class //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This class emulates a 65C02 processor. It is interfaced to the rest of //
|
||||||
|
// the system via the PEEK/POKE macros and a number of global variables //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef C65C02_H
|
||||||
|
#define C65C02_H
|
||||||
|
|
||||||
|
//#include <crtdbg.h>
|
||||||
|
//#define TRACE_CPU
|
||||||
|
|
||||||
|
#ifdef TRACE_CPU
|
||||||
|
|
||||||
|
#define TRACE_CPU0(msg) _RPT1(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",gSystemCycleCount)
|
||||||
|
#define TRACE_CPU1(msg,arg1) _RPT2(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,gSystemCycleCount)
|
||||||
|
#define TRACE_CPU2(msg,arg1,arg2) _RPT3(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,arg2,gSystemCycleCount)
|
||||||
|
#define TRACE_CPU3(msg,arg1,arg2,arg3) _RPT4(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,arg2,arg3,gSystemCycleCount)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TRACE_CPU0(msg)
|
||||||
|
#define TRACE_CPU1(msg,arg1)
|
||||||
|
#define TRACE_CPU2(msg,arg1,arg2)
|
||||||
|
#define TRACE_CPU3(msg,arg1,arg2,arg3)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handy definitions
|
||||||
|
//
|
||||||
|
|
||||||
|
#define NMI_VECTOR 0xfffa
|
||||||
|
#define BOOT_VECTOR 0xfffc
|
||||||
|
#define IRQ_VECTOR 0xfffe
|
||||||
|
|
||||||
|
#define MAX_CPU_BREAKPOINTS 8
|
||||||
|
|
||||||
|
//
|
||||||
|
// ACCESS MACROS
|
||||||
|
//
|
||||||
|
|
||||||
|
//#define CPU_PEEK(m) (mSystem.Peek_CPU(m))
|
||||||
|
//#define CPU_PEEKW(m) (mSystem.PeekW_CPU(m))
|
||||||
|
//#define CPU_POKE(m1,m2) (mSystem.Poke_CPU(m1,m2))
|
||||||
|
|
||||||
|
#define CPU_PEEK(m) (((m<0xfc00)?mRamPointer[m]:mSystem.Peek_CPU(m)))
|
||||||
|
#define CPU_PEEKW(m) (((m<0xfc00)?(mRamPointer[m]+(mRamPointer[m+1]<<8)):mSystem.PeekW_CPU(m)))
|
||||||
|
#define CPU_POKE(m1,m2) {if(m1<0xfc00) mRamPointer[m1]=m2; else mSystem.Poke_CPU(m1,m2);}
|
||||||
|
|
||||||
|
|
||||||
|
enum { illegal=0,
|
||||||
|
accu,
|
||||||
|
imm,
|
||||||
|
absl,
|
||||||
|
zp,
|
||||||
|
zpx,
|
||||||
|
zpy,
|
||||||
|
absx,
|
||||||
|
absy,
|
||||||
|
iabsx,
|
||||||
|
impl,
|
||||||
|
rel,
|
||||||
|
zrel,
|
||||||
|
indx,
|
||||||
|
indy,
|
||||||
|
iabs,
|
||||||
|
ind
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int PS; // Processor status register 8 bits
|
||||||
|
int A; // Accumulator 8 bits
|
||||||
|
int X; // X index register 8 bits
|
||||||
|
int Y; // Y index register 8 bits
|
||||||
|
int SP; // Stack Pointer 8 bits
|
||||||
|
int Opcode; // Instruction opcode 8 bits
|
||||||
|
int Operand;// Intructions operand 16 bits
|
||||||
|
int PC; // Program Counter 16 bits
|
||||||
|
bool NMI;
|
||||||
|
bool IRQ;
|
||||||
|
bool WAIT;
|
||||||
|
}C6502_REGS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The CPU emulation macros
|
||||||
|
//
|
||||||
|
#include "c6502mak.h"
|
||||||
|
//
|
||||||
|
// The CPU emulation macros
|
||||||
|
//
|
||||||
|
|
||||||
|
class C65C02
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
C65C02(CSystem& parent)
|
||||||
|
:mSystem(parent)
|
||||||
|
{
|
||||||
|
TRACE_CPU0("C65C02()");
|
||||||
|
// Compute the BCD lookup table
|
||||||
|
for(uint16 t=0;t<256;++t)
|
||||||
|
{
|
||||||
|
mBCDTable[0][t]=((t >> 4) * 10) + (t & 0x0f);
|
||||||
|
mBCDTable[1][t]=(((t % 100) / 10) << 4) | (t % 10);
|
||||||
|
}
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~C65C02()
|
||||||
|
{
|
||||||
|
TRACE_CPU0("~C65C02()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Reset();
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void SetRegs(C6502_REGS ®s);
|
||||||
|
void GetRegs(C6502_REGS ®s);
|
||||||
|
|
||||||
|
|
||||||
|
inline int GetPC() { return mPC; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSystem &mSystem;
|
||||||
|
|
||||||
|
// CPU Flags & status
|
||||||
|
|
||||||
|
int mA; // Accumulator 8 bits
|
||||||
|
int mX; // X index register 8 bits
|
||||||
|
int mY; // Y index register 8 bits
|
||||||
|
int mSP; // Stack Pointer 8 bits
|
||||||
|
int mOpcode; // Instruction opcode 8 bits
|
||||||
|
int mOperand; // Intructions operand 16 bits
|
||||||
|
int mPC; // Program Counter 16 bits
|
||||||
|
|
||||||
|
int mN; // N flag for processor status register
|
||||||
|
int mV; // V flag for processor status register
|
||||||
|
int mB; // B flag for processor status register
|
||||||
|
int mD; // D flag for processor status register
|
||||||
|
int mI; // I flag for processor status register
|
||||||
|
int mZ; // Z flag for processor status register
|
||||||
|
int mC; // C flag for processor status register
|
||||||
|
|
||||||
|
int mIRQActive;
|
||||||
|
|
||||||
|
uint8 *mRamPointer;
|
||||||
|
|
||||||
|
// Associated lookup tables
|
||||||
|
|
||||||
|
int mBCDTable[2][256];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Opcode prototypes
|
||||||
|
//
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Answers value of the Processor Status register
|
||||||
|
INLINE int PS() const
|
||||||
|
{
|
||||||
|
uint8 ps = 0x20;
|
||||||
|
if(mN) ps|=0x80;
|
||||||
|
if(mV) ps|=0x40;
|
||||||
|
if(mB) ps|=0x10;
|
||||||
|
if(mD) ps|=0x08;
|
||||||
|
if(mI) ps|=0x04;
|
||||||
|
if(mZ) ps|=0x02;
|
||||||
|
if(mC) ps|=0x01;
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Change the processor flags to correspond to the given value
|
||||||
|
INLINE void PS(int ps)
|
||||||
|
{
|
||||||
|
mN=ps&0x80;
|
||||||
|
mV=ps&0x40;
|
||||||
|
mB=ps&0x10;
|
||||||
|
mD=ps&0x08;
|
||||||
|
mI=ps&0x04;
|
||||||
|
mZ=ps&0x02;
|
||||||
|
mC=ps&0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,316 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Lynx Cartridge Class //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This class emulates the Lynx cartridge interface, given a filename it //
|
||||||
|
// will contstruct a cartridge object via the constructor. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define CART_CPP
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string.h>
|
||||||
|
#include "cart.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool CCart::TestMagic(const uint8 *data, uint32 size)
|
||||||
|
{
|
||||||
|
if(size <= HEADER_RAW_SIZE)
|
||||||
|
return(FALSE);
|
||||||
|
|
||||||
|
if(memcmp(data, "LYNX", 4) || data[8] != 0x01)
|
||||||
|
return(FALSE);
|
||||||
|
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
CCart::CCart(const uint8 *gamedata, uint32 gamesize, int pagesize0, int pagesize1)
|
||||||
|
{
|
||||||
|
CTYPE banktype0,banktype1;
|
||||||
|
|
||||||
|
switch(pagesize0)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
// warn?
|
||||||
|
case 0x000:
|
||||||
|
banktype0=UNUSED;
|
||||||
|
mMaskBank0=0;
|
||||||
|
mShiftCount0=0;
|
||||||
|
mCountMask0=0;
|
||||||
|
break;
|
||||||
|
case 0x100:
|
||||||
|
banktype0=C64K;
|
||||||
|
mMaskBank0=0x00ffff;
|
||||||
|
mShiftCount0=8;
|
||||||
|
mCountMask0=0x0ff;
|
||||||
|
break;
|
||||||
|
case 0x200:
|
||||||
|
banktype0=C128K;
|
||||||
|
mMaskBank0=0x01ffff;
|
||||||
|
mShiftCount0=9;
|
||||||
|
mCountMask0=0x1ff;
|
||||||
|
break;
|
||||||
|
case 0x400:
|
||||||
|
banktype0=C256K;
|
||||||
|
mMaskBank0=0x03ffff;
|
||||||
|
mShiftCount0=10;
|
||||||
|
mCountMask0=0x3ff;
|
||||||
|
break;
|
||||||
|
case 0x800:
|
||||||
|
banktype0=C512K;
|
||||||
|
mMaskBank0=0x07ffff;
|
||||||
|
mShiftCount0=11;
|
||||||
|
mCountMask0=0x7ff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(pagesize1)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
// warn?
|
||||||
|
case 0x000:
|
||||||
|
banktype1=UNUSED;
|
||||||
|
mMaskBank1=0;
|
||||||
|
mShiftCount1=0;
|
||||||
|
mCountMask1=0;
|
||||||
|
break;
|
||||||
|
case 0x100:
|
||||||
|
banktype1=C64K;
|
||||||
|
mMaskBank1=0x00ffff;
|
||||||
|
mShiftCount1=8;
|
||||||
|
mCountMask1=0x0ff;
|
||||||
|
break;
|
||||||
|
case 0x200:
|
||||||
|
banktype1=C128K;
|
||||||
|
mMaskBank1=0x01ffff;
|
||||||
|
mShiftCount1=9;
|
||||||
|
mCountMask1=0x1ff;
|
||||||
|
break;
|
||||||
|
case 0x400:
|
||||||
|
banktype1=C256K;
|
||||||
|
mMaskBank1=0x03ffff;
|
||||||
|
mShiftCount1=10;
|
||||||
|
mCountMask1=0x3ff;
|
||||||
|
break;
|
||||||
|
case 0x800:
|
||||||
|
banktype1=C512K;
|
||||||
|
mMaskBank1=0x07ffff;
|
||||||
|
mShiftCount1=11;
|
||||||
|
mCountMask1=0x7ff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make some space for the new carts
|
||||||
|
mCartBank0 = new uint8[mMaskBank0+1];
|
||||||
|
mCartBank1 = new uint8[mMaskBank1+1];
|
||||||
|
|
||||||
|
// Set default bank
|
||||||
|
mBank=bank0;
|
||||||
|
|
||||||
|
// Initialiase
|
||||||
|
std::memset(mCartBank0, DEFAULT_CART_CONTENTS, mMaskBank0 + 1);
|
||||||
|
std::memset(mCartBank1, DEFAULT_CART_CONTENTS, mMaskBank1 + 1);
|
||||||
|
|
||||||
|
// Read in the BANK0 bytes
|
||||||
|
if(mMaskBank0)
|
||||||
|
{
|
||||||
|
int size = std::min(gamesize, mMaskBank0+1);
|
||||||
|
std::memcpy(mCartBank0, gamedata, size);
|
||||||
|
gamedata += size;
|
||||||
|
gamesize -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read in the BANK1 bytes
|
||||||
|
if(mMaskBank1)
|
||||||
|
{
|
||||||
|
int size = std::min(gamesize, mMaskBank1+1);
|
||||||
|
std::memcpy(mCartBank1, gamedata, size);
|
||||||
|
gamedata += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// As this is a cartridge boot unset the boot address
|
||||||
|
// mSystem.gCPUBootAddress=0;
|
||||||
|
|
||||||
|
// Dont allow an empty Bank1 - Use it for shadow SRAM/EEPROM
|
||||||
|
if(banktype1==UNUSED)
|
||||||
|
{
|
||||||
|
// Delete the single byte allocated earlier
|
||||||
|
delete[] mCartBank1;
|
||||||
|
// Allocate some new memory for us
|
||||||
|
banktype1=C64K;
|
||||||
|
mMaskBank1=0x00ffff;
|
||||||
|
mShiftCount1=8;
|
||||||
|
mCountMask1=0x0ff;
|
||||||
|
mCartBank1 = (uint8*) new uint8[mMaskBank1+1];
|
||||||
|
std::memset(mCartBank1, DEFAULT_RAM_CONTENTS, mMaskBank1 + 1);
|
||||||
|
mWriteEnableBank1=TRUE;
|
||||||
|
mCartRAM=TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CCart::~CCart()
|
||||||
|
{
|
||||||
|
delete[] mCartBank0;
|
||||||
|
delete[] mCartBank1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CCart::Reset()
|
||||||
|
{
|
||||||
|
mCounter = 0;
|
||||||
|
mShifter = 0;
|
||||||
|
mAddrData = 0;
|
||||||
|
mStrobe = 0;
|
||||||
|
last_strobe = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void CCart::Poke(uint32 addr, uint8 data)
|
||||||
|
{
|
||||||
|
if(mBank==bank0)
|
||||||
|
{
|
||||||
|
if(mWriteEnableBank0)
|
||||||
|
mCartBank0[addr&mMaskBank0]=data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(mWriteEnableBank1)
|
||||||
|
mCartBank1[addr&mMaskBank1]=data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
INLINE uint8 CCart::Peek(uint32 addr)
|
||||||
|
{
|
||||||
|
if(mBank==bank0)
|
||||||
|
{
|
||||||
|
return(mCartBank0[addr&mMaskBank0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(mCartBank1[addr&mMaskBank1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CCart::CartAddressStrobe(bool strobe)
|
||||||
|
{
|
||||||
|
mStrobe=strobe;
|
||||||
|
|
||||||
|
if(mStrobe) mCounter=0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Either of the two below seem to work OK.
|
||||||
|
//
|
||||||
|
// if(!strobe && last_strobe)
|
||||||
|
//
|
||||||
|
if(mStrobe && !last_strobe)
|
||||||
|
{
|
||||||
|
// Clock a bit into the shifter
|
||||||
|
mShifter=mShifter<<1;
|
||||||
|
mShifter+=mAddrData?1:0;
|
||||||
|
mShifter&=0xff;
|
||||||
|
}
|
||||||
|
last_strobe=mStrobe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCart::CartAddressData(bool data)
|
||||||
|
{
|
||||||
|
mAddrData=data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CCart::Poke0(uint8 data)
|
||||||
|
{
|
||||||
|
if(mWriteEnableBank0)
|
||||||
|
{
|
||||||
|
uint32 address=(mShifter<<mShiftCount0)+(mCounter&mCountMask0);
|
||||||
|
mCartBank0[address&mMaskBank0]=data;
|
||||||
|
}
|
||||||
|
if(!mStrobe)
|
||||||
|
{
|
||||||
|
mCounter++;
|
||||||
|
mCounter&=0x07ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCart::Poke1(uint8 data)
|
||||||
|
{
|
||||||
|
if(mWriteEnableBank1)
|
||||||
|
{
|
||||||
|
uint32 address=(mShifter<<mShiftCount1)+(mCounter&mCountMask1);
|
||||||
|
mCartBank1[address&mMaskBank1]=data;
|
||||||
|
}
|
||||||
|
if(!mStrobe)
|
||||||
|
{
|
||||||
|
mCounter++;
|
||||||
|
mCounter&=0x07ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8 CCart::Peek0(void)
|
||||||
|
{
|
||||||
|
uint32 address=(mShifter<<mShiftCount0)+(mCounter&mCountMask0);
|
||||||
|
uint8 data=mCartBank0[address&mMaskBank0];
|
||||||
|
|
||||||
|
if(!mStrobe)
|
||||||
|
{
|
||||||
|
mCounter++;
|
||||||
|
mCounter&=0x07ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CCart::Peek1(void)
|
||||||
|
{
|
||||||
|
uint32 address=(mShifter<<mShiftCount1)+(mCounter&mCountMask1);
|
||||||
|
uint8 data=mCartBank1[address&mMaskBank1];
|
||||||
|
|
||||||
|
if(!mStrobe)
|
||||||
|
{
|
||||||
|
mCounter++;
|
||||||
|
mCounter&=0x07ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Lynx cartridge class header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition and code for some of //
|
||||||
|
// the simpler cartridge API. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef CART_H
|
||||||
|
#define CART_H
|
||||||
|
|
||||||
|
#define DEFAULT_CART_CONTENTS 0x11
|
||||||
|
|
||||||
|
enum CTYPE {UNUSED,C64K,C128K,C256K,C512K,C1024K};
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define CART_NO_ROTATE 0
|
||||||
|
#define CART_ROTATE_LEFT 1
|
||||||
|
#define CART_ROTATE_RIGHT 2
|
||||||
|
|
||||||
|
struct LYNX_HEADER
|
||||||
|
{
|
||||||
|
uint8 magic[4]; // "LYNX"
|
||||||
|
uint16 page_size_bank0;
|
||||||
|
uint16 page_size_bank1; // "BS93" for unsupported homebrews
|
||||||
|
uint16 version;
|
||||||
|
uint8 cartname[32];
|
||||||
|
uint8 manufname[16];
|
||||||
|
uint8 rotation;
|
||||||
|
uint8 spare[5];
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CCart : public CLynxBase
|
||||||
|
{
|
||||||
|
// Function members
|
||||||
|
|
||||||
|
public:
|
||||||
|
CCart(const uint8 *gamedata, uint32 gamesize, int pagesize0, int pagesize1) MDFN_COLD;
|
||||||
|
~CCart() MDFN_COLD;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Access for sensible members of the clan
|
||||||
|
enum { HEADER_RAW_SIZE = 64 };
|
||||||
|
|
||||||
|
//static bool TestMagic(const uint8 *data, uint32 size);
|
||||||
|
|
||||||
|
void Reset(void) MDFN_COLD;
|
||||||
|
void Poke(uint32 addr,uint8 data);
|
||||||
|
uint8 Peek(uint32 addr);
|
||||||
|
uint32 ReadCycle(void) {return 15;};
|
||||||
|
uint32 WriteCycle(void) {return 15;};
|
||||||
|
void BankSelect(EMMODE newbank) {mBank=newbank;}
|
||||||
|
uint32 ObjectSize(void) {return (mBank==bank0)?mMaskBank0+1:mMaskBank1+1;};
|
||||||
|
|
||||||
|
// Access for the lynx itself, it has no idea of address etc as this is done by the
|
||||||
|
// cartridge emulation hardware
|
||||||
|
void CartAddressStrobe(bool strobe);
|
||||||
|
void CartAddressData(bool data);
|
||||||
|
void Poke0(uint8 data);
|
||||||
|
void Poke1(uint8 data);
|
||||||
|
uint8 Peek0(void);
|
||||||
|
uint8 Peek1(void);
|
||||||
|
|
||||||
|
// Data members
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint32 mWriteEnableBank0;
|
||||||
|
uint32 mWriteEnableBank1;
|
||||||
|
uint32 mCartRAM;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EMMODE mBank;
|
||||||
|
uint32 mMaskBank0;
|
||||||
|
uint32 mMaskBank1;
|
||||||
|
uint8 *mCartBank0;
|
||||||
|
uint8 *mCartBank1;
|
||||||
|
|
||||||
|
uint32 mCounter;
|
||||||
|
uint32 mShifter;
|
||||||
|
uint32 mAddrData;
|
||||||
|
uint32 mStrobe;
|
||||||
|
|
||||||
|
uint32 mShiftCount0;
|
||||||
|
uint32 mCountMask0;
|
||||||
|
uint32 mShiftCount1;
|
||||||
|
uint32 mCountMask1;
|
||||||
|
|
||||||
|
int8 last_strobe;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
void *operator new(std::size_t n)
|
||||||
|
{
|
||||||
|
void *p = std::malloc(n);
|
||||||
|
std::memset(p, 0, n);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *p)
|
||||||
|
{
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EXPORT extern "C" __declspec(dllexport)
|
||||||
|
|
||||||
|
EXPORT CSystem *Create(const uint8 *game, uint32 gamesize, const uint8 *bios, uint32 biossize, int pagesize0, int pagesize1, int lowpass)
|
||||||
|
{
|
||||||
|
return new CSystem(game, gamesize, bios, biossize, pagesize0, pagesize1, lowpass);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void Destroy(CSystem *s)
|
||||||
|
{
|
||||||
|
delete s;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void Reset(CSystem *s)
|
||||||
|
{
|
||||||
|
s->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void Advance(CSystem *s, int buttons, uint32 *vbuff, int16 *sbuff, int *sbuffsize)
|
||||||
|
{
|
||||||
|
s->Advance(buttons, vbuff, sbuff, *sbuffsize);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
|
@ -0,0 +1,56 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generic Lynx base class.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef LYNXBASE_H
|
||||||
|
#define LYNXBASE_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// bank0 - Cartridge bank 0
|
||||||
|
// bank1 - Cartridge bank 1
|
||||||
|
// ram - all ram
|
||||||
|
// cpu - system memory as viewed by the cpu
|
||||||
|
//
|
||||||
|
enum EMMODE {bank0,bank1,ram,cpu};
|
||||||
|
|
||||||
|
class CLynxBase
|
||||||
|
{
|
||||||
|
// Function members
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~CLynxBase() {};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void Reset(void) {};
|
||||||
|
|
||||||
|
virtual void Poke(uint32 addr,uint8 data)=0;
|
||||||
|
virtual uint8 Peek(uint32 addr)=0;
|
||||||
|
virtual void PokeW(uint32 addr,uint16 data) {}; // ONLY mSystem overloads these, they are never use by the clients
|
||||||
|
virtual uint16 PeekW(uint32 addr) {return 0;};
|
||||||
|
virtual void BankSelect(EMMODE newbank){};
|
||||||
|
virtual uint32 ObjectSize(void) {return 1;};
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,287 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Generic lyynx definition header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the definition of all of the useful hardware //
|
||||||
|
// addreses within the Lynx. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define TMPADR 0xfc00
|
||||||
|
#define TMPADRL 0xfc00
|
||||||
|
#define TMPADRH 0xfc01
|
||||||
|
#define TILTACUM 0xfc02
|
||||||
|
#define TILTACUML 0xfc02
|
||||||
|
#define TILTACUMH 0xfc03
|
||||||
|
#define HOFF 0xfc04
|
||||||
|
#define HOFFL 0xfc04
|
||||||
|
#define HOFFH 0xfc05
|
||||||
|
#define VOFF 0xfc06
|
||||||
|
#define VOFFL 0xfc06
|
||||||
|
#define VOFFH 0xfc07
|
||||||
|
#define VIDBAS 0xfc08
|
||||||
|
#define VIDBASL 0xfc08
|
||||||
|
#define VIDBASH 0xfc09
|
||||||
|
#define COLLBAS 0xfc0a
|
||||||
|
#define COLLBASL 0xfc0a
|
||||||
|
#define COLLBASH 0xfc0b
|
||||||
|
#define VIDADR 0xfc0c
|
||||||
|
#define VIDADRL 0xfc0c
|
||||||
|
#define VIDADRH 0xfc0d
|
||||||
|
#define COLLADR 0xfc0e
|
||||||
|
#define COLLADRL 0xfc0e
|
||||||
|
#define COLLADRH 0xfc0f
|
||||||
|
#define SCBNEXT 0xfc10
|
||||||
|
#define SCBNEXTL 0xfc10
|
||||||
|
#define SCBNEXTH 0xfc11
|
||||||
|
#define SPRDLINE 0xfc12
|
||||||
|
#define SPRDLINEL 0xfc12
|
||||||
|
#define SPRDLINEH 0xfc13
|
||||||
|
#define HPOSSTRT 0xfc14
|
||||||
|
#define HPOSSTRTL 0xfc14
|
||||||
|
#define HPOSSTRTH 0xfc15
|
||||||
|
#define VPOSSTRT 0xfc16
|
||||||
|
#define VPOSSTRTL 0xfc16
|
||||||
|
#define VPOSSTRTH 0xfc17
|
||||||
|
#define SPRHSIZ 0xfc18
|
||||||
|
#define SPRHSIZL 0xfc18
|
||||||
|
#define SPRHSIZH 0xfc19
|
||||||
|
#define SPRVSIZ 0xfc1a
|
||||||
|
#define SPRVSIZL 0xfc1a
|
||||||
|
#define SPRVSIZH 0xfc1b
|
||||||
|
#define STRETCH 0xfc1c
|
||||||
|
#define STRETCHL 0xfc1c
|
||||||
|
#define STRETCHH 0xfc1d
|
||||||
|
#define TILT 0xfc1e
|
||||||
|
#define TILTL 0xfc1e
|
||||||
|
#define TILTH 0xfc1f
|
||||||
|
#define SPRDOFF 0xfc20
|
||||||
|
#define SPRDOFFL 0xfc20
|
||||||
|
#define SPRDOFFH 0xfc21
|
||||||
|
#define SPRVPOS 0xfc22
|
||||||
|
#define SPRVPOSL 0xfc22
|
||||||
|
#define SPRVPOSH 0xfc23
|
||||||
|
#define COLLOFF 0xfc24
|
||||||
|
#define COLLOFFL 0xfc24
|
||||||
|
#define COLLOFFH 0xfc25
|
||||||
|
#define VSIZACUM 0xfc26
|
||||||
|
#define VSIZACUML 0xfc26
|
||||||
|
#define VSIZACUMH 0xfc27
|
||||||
|
#define HSIZOFF 0xfc28
|
||||||
|
#define HSIZOFFL 0xfc28
|
||||||
|
#define HSIZOFFH 0xfc29
|
||||||
|
#define VSIZOFF 0xfc2a
|
||||||
|
#define VSIZOFFL 0xfc2a
|
||||||
|
#define VSIZOFFH 0xfc2b
|
||||||
|
#define SCBADR 0xfc2c
|
||||||
|
#define SCBADRL 0xfc2c
|
||||||
|
#define SCBADRH 0xfc2d
|
||||||
|
#define PROCADR 0xfc2e
|
||||||
|
#define PROCADRL 0xfc2e
|
||||||
|
#define PROCADRH 0xfc2f
|
||||||
|
#define MATHD 0xfc52
|
||||||
|
#define MATHC 0xfc53
|
||||||
|
#define MATHB 0xfc54
|
||||||
|
#define MATHA 0xfc55
|
||||||
|
#define MATHP 0xfc56
|
||||||
|
#define MATHN 0xfc57
|
||||||
|
#define MATHH 0xfc60
|
||||||
|
#define MATHG 0xfc61
|
||||||
|
#define MATHF 0xfc62
|
||||||
|
#define MATHE 0xfc63
|
||||||
|
#define MATHM 0xfc6c
|
||||||
|
#define MATHL 0xfc6d
|
||||||
|
#define MATHK 0xfc6e
|
||||||
|
#define MATHJ 0xfc6f
|
||||||
|
#define SPRCTL0 0xfc80
|
||||||
|
#define SPRCTL1 0xfc81
|
||||||
|
#define SPRCOLL 0xfc82
|
||||||
|
#define SPRINIT 0xfc83
|
||||||
|
#define SUZYHREV 0xfc88
|
||||||
|
#define SUZYSREV 0xfc89
|
||||||
|
#define SUZYBUSEN 0xfc90
|
||||||
|
#define SPRGO 0xfc91
|
||||||
|
#define SPRSYS 0xfc92
|
||||||
|
#define JOYSTICK 0xfcb0
|
||||||
|
#define SWITCHES 0xfcb1
|
||||||
|
#define RCART0 0xfcb2
|
||||||
|
#define RCART1 0xfcb3
|
||||||
|
#define LEDS 0xfcc0
|
||||||
|
#define PPORTSTAT 0xfcc2
|
||||||
|
#define PPORTDATA 0xfcc3
|
||||||
|
#define HOWIE 0xfcc4
|
||||||
|
#define TIM0BKUP 0xfd00
|
||||||
|
#define TIM0CTLA 0xfd01
|
||||||
|
#define TIM0CNT 0xfd02
|
||||||
|
#define TIM0CTLB 0xfd03
|
||||||
|
#define TIM1BKUP 0xfd04
|
||||||
|
#define TIM1CTLA 0xfd05
|
||||||
|
#define TIM1CNT 0xfd06
|
||||||
|
#define TIM1CTLB 0xfd07
|
||||||
|
#define TIM2BKUP 0xfd08
|
||||||
|
#define TIM2CTLA 0xfd09
|
||||||
|
#define TIM2CNT 0xfd0a
|
||||||
|
#define TIM2CTLB 0xfd0b
|
||||||
|
#define TIM3BKUP 0xfd0c
|
||||||
|
#define TIM3CTLA 0xfd0d
|
||||||
|
#define TIM3CNT 0xfd0e
|
||||||
|
#define TIM3CTLB 0xfd0f
|
||||||
|
#define TIM4BKUP 0xfd10
|
||||||
|
#define TIM4CTLA 0xfd11
|
||||||
|
#define TIM4CNT 0xfd12
|
||||||
|
#define TIM4CTLB 0xfd13
|
||||||
|
#define TIM5BKUP 0xfd14
|
||||||
|
#define TIM5CTLA 0xfd15
|
||||||
|
#define TIM5CNT 0xfd16
|
||||||
|
#define TIM5CTLB 0xfd17
|
||||||
|
#define TIM6BKUP 0xfd18
|
||||||
|
#define TIM6CTLA 0xfd19
|
||||||
|
#define TIM6CNT 0xfd1a
|
||||||
|
#define TIM6CTLB 0xfd1b
|
||||||
|
#define TIM7BKUP 0xfd1c
|
||||||
|
#define TIM7CTLA 0xfd1d
|
||||||
|
#define TIM7CNT 0xfd1e
|
||||||
|
#define TIM7CTLB 0xfd1f
|
||||||
|
|
||||||
|
#define AUD0VOL 0xfd20
|
||||||
|
#define AUD0SHFTFB 0xfd21
|
||||||
|
#define AUD0OUTVAL 0xfd22
|
||||||
|
#define AUD0L8SHFT 0xfd23
|
||||||
|
#define AUD0TBACK 0xfd24
|
||||||
|
#define AUD0CTL 0xfd25
|
||||||
|
#define AUD0COUNT 0xfd26
|
||||||
|
#define AUD0MISC 0xfd27
|
||||||
|
|
||||||
|
#define AUD1VOL 0xfd28
|
||||||
|
#define AUD1SHFTFB 0xfd29
|
||||||
|
#define AUD1OUTVAL 0xfd2a
|
||||||
|
#define AUD1L8SHFT 0xfd2b
|
||||||
|
#define AUD1TBACK 0xfd2c
|
||||||
|
#define AUD1CTL 0xfd2d
|
||||||
|
#define AUD1COUNT 0xfd2e
|
||||||
|
#define AUD1MISC 0xfd2f
|
||||||
|
|
||||||
|
#define AUD2VOL 0xfd30
|
||||||
|
#define AUD2SHFTFB 0xfd31
|
||||||
|
#define AUD2OUTVAL 0xfd32
|
||||||
|
#define AUD2L8SHFT 0xfd33
|
||||||
|
#define AUD2TBACK 0xfd34
|
||||||
|
#define AUD2CTL 0xfd35
|
||||||
|
#define AUD2COUNT 0xfd36
|
||||||
|
#define AUD2MISC 0xfd37
|
||||||
|
|
||||||
|
#define AUD3VOL 0xfd38
|
||||||
|
#define AUD3SHFTFB 0xfd39
|
||||||
|
#define AUD3OUTVAL 0xfd3a
|
||||||
|
#define AUD3L8SHFT 0xfd3b
|
||||||
|
#define AUD3TBACK 0xfd3c
|
||||||
|
#define AUD3CTL 0xfd3d
|
||||||
|
#define AUD3COUNT 0xfd3e
|
||||||
|
#define AUD3MISC 0xfd3f
|
||||||
|
|
||||||
|
#define ATTEN_A 0xFD40 //
|
||||||
|
#define ATTEN_B 0xFD41
|
||||||
|
#define ATTEN_C 0xFD42 // Lynx2 Regs see macros/handy.equ
|
||||||
|
#define ATTEN_D 0xFD43
|
||||||
|
#define MPAN 0xFD44 //
|
||||||
|
#define MSTEREO 0xfd50
|
||||||
|
#define INTRST 0xfd80
|
||||||
|
#define INTSET 0xfd81
|
||||||
|
#define MAGRDY0 0xfd84
|
||||||
|
#define MAGRDY1 0xfd85
|
||||||
|
#define AUDIN 0xfd86
|
||||||
|
#define SYSCTL1 0xfd87
|
||||||
|
#define MIKEYHREV 0xfd88
|
||||||
|
#define MIKEYSREV 0xfd89
|
||||||
|
#define IODIR 0xfd8a
|
||||||
|
#define IODAT 0xfd8b
|
||||||
|
#define SERCTL 0xfd8c
|
||||||
|
#define SERDAT 0xfd8d
|
||||||
|
#define SDONEACK 0xfd90
|
||||||
|
#define CPUSLEEP 0xfd91
|
||||||
|
#define DISPCTL 0xfd92
|
||||||
|
#define PBKUP 0xfd93
|
||||||
|
#define DISPADR 0xfd94
|
||||||
|
#define DISPADRL 0xfd94
|
||||||
|
#define DISPADRH 0xfd95
|
||||||
|
#define Mtest0 0xfd9c
|
||||||
|
#define Mtest1 0xfd9d
|
||||||
|
#define Mtest2 0xfd9e
|
||||||
|
#define GREEN0 0xfda0
|
||||||
|
#define GREEN1 0xfda1
|
||||||
|
#define GREEN2 0xfda2
|
||||||
|
#define GREEN3 0xfda3
|
||||||
|
#define GREEN4 0xfda4
|
||||||
|
#define GREEN5 0xfda5
|
||||||
|
#define GREEN6 0xfda6
|
||||||
|
#define GREEN7 0xfda7
|
||||||
|
#define GREEN8 0xfda8
|
||||||
|
#define GREEN9 0xfda9
|
||||||
|
#define GREENA 0xfdaa
|
||||||
|
#define GREENB 0xfdab
|
||||||
|
#define GREENC 0xfdac
|
||||||
|
#define GREEND 0xfdad
|
||||||
|
#define GREENE 0xfdae
|
||||||
|
#define GREENF 0xfdaf
|
||||||
|
#define BLUERED0 0xfdb0
|
||||||
|
#define BLUERED1 0xfdb1
|
||||||
|
#define BLUERED2 0xfdb2
|
||||||
|
#define BLUERED3 0xfdb3
|
||||||
|
#define BLUERED4 0xfdb4
|
||||||
|
#define BLUERED5 0xfdb5
|
||||||
|
#define BLUERED6 0xfdb6
|
||||||
|
#define BLUERED7 0xfdb7
|
||||||
|
#define BLUERED8 0xfdb8
|
||||||
|
#define BLUERED9 0xfdb9
|
||||||
|
#define BLUEREDA 0xfdba
|
||||||
|
#define BLUEREDB 0xfdbb
|
||||||
|
#define BLUEREDC 0xfdbc
|
||||||
|
#define BLUEREDD 0xfdbd
|
||||||
|
#define BLUEREDE 0xfdbe
|
||||||
|
#define BLUEREDF 0xfdbf
|
||||||
|
#define MMAPCTL 0xfff9
|
||||||
|
#define CPUNMI 0xfffa
|
||||||
|
#define CPUNMIL 0xfffa
|
||||||
|
#define CPUNMIH 0xfffb
|
||||||
|
#define CPURESET 0xfffc
|
||||||
|
#define CPURESETL 0xfffc
|
||||||
|
#define CPURESETH 0xfffd
|
||||||
|
#define CPUINT 0xfffe
|
||||||
|
#define CPUINTL 0xfffe
|
||||||
|
#define CPUINTH 0xffff
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Core machine definitions header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition and code for the core //
|
||||||
|
// definitions used throughout the Handy code. Additionally it provides //
|
||||||
|
// a generic memory object definition. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MACHINE_H
|
||||||
|
#define MACHINE_H
|
||||||
|
|
||||||
|
#include "mednafen.h"
|
||||||
|
|
||||||
|
// Read/Write Cycle definitions
|
||||||
|
#define CPU_RDWR_CYC 5
|
||||||
|
#define DMA_RDWR_CYC 4
|
||||||
|
#define SPR_RDWR_CYC 3
|
||||||
|
// Ammended to 2 on 28/04/00, 16Mhz = 62.5nS cycle
|
||||||
|
//
|
||||||
|
// 2 cycles is 125ns - PAGE MODE CYCLE
|
||||||
|
// 4 cycles is 250ns - NORMAL MODE CYCLE
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "lynxbase.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef MEDNAFEN_H
|
||||||
|
#define MEDNAFEN_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
typedef int8_t int8;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
|
||||||
|
typedef uint8_t uint8;
|
||||||
|
typedef uint16_t uint16;
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
|
#define MDFN_COLD
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
#define INLINE
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 High;
|
||||||
|
uint8 Low;
|
||||||
|
#else
|
||||||
|
uint8 Low;
|
||||||
|
uint8 High;
|
||||||
|
#endif
|
||||||
|
} Union8;
|
||||||
|
uint16 Val16;
|
||||||
|
};
|
||||||
|
} Uuint16;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
Uuint16 High;
|
||||||
|
Uuint16 Low;
|
||||||
|
#else
|
||||||
|
Uuint16 Low;
|
||||||
|
Uuint16 High;
|
||||||
|
#endif
|
||||||
|
} Union16;
|
||||||
|
uint32 Val32;
|
||||||
|
};
|
||||||
|
} Uuint32;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,189 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Lynx memory map class //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This class provides the register $FFF9 functionality to the emulator, it //
|
||||||
|
// sets which devices can be seen by the CPU. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define MEMMAP_CPP
|
||||||
|
|
||||||
|
//#include <crtdbg.h>
|
||||||
|
//#define TRACE_MEMMAP
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "memmap.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// IGNORE THIS TEXT, now overridden by new system
|
||||||
|
//
|
||||||
|
// We will hold 16 different memory maps for the "top" area which are selected
|
||||||
|
// on the basis of mMemMap->mSelector:
|
||||||
|
//
|
||||||
|
// Code Vect ROM Mikie Susie
|
||||||
|
//----------------------------------------------------
|
||||||
|
// (Default) 0000 V R M S
|
||||||
|
// 0001 V R M RAM
|
||||||
|
// 0001 V R RAM S
|
||||||
|
// 0011 V R RAM RAM
|
||||||
|
// 0100 V RAM M S
|
||||||
|
// ..
|
||||||
|
// ..
|
||||||
|
// 1111 RAM RAM RAM RAM
|
||||||
|
//
|
||||||
|
// Get it.....
|
||||||
|
//
|
||||||
|
// We can then index with mMemoryHandlers[mMemMap->mSelector][addr] for speed
|
||||||
|
//
|
||||||
|
|
||||||
|
CMemMap::CMemMap(CSystem& parent)
|
||||||
|
:mSystem(parent)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CMemMap::Reset(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Initialise ALL pointers to RAM then overload to correct
|
||||||
|
for(int loop=0;loop<SYSTEM_SIZE;loop++) mSystem.mMemoryHandlers[loop]=mSystem.mRam;
|
||||||
|
|
||||||
|
// Special case for ourselves.
|
||||||
|
mSystem.mMemoryHandlers[0xFFF8]=mSystem.mRam;
|
||||||
|
mSystem.mMemoryHandlers[0xFFF9]=mSystem.mMemMap;
|
||||||
|
|
||||||
|
mSusieEnabled=-1;
|
||||||
|
mMikieEnabled=-1;
|
||||||
|
mRomEnabled=-1;
|
||||||
|
mVectorsEnabled=-1;
|
||||||
|
|
||||||
|
// Initialise everything correctly
|
||||||
|
Poke(0,0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
INLINE void CMemMap::Poke(uint32 addr, uint8 data)
|
||||||
|
{
|
||||||
|
TRACE_MEMMAP1("Poke() - Data %02x",data);
|
||||||
|
|
||||||
|
int newstate,loop;
|
||||||
|
|
||||||
|
// FC00-FCFF Susie area
|
||||||
|
newstate=(data&0x01)?FALSE:TRUE;
|
||||||
|
if(newstate!=mSusieEnabled)
|
||||||
|
{
|
||||||
|
mSusieEnabled=newstate;
|
||||||
|
|
||||||
|
if(mSusieEnabled)
|
||||||
|
{
|
||||||
|
for(loop=SUSIE_START;loop<SUSIE_START+SUSIE_SIZE;loop++) mSystem.mMemoryHandlers[loop]=mSystem.mSusie;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(loop=SUSIE_START;loop<SUSIE_START+SUSIE_SIZE;loop++) mSystem.mMemoryHandlers[loop]=mSystem.mRam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FD00-FCFF Mikie area
|
||||||
|
newstate=(data&0x02)?FALSE:TRUE;
|
||||||
|
if(newstate!=mMikieEnabled)
|
||||||
|
{
|
||||||
|
mMikieEnabled=newstate;
|
||||||
|
|
||||||
|
if(mMikieEnabled)
|
||||||
|
{
|
||||||
|
for(loop=MIKIE_START;loop<MIKIE_START+MIKIE_SIZE;loop++) mSystem.mMemoryHandlers[loop]=mSystem.mMikie;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(loop=MIKIE_START;loop<MIKIE_START+MIKIE_SIZE;loop++) mSystem.mMemoryHandlers[loop]=mSystem.mRam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FE00-FFF7 Rom area
|
||||||
|
newstate=(data&0x04)?FALSE:TRUE;
|
||||||
|
if(newstate!=mRomEnabled)
|
||||||
|
{
|
||||||
|
mRomEnabled=newstate;
|
||||||
|
|
||||||
|
if(mRomEnabled)
|
||||||
|
{
|
||||||
|
for(loop=BROM_START;loop<BROM_START+(BROM_SIZE-8);loop++) mSystem.mMemoryHandlers[loop]=mSystem.mRom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(loop=BROM_START;loop<BROM_START+(BROM_SIZE-8);loop++) mSystem.mMemoryHandlers[loop]=mSystem.mRam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FFFA-FFFF Vector area - Overload ROM space
|
||||||
|
newstate=(data&0x08)?FALSE:TRUE;
|
||||||
|
if(newstate!=mVectorsEnabled)
|
||||||
|
{
|
||||||
|
mVectorsEnabled=newstate;
|
||||||
|
|
||||||
|
if(mVectorsEnabled)
|
||||||
|
{
|
||||||
|
for(loop=VECTOR_START;loop<VECTOR_START+VECTOR_SIZE;loop++) mSystem.mMemoryHandlers[loop]=mSystem.mRom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(loop=VECTOR_START;loop<VECTOR_START+VECTOR_SIZE;loop++) mSystem.mMemoryHandlers[loop]=mSystem.mRam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE uint8 CMemMap::Peek(uint32 addr)
|
||||||
|
{
|
||||||
|
uint8 retval=0;
|
||||||
|
|
||||||
|
retval+=(mSusieEnabled)?0:0x01;
|
||||||
|
retval+=(mMikieEnabled)?0:0x02;
|
||||||
|
retval+=(mRomEnabled)?0:0x04;
|
||||||
|
retval+=(mVectorsEnabled)?0:0x08;
|
||||||
|
TRACE_MEMMAP1("Peek() - Data %02x",retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
//END OF FILE
|
|
@ -0,0 +1,95 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Lynx memory map object header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition for the memory map //
|
||||||
|
// object, this object controls which pieces of lynx hardware are //
|
||||||
|
// accesible by the CPU at any given time, it is the code for addr $FFF9 //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MEMMAP_H
|
||||||
|
#define MEMMAP_H
|
||||||
|
|
||||||
|
#define MEMMAP_SIZE 0x1
|
||||||
|
|
||||||
|
#ifdef TRACE_CART
|
||||||
|
|
||||||
|
#define TRACE_MEMMAP0(msg) _RPT1(_CRT_WARN,"CMamMap::"msg" (Time=%012d)\n",gSystemCycleCount)
|
||||||
|
#define TRACE_MEMMAP1(msg,arg1) _RPT2(_CRT_WARN,"CMamMap::"msg" (Time=%012d)\n",arg1,gSystemCycleCount)
|
||||||
|
#define TRACE_MEMMAP2(msg,arg1,arg2) _RPT3(_CRT_WARN,"CMamMap::"msg" (Time=%012d)\n",arg1,arg2,gSystemCycleCount)
|
||||||
|
#define TRACE_MEMMAP3(msg,arg1,arg2,arg3) _RPT4(_CRT_WARN,"CMamMap::"msg" (Time=%012d)\n",arg1,arg2,arg3,gSystemCycleCount)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TRACE_MEMMAP0(msg)
|
||||||
|
#define TRACE_MEMMAP1(msg,arg1)
|
||||||
|
#define TRACE_MEMMAP2(msg,arg1,arg2)
|
||||||
|
#define TRACE_MEMMAP3(msg,arg1,arg2,arg3)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CMemMap : public CLynxBase
|
||||||
|
{
|
||||||
|
// Function members
|
||||||
|
|
||||||
|
public:
|
||||||
|
CMemMap(CSystem& parent) MDFN_COLD;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Reset(void) MDFN_COLD;
|
||||||
|
|
||||||
|
void Poke(uint32 addr,uint8 data);
|
||||||
|
uint8 Peek(uint32 addr);
|
||||||
|
uint32 ReadCycle(void) {return 5;};
|
||||||
|
uint32 WriteCycle(void) {return 5;};
|
||||||
|
uint32 ObjectSize(void) {return MEMMAP_SIZE;};
|
||||||
|
|
||||||
|
// Data members
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mMikieEnabled;
|
||||||
|
int mSusieEnabled;
|
||||||
|
int mRomEnabled;
|
||||||
|
int mVectorsEnabled;
|
||||||
|
|
||||||
|
CSystem& mSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,406 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mikey class header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition and some of the code //
|
||||||
|
// for the Mikey chip within the Lynx. The most crucial code is the //
|
||||||
|
// Update() function which as you can probably guess updates all of the //
|
||||||
|
// Mikey hardware counters and screen DMA from the prevous time it was //
|
||||||
|
// called. Yes I know how to spell Mikey but I cant be bothered to change //
|
||||||
|
// it everywhere. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MIKIE_H
|
||||||
|
#define MIKIE_H
|
||||||
|
|
||||||
|
//#include <crtdbg.h>
|
||||||
|
//#define TRACE_MIKIE
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef TRACE_MIKIE
|
||||||
|
|
||||||
|
#define TRACE_MIKIE0(msg) _RPT1(_CRT_WARN,"CMikie::"msg" (Time=%012d)\n",gSystemCycleCount)
|
||||||
|
#define TRACE_MIKIE1(msg,arg1) _RPT2(_CRT_WARN,"CMikie::"msg" (Time=%012d)\n",arg1,gSystemCycleCount)
|
||||||
|
#define TRACE_MIKIE2(msg,arg1,arg2) _RPT3(_CRT_WARN,"CMikie::"msg" (Time=%012d)\n",arg1,arg2,gSystemCycleCount)
|
||||||
|
#define TRACE_MIKIE3(msg,arg1,arg2,arg3) _RPT4(_CRT_WARN,"CMikie::"msg" (Time=%012d)\n",arg1,arg2,arg3,gSystemCycleCount)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TRACE_MIKIE0(msg)
|
||||||
|
#define TRACE_MIKIE1(msg,arg1)
|
||||||
|
#define TRACE_MIKIE2(msg,arg1,arg2)
|
||||||
|
#define TRACE_MIKIE3(msg,arg1,arg2,arg3)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CSystem;
|
||||||
|
|
||||||
|
#define MIKIE_START 0xfd00
|
||||||
|
#define MIKIE_SIZE 0x100
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define counter types and defines
|
||||||
|
//
|
||||||
|
|
||||||
|
#define CTRL_A_IRQEN 0x80
|
||||||
|
#define CTRL_A_RTD 0x40
|
||||||
|
#define CTRL_A_RELOAD 0x10
|
||||||
|
#define CTRL_A_COUNT 0x08
|
||||||
|
#define CTRL_A_DIVIDE 0x07
|
||||||
|
|
||||||
|
#define CTRL_B_TDONE 0x08
|
||||||
|
#define CTRL_B_LASTCK 0x04
|
||||||
|
#define CTRL_B_CIN 0x02
|
||||||
|
#define CTRL_B_COUT 0x01
|
||||||
|
|
||||||
|
#define LINE_TIMER 0x00
|
||||||
|
#define SCREEN_TIMER 0x02
|
||||||
|
|
||||||
|
#define LINE_WIDTH 160
|
||||||
|
#define LINE_SIZE 80
|
||||||
|
|
||||||
|
#define UART_TX_INACTIVE 0x80000000
|
||||||
|
#define UART_RX_INACTIVE 0x80000000
|
||||||
|
#define UART_BREAK_CODE 0x00008000
|
||||||
|
#define UART_MAX_RX_QUEUE 32
|
||||||
|
#define UART_TX_TIME_PERIOD (11)
|
||||||
|
#define UART_RX_TIME_PERIOD (11)
|
||||||
|
#define UART_RX_NEXT_DELAY (44)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 unused:4;
|
||||||
|
uint8 Colour:1;
|
||||||
|
uint8 FourColour:1;
|
||||||
|
uint8 Flip:1;
|
||||||
|
uint8 DMAEnable:1;
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint8 DMAEnable:1;
|
||||||
|
uint8 Flip:1;
|
||||||
|
uint8 FourColour:1;
|
||||||
|
uint8 Colour:1;
|
||||||
|
uint8 unused:4;
|
||||||
|
#endif
|
||||||
|
}Bits;
|
||||||
|
uint8 Byte;
|
||||||
|
};
|
||||||
|
}TDISPCTL;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 unused:8;
|
||||||
|
uint8 unused2:8;
|
||||||
|
uint8 unused3:4;
|
||||||
|
uint8 Blue:4;
|
||||||
|
uint8 Red:4;
|
||||||
|
uint8 Green:4;
|
||||||
|
#else
|
||||||
|
uint8 Green:4;
|
||||||
|
uint8 Red:4;
|
||||||
|
uint8 Blue:4;
|
||||||
|
#endif
|
||||||
|
}Colours;
|
||||||
|
uint32 Index;
|
||||||
|
};
|
||||||
|
}TPALETTE;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Emumerated types for possible mikie windows independant modes
|
||||||
|
//
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MIKIE_BAD_MODE=0,
|
||||||
|
MIKIE_NO_ROTATE,
|
||||||
|
MIKIE_ROTATE_L,
|
||||||
|
MIKIE_ROTATE_R
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MIKIE_PIXEL_FORMAT_8BPP=0,
|
||||||
|
MIKIE_PIXEL_FORMAT_16BPP_555,
|
||||||
|
MIKIE_PIXEL_FORMAT_16BPP_565,
|
||||||
|
MIKIE_PIXEL_FORMAT_24BPP,
|
||||||
|
MIKIE_PIXEL_FORMAT_32BPP,
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "sound/Stereo_Buffer.h"
|
||||||
|
|
||||||
|
typedef Blip_Synth<blip_good_quality, 256 * 4> Synth;
|
||||||
|
|
||||||
|
class CMikie : public CLynxBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMikie(CSystem& parent) MDFN_COLD;
|
||||||
|
~CMikie() MDFN_COLD;
|
||||||
|
|
||||||
|
uint32 startTS;
|
||||||
|
Synth miksynth;
|
||||||
|
Stereo_Buffer mikbuf;
|
||||||
|
|
||||||
|
void Reset() MDFN_COLD;
|
||||||
|
|
||||||
|
uint8 Peek(uint32 addr);
|
||||||
|
void Poke(uint32 addr,uint8 data);
|
||||||
|
uint32 ReadCycle() {return 5;};
|
||||||
|
uint32 WriteCycle() {return 5;};
|
||||||
|
uint32 ObjectSize() {return MIKIE_SIZE;};
|
||||||
|
void PresetForHomebrew();
|
||||||
|
uint32 GetLfsrNext(uint32 current);
|
||||||
|
|
||||||
|
void ComLynxCable(int status);
|
||||||
|
void ComLynxRxData(int data);
|
||||||
|
void ComLynxTxLoopback(int data);
|
||||||
|
void ComLynxTxCallback(void (*function)(int data,uint32 objref),uint32 objref);
|
||||||
|
|
||||||
|
void DisplaySetAttributes();
|
||||||
|
|
||||||
|
void BlowOut();
|
||||||
|
|
||||||
|
uint32 DisplayRenderLine();
|
||||||
|
uint32 DisplayEndOfFrame();
|
||||||
|
|
||||||
|
inline void SetCPUSleep();
|
||||||
|
inline void ClearCPUSleep();
|
||||||
|
|
||||||
|
void CombobulateSound(uint32 teatime);
|
||||||
|
void Update();
|
||||||
|
void CheckWrap();
|
||||||
|
|
||||||
|
uint32* mpDisplayCurrent;
|
||||||
|
uint32 mpDisplayCurrentLine;
|
||||||
|
uint32 framebuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSystem &mSystem;
|
||||||
|
|
||||||
|
int last_lsample;
|
||||||
|
int last_rsample;
|
||||||
|
|
||||||
|
// Hardware storage
|
||||||
|
|
||||||
|
uint32 mDisplayAddress;
|
||||||
|
uint32 mAudioInputComparator;
|
||||||
|
uint32 mTimerStatusFlags;
|
||||||
|
uint32 mTimerInterruptMask;
|
||||||
|
|
||||||
|
TPALETTE mPalette[16];
|
||||||
|
uint32 mColourMap[4096];
|
||||||
|
|
||||||
|
uint32 mIODAT;
|
||||||
|
uint32 mIODIR;
|
||||||
|
uint32 mIODAT_REST_SIGNAL;
|
||||||
|
|
||||||
|
uint32 mDISPCTL_DMAEnable;
|
||||||
|
uint32 mDISPCTL_Flip;
|
||||||
|
uint32 mDISPCTL_FourColour;
|
||||||
|
uint32 mDISPCTL_Colour;
|
||||||
|
|
||||||
|
uint32 mTIM_0_BKUP;
|
||||||
|
uint32 mTIM_0_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_0_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_0_LINKING;
|
||||||
|
uint32 mTIM_0_CURRENT;
|
||||||
|
uint32 mTIM_0_TIMER_DONE;
|
||||||
|
uint32 mTIM_0_LAST_CLOCK;
|
||||||
|
uint32 mTIM_0_BORROW_IN;
|
||||||
|
uint32 mTIM_0_BORROW_OUT;
|
||||||
|
uint32 mTIM_0_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_0_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mTIM_1_BKUP;
|
||||||
|
uint32 mTIM_1_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_1_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_1_LINKING;
|
||||||
|
uint32 mTIM_1_CURRENT;
|
||||||
|
uint32 mTIM_1_TIMER_DONE;
|
||||||
|
uint32 mTIM_1_LAST_CLOCK;
|
||||||
|
uint32 mTIM_1_BORROW_IN;
|
||||||
|
uint32 mTIM_1_BORROW_OUT;
|
||||||
|
uint32 mTIM_1_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_1_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mTIM_2_BKUP;
|
||||||
|
uint32 mTIM_2_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_2_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_2_LINKING;
|
||||||
|
uint32 mTIM_2_CURRENT;
|
||||||
|
uint32 mTIM_2_TIMER_DONE;
|
||||||
|
uint32 mTIM_2_LAST_CLOCK;
|
||||||
|
uint32 mTIM_2_BORROW_IN;
|
||||||
|
uint32 mTIM_2_BORROW_OUT;
|
||||||
|
uint32 mTIM_2_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_2_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mTIM_3_BKUP;
|
||||||
|
uint32 mTIM_3_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_3_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_3_LINKING;
|
||||||
|
uint32 mTIM_3_CURRENT;
|
||||||
|
uint32 mTIM_3_TIMER_DONE;
|
||||||
|
uint32 mTIM_3_LAST_CLOCK;
|
||||||
|
uint32 mTIM_3_BORROW_IN;
|
||||||
|
uint32 mTIM_3_BORROW_OUT;
|
||||||
|
uint32 mTIM_3_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_3_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mTIM_4_BKUP;
|
||||||
|
uint32 mTIM_4_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_4_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_4_LINKING;
|
||||||
|
uint32 mTIM_4_CURRENT;
|
||||||
|
uint32 mTIM_4_TIMER_DONE;
|
||||||
|
uint32 mTIM_4_LAST_CLOCK;
|
||||||
|
uint32 mTIM_4_BORROW_IN;
|
||||||
|
uint32 mTIM_4_BORROW_OUT;
|
||||||
|
uint32 mTIM_4_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_4_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mTIM_5_BKUP;
|
||||||
|
uint32 mTIM_5_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_5_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_5_LINKING;
|
||||||
|
uint32 mTIM_5_CURRENT;
|
||||||
|
uint32 mTIM_5_TIMER_DONE;
|
||||||
|
uint32 mTIM_5_LAST_CLOCK;
|
||||||
|
uint32 mTIM_5_BORROW_IN;
|
||||||
|
uint32 mTIM_5_BORROW_OUT;
|
||||||
|
uint32 mTIM_5_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_5_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mTIM_6_BKUP;
|
||||||
|
uint32 mTIM_6_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_6_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_6_LINKING;
|
||||||
|
uint32 mTIM_6_CURRENT;
|
||||||
|
uint32 mTIM_6_TIMER_DONE;
|
||||||
|
uint32 mTIM_6_LAST_CLOCK;
|
||||||
|
uint32 mTIM_6_BORROW_IN;
|
||||||
|
uint32 mTIM_6_BORROW_OUT;
|
||||||
|
uint32 mTIM_6_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_6_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mTIM_7_BKUP;
|
||||||
|
uint32 mTIM_7_ENABLE_RELOAD;
|
||||||
|
uint32 mTIM_7_ENABLE_COUNT;
|
||||||
|
uint32 mTIM_7_LINKING;
|
||||||
|
uint32 mTIM_7_CURRENT;
|
||||||
|
uint32 mTIM_7_TIMER_DONE;
|
||||||
|
uint32 mTIM_7_LAST_CLOCK;
|
||||||
|
uint32 mTIM_7_BORROW_IN;
|
||||||
|
uint32 mTIM_7_BORROW_OUT;
|
||||||
|
uint32 mTIM_7_LAST_LINK_CARRY;
|
||||||
|
uint32 mTIM_7_LAST_COUNT;
|
||||||
|
|
||||||
|
uint32 mAUDIO_BKUP[4];
|
||||||
|
uint32 mAUDIO_ENABLE_RELOAD[4];
|
||||||
|
uint32 mAUDIO_ENABLE_COUNT[4];
|
||||||
|
uint32 mAUDIO_LINKING[4];
|
||||||
|
uint32 mAUDIO_CURRENT[4];
|
||||||
|
uint32 mAUDIO_TIMER_DONE[4];
|
||||||
|
uint32 mAUDIO_LAST_CLOCK[4];
|
||||||
|
uint32 mAUDIO_BORROW_IN[4];
|
||||||
|
uint32 mAUDIO_BORROW_OUT[4];
|
||||||
|
uint32 mAUDIO_LAST_LINK_CARRY[4];
|
||||||
|
uint32 mAUDIO_LAST_COUNT[4];
|
||||||
|
int8 mAUDIO_VOLUME[4];
|
||||||
|
uint32 mAUDIO_INTEGRATE_ENABLE[4];
|
||||||
|
uint32 mAUDIO_WAVESHAPER[4];
|
||||||
|
|
||||||
|
int8 mAUDIO_OUTPUT[4];
|
||||||
|
uint8 mAUDIO_ATTEN[4];
|
||||||
|
uint32 mSTEREO;
|
||||||
|
uint32 mPAN;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Serial related variables
|
||||||
|
//
|
||||||
|
uint32 mUART_RX_IRQ_ENABLE;
|
||||||
|
uint32 mUART_TX_IRQ_ENABLE;
|
||||||
|
|
||||||
|
uint32 mUART_RX_COUNTDOWN;
|
||||||
|
uint32 mUART_TX_COUNTDOWN;
|
||||||
|
|
||||||
|
uint32 mUART_SENDBREAK;
|
||||||
|
uint32 mUART_TX_DATA;
|
||||||
|
uint32 mUART_RX_DATA;
|
||||||
|
uint32 mUART_RX_READY;
|
||||||
|
|
||||||
|
uint32 mUART_PARITY_ENABLE;
|
||||||
|
uint32 mUART_PARITY_EVEN;
|
||||||
|
|
||||||
|
int mUART_CABLE_PRESENT;
|
||||||
|
void (*mpUART_TX_CALLBACK)(int data,uint32 objref);
|
||||||
|
uint32 mUART_TX_CALLBACK_OBJECT;
|
||||||
|
|
||||||
|
int mUART_Rx_input_queue[UART_MAX_RX_QUEUE];
|
||||||
|
unsigned int mUART_Rx_input_ptr;
|
||||||
|
unsigned int mUART_Rx_output_ptr;
|
||||||
|
int mUART_Rx_waiting;
|
||||||
|
int mUART_Rx_framing_error;
|
||||||
|
int mUART_Rx_overun_error;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Screen related
|
||||||
|
//
|
||||||
|
|
||||||
|
uint8 *mpRamPointer;
|
||||||
|
uint32 mLynxLine;
|
||||||
|
uint32 mLynxLineDMACounter;
|
||||||
|
uint32 mLynxAddr;
|
||||||
|
|
||||||
|
void CopyLineSurface();
|
||||||
|
void BlankLineSurface();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r26 | 2009-10-02 13:36:47 +0400 | 2 lines
|
||||||
|
|
||||||
|
[Issue 5] Change <stdint.h> to "stdint.h" to let compiler search for it in local directory.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r25 | 2009-09-17 23:46:49 +0400 | 2 lines
|
||||||
|
|
||||||
|
[Issue 4] Fix incorrect int8_t behaviour if compiled with /J flag.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r24 | 2009-05-13 14:53:48 +0400 | 2 lines
|
||||||
|
|
||||||
|
Forgot about #ifdef __cplusplus guard around 'extern "C"', so inclusion to C files has been broken.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r23 | 2009-05-12 01:27:45 +0400 | 3 lines
|
||||||
|
|
||||||
|
[Issue 2] Always wrap <wcharîàž with external "C" {}.
|
||||||
|
It turns out that not only Visual Studio 6 requires this, but also newer versions when compiling for ARM.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r22 | 2009-05-11 22:22:15 +0400 | 3 lines
|
||||||
|
|
||||||
|
[Issue 3] Visual Studio 6 and Embedded Visual C++ 4 doesn't realize that, e.g. char has the same size as __int8 so we give up on __intX for them.
|
||||||
|
his should close Issue 3 in issue tracker.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r21 | 2008-07-17 09:47:22 +0400 | 4 lines
|
||||||
|
|
||||||
|
Get rid of these compiler warnings when compiling for 32-bit:
|
||||||
|
warning C4311: 'type cast' : pointer truncation from 'void *' to 'uintptr_t'
|
||||||
|
warning C4312: 'type cast' : conversion from 'uintptr_t' to 'const void *' of greater size
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r20 | 2007-10-09 16:54:27 +0400 | 2 lines
|
||||||
|
|
||||||
|
Better C99 conformance: macros for format specifiers should only be included in C++ implementations if __STDC_FORMAT_MACROS is defined before <inttypes.h> is included.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r19 | 2007-07-04 02:14:40 +0400 | 3 lines
|
||||||
|
|
||||||
|
Explicitly cast to appropriate type INT8_MIN, INT16_MIN, INT32_MIN and INT64_MIN constants.
|
||||||
|
Due to their unusual definition in Visual Studio headers (-_Ix_MAX-1) they are propagated to int and thus do not have expected type, causing VS6 strict compiler to claim about type inconsistency.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r18 | 2007-06-26 16:53:23 +0400 | 2 lines
|
||||||
|
|
||||||
|
Better handling of (U)INTx_C macros - now they generate constants of exact width.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r17 | 2007-03-29 20:16:14 +0400 | 2 lines
|
||||||
|
|
||||||
|
Fix typo: Miscrosoft -> Microsoft.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r16 | 2007-02-24 17:32:58 +0300 | 4 lines
|
||||||
|
|
||||||
|
Remove <BaseTsd.h> include, as it is not present in Visual Studio 2005 Epxress Edition and required only for INT_PTR and UINT_PTR types.
|
||||||
|
|
||||||
|
'intptr_t' and 'uintptr_t' types now defined explicitly with #ifdef _WIN64.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r15 | 2007-02-11 20:53:05 +0300 | 2 lines
|
||||||
|
|
||||||
|
More correct fix for compilation under VS6.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r14 | 2007-02-11 20:04:32 +0300 | 2 lines
|
||||||
|
|
||||||
|
Bugfix: fix compiling under VS6, when stdint.h enclosed in 'extern "C" {}'.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r13 | 2006-12-13 16:53:11 +0300 | 2 lines
|
||||||
|
|
||||||
|
Make _inline modifier for imaxdiv default option. Use STATIC_IMAXDIV to make it static.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r12 | 2006-12-13 16:42:24 +0300 | 2 lines
|
||||||
|
|
||||||
|
Error message changed: VC6 supported from now.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r11 | 2006-12-13 16:39:33 +0300 | 2 lines
|
||||||
|
|
||||||
|
All (U)INT* types changed to (unsigned) __int*. This should make stdint.h compatible with VC6.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r10 | 2006-12-13 16:20:57 +0300 | 3 lines
|
||||||
|
|
||||||
|
Added INLINE_IMAXDIV define switch.
|
||||||
|
If INLINE_IMAXDIV is defined imaxdiv() have static modifier. If not - it is _inline.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r9 | 2006-12-13 15:53:52 +0300 | 2 lines
|
||||||
|
|
||||||
|
Error message for non-MSC compiler changed.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r8 | 2006-12-13 12:47:48 +0300 | 2 lines
|
||||||
|
|
||||||
|
Added #ifndef for SIZE_MAX (it is defined in limits.h on MSVSC 8).
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r7 | 2006-12-13 01:08:02 +0300 | 2 lines
|
||||||
|
|
||||||
|
License chaged to BSD-derivative.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r6 | 2006-12-13 00:53:20 +0300 | 2 lines
|
||||||
|
|
||||||
|
Added <wchar.h> include to avoid warnings when it is included after stdint.h.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r5 | 2006-12-12 00:58:05 +0300 | 2 lines
|
||||||
|
|
||||||
|
BUGFIX: Definitions of INTPTR_MIN, INTPTR_MAX and UINTPTR_MAX for WIN32 and WIN64 was mixed up.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r4 | 2006-12-12 00:51:55 +0300 | 2 lines
|
||||||
|
|
||||||
|
Rise #error if _MSC_VER is not defined. I.e. compiler other then Microsoft Visual C++ is used.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r3 | 2006-12-11 22:54:14 +0300 | 2 lines
|
||||||
|
|
||||||
|
Added <limits.h> include to stdint.h.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r2 | 2006-12-11 21:39:27 +0300 | 2 lines
|
||||||
|
|
||||||
|
Initial check in.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
r1 | 2006-12-11 21:30:23 +0300 | 1 line
|
||||||
|
|
||||||
|
Initial directory structure.
|
||||||
|
------------------------------------------------------------------------
|
|
@ -0,0 +1,305 @@
|
||||||
|
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
|
||||||
|
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006 Alexander Chemeris
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. The name of the author may be used to endorse or promote products
|
||||||
|
// derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef _MSC_INTTYPES_H_ // [
|
||||||
|
#define _MSC_INTTYPES_H_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
// 7.8 Format conversion of integer types
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
intmax_t quot;
|
||||||
|
intmax_t rem;
|
||||||
|
} imaxdiv_t;
|
||||||
|
|
||||||
|
// 7.8.1 Macros for format specifiers
|
||||||
|
|
||||||
|
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
|
||||||
|
|
||||||
|
// The fprintf macros for signed integers are:
|
||||||
|
#define PRId8 "d"
|
||||||
|
#define PRIi8 "i"
|
||||||
|
#define PRIdLEAST8 "d"
|
||||||
|
#define PRIiLEAST8 "i"
|
||||||
|
#define PRIdFAST8 "d"
|
||||||
|
#define PRIiFAST8 "i"
|
||||||
|
|
||||||
|
#define PRId16 "hd"
|
||||||
|
#define PRIi16 "hi"
|
||||||
|
#define PRIdLEAST16 "hd"
|
||||||
|
#define PRIiLEAST16 "hi"
|
||||||
|
#define PRIdFAST16 "hd"
|
||||||
|
#define PRIiFAST16 "hi"
|
||||||
|
|
||||||
|
#define PRId32 "I32d"
|
||||||
|
#define PRIi32 "I32i"
|
||||||
|
#define PRIdLEAST32 "I32d"
|
||||||
|
#define PRIiLEAST32 "I32i"
|
||||||
|
#define PRIdFAST32 "I32d"
|
||||||
|
#define PRIiFAST32 "I32i"
|
||||||
|
|
||||||
|
#define PRId64 "I64d"
|
||||||
|
#define PRIi64 "I64i"
|
||||||
|
#define PRIdLEAST64 "I64d"
|
||||||
|
#define PRIiLEAST64 "I64i"
|
||||||
|
#define PRIdFAST64 "I64d"
|
||||||
|
#define PRIiFAST64 "I64i"
|
||||||
|
|
||||||
|
#define PRIdMAX "I64d"
|
||||||
|
#define PRIiMAX "I64i"
|
||||||
|
|
||||||
|
#define PRIdPTR "Id"
|
||||||
|
#define PRIiPTR "Ii"
|
||||||
|
|
||||||
|
// The fprintf macros for unsigned integers are:
|
||||||
|
#define PRIo8 "o"
|
||||||
|
#define PRIu8 "u"
|
||||||
|
#define PRIx8 "x"
|
||||||
|
#define PRIX8 "X"
|
||||||
|
#define PRIoLEAST8 "o"
|
||||||
|
#define PRIuLEAST8 "u"
|
||||||
|
#define PRIxLEAST8 "x"
|
||||||
|
#define PRIXLEAST8 "X"
|
||||||
|
#define PRIoFAST8 "o"
|
||||||
|
#define PRIuFAST8 "u"
|
||||||
|
#define PRIxFAST8 "x"
|
||||||
|
#define PRIXFAST8 "X"
|
||||||
|
|
||||||
|
#define PRIo16 "ho"
|
||||||
|
#define PRIu16 "hu"
|
||||||
|
#define PRIx16 "hx"
|
||||||
|
#define PRIX16 "hX"
|
||||||
|
#define PRIoLEAST16 "ho"
|
||||||
|
#define PRIuLEAST16 "hu"
|
||||||
|
#define PRIxLEAST16 "hx"
|
||||||
|
#define PRIXLEAST16 "hX"
|
||||||
|
#define PRIoFAST16 "ho"
|
||||||
|
#define PRIuFAST16 "hu"
|
||||||
|
#define PRIxFAST16 "hx"
|
||||||
|
#define PRIXFAST16 "hX"
|
||||||
|
|
||||||
|
#define PRIo32 "I32o"
|
||||||
|
#define PRIu32 "I32u"
|
||||||
|
#define PRIx32 "I32x"
|
||||||
|
#define PRIX32 "I32X"
|
||||||
|
#define PRIoLEAST32 "I32o"
|
||||||
|
#define PRIuLEAST32 "I32u"
|
||||||
|
#define PRIxLEAST32 "I32x"
|
||||||
|
#define PRIXLEAST32 "I32X"
|
||||||
|
#define PRIoFAST32 "I32o"
|
||||||
|
#define PRIuFAST32 "I32u"
|
||||||
|
#define PRIxFAST32 "I32x"
|
||||||
|
#define PRIXFAST32 "I32X"
|
||||||
|
|
||||||
|
#define PRIo64 "I64o"
|
||||||
|
#define PRIu64 "I64u"
|
||||||
|
#define PRIx64 "I64x"
|
||||||
|
#define PRIX64 "I64X"
|
||||||
|
#define PRIoLEAST64 "I64o"
|
||||||
|
#define PRIuLEAST64 "I64u"
|
||||||
|
#define PRIxLEAST64 "I64x"
|
||||||
|
#define PRIXLEAST64 "I64X"
|
||||||
|
#define PRIoFAST64 "I64o"
|
||||||
|
#define PRIuFAST64 "I64u"
|
||||||
|
#define PRIxFAST64 "I64x"
|
||||||
|
#define PRIXFAST64 "I64X"
|
||||||
|
|
||||||
|
#define PRIoMAX "I64o"
|
||||||
|
#define PRIuMAX "I64u"
|
||||||
|
#define PRIxMAX "I64x"
|
||||||
|
#define PRIXMAX "I64X"
|
||||||
|
|
||||||
|
#define PRIoPTR "Io"
|
||||||
|
#define PRIuPTR "Iu"
|
||||||
|
#define PRIxPTR "Ix"
|
||||||
|
#define PRIXPTR "IX"
|
||||||
|
|
||||||
|
// The fscanf macros for signed integers are:
|
||||||
|
#define SCNd8 "d"
|
||||||
|
#define SCNi8 "i"
|
||||||
|
#define SCNdLEAST8 "d"
|
||||||
|
#define SCNiLEAST8 "i"
|
||||||
|
#define SCNdFAST8 "d"
|
||||||
|
#define SCNiFAST8 "i"
|
||||||
|
|
||||||
|
#define SCNd16 "hd"
|
||||||
|
#define SCNi16 "hi"
|
||||||
|
#define SCNdLEAST16 "hd"
|
||||||
|
#define SCNiLEAST16 "hi"
|
||||||
|
#define SCNdFAST16 "hd"
|
||||||
|
#define SCNiFAST16 "hi"
|
||||||
|
|
||||||
|
#define SCNd32 "ld"
|
||||||
|
#define SCNi32 "li"
|
||||||
|
#define SCNdLEAST32 "ld"
|
||||||
|
#define SCNiLEAST32 "li"
|
||||||
|
#define SCNdFAST32 "ld"
|
||||||
|
#define SCNiFAST32 "li"
|
||||||
|
|
||||||
|
#define SCNd64 "I64d"
|
||||||
|
#define SCNi64 "I64i"
|
||||||
|
#define SCNdLEAST64 "I64d"
|
||||||
|
#define SCNiLEAST64 "I64i"
|
||||||
|
#define SCNdFAST64 "I64d"
|
||||||
|
#define SCNiFAST64 "I64i"
|
||||||
|
|
||||||
|
#define SCNdMAX "I64d"
|
||||||
|
#define SCNiMAX "I64i"
|
||||||
|
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define SCNdPTR "I64d"
|
||||||
|
# define SCNiPTR "I64i"
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define SCNdPTR "ld"
|
||||||
|
# define SCNiPTR "li"
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
// The fscanf macros for unsigned integers are:
|
||||||
|
#define SCNo8 "o"
|
||||||
|
#define SCNu8 "u"
|
||||||
|
#define SCNx8 "x"
|
||||||
|
#define SCNX8 "X"
|
||||||
|
#define SCNoLEAST8 "o"
|
||||||
|
#define SCNuLEAST8 "u"
|
||||||
|
#define SCNxLEAST8 "x"
|
||||||
|
#define SCNXLEAST8 "X"
|
||||||
|
#define SCNoFAST8 "o"
|
||||||
|
#define SCNuFAST8 "u"
|
||||||
|
#define SCNxFAST8 "x"
|
||||||
|
#define SCNXFAST8 "X"
|
||||||
|
|
||||||
|
#define SCNo16 "ho"
|
||||||
|
#define SCNu16 "hu"
|
||||||
|
#define SCNx16 "hx"
|
||||||
|
#define SCNX16 "hX"
|
||||||
|
#define SCNoLEAST16 "ho"
|
||||||
|
#define SCNuLEAST16 "hu"
|
||||||
|
#define SCNxLEAST16 "hx"
|
||||||
|
#define SCNXLEAST16 "hX"
|
||||||
|
#define SCNoFAST16 "ho"
|
||||||
|
#define SCNuFAST16 "hu"
|
||||||
|
#define SCNxFAST16 "hx"
|
||||||
|
#define SCNXFAST16 "hX"
|
||||||
|
|
||||||
|
#define SCNo32 "lo"
|
||||||
|
#define SCNu32 "lu"
|
||||||
|
#define SCNx32 "lx"
|
||||||
|
#define SCNX32 "lX"
|
||||||
|
#define SCNoLEAST32 "lo"
|
||||||
|
#define SCNuLEAST32 "lu"
|
||||||
|
#define SCNxLEAST32 "lx"
|
||||||
|
#define SCNXLEAST32 "lX"
|
||||||
|
#define SCNoFAST32 "lo"
|
||||||
|
#define SCNuFAST32 "lu"
|
||||||
|
#define SCNxFAST32 "lx"
|
||||||
|
#define SCNXFAST32 "lX"
|
||||||
|
|
||||||
|
#define SCNo64 "I64o"
|
||||||
|
#define SCNu64 "I64u"
|
||||||
|
#define SCNx64 "I64x"
|
||||||
|
#define SCNX64 "I64X"
|
||||||
|
#define SCNoLEAST64 "I64o"
|
||||||
|
#define SCNuLEAST64 "I64u"
|
||||||
|
#define SCNxLEAST64 "I64x"
|
||||||
|
#define SCNXLEAST64 "I64X"
|
||||||
|
#define SCNoFAST64 "I64o"
|
||||||
|
#define SCNuFAST64 "I64u"
|
||||||
|
#define SCNxFAST64 "I64x"
|
||||||
|
#define SCNXFAST64 "I64X"
|
||||||
|
|
||||||
|
#define SCNoMAX "I64o"
|
||||||
|
#define SCNuMAX "I64u"
|
||||||
|
#define SCNxMAX "I64x"
|
||||||
|
#define SCNXMAX "I64X"
|
||||||
|
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define SCNoPTR "I64o"
|
||||||
|
# define SCNuPTR "I64u"
|
||||||
|
# define SCNxPTR "I64x"
|
||||||
|
# define SCNXPTR "I64X"
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define SCNoPTR "lo"
|
||||||
|
# define SCNuPTR "lu"
|
||||||
|
# define SCNxPTR "lx"
|
||||||
|
# define SCNXPTR "lX"
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
#endif // __STDC_FORMAT_MACROS ]
|
||||||
|
|
||||||
|
// 7.8.2 Functions for greatest-width integer types
|
||||||
|
|
||||||
|
// 7.8.2.1 The imaxabs function
|
||||||
|
#define imaxabs _abs64
|
||||||
|
|
||||||
|
// 7.8.2.2 The imaxdiv function
|
||||||
|
|
||||||
|
// This is modified version of div() function from Microsoft's div.c found
|
||||||
|
// in %MSVC.NET%\crt\src\div.c
|
||||||
|
#ifdef STATIC_IMAXDIV // [
|
||||||
|
static
|
||||||
|
#else // STATIC_IMAXDIV ][
|
||||||
|
_inline
|
||||||
|
#endif // STATIC_IMAXDIV ]
|
||||||
|
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||||
|
{
|
||||||
|
imaxdiv_t result;
|
||||||
|
|
||||||
|
result.quot = numer / denom;
|
||||||
|
result.rem = numer % denom;
|
||||||
|
|
||||||
|
if (numer < 0 && result.rem > 0) {
|
||||||
|
// did division wrong; must fix up
|
||||||
|
++result.quot;
|
||||||
|
result.rem -= denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7.8.2.3 The strtoimax and strtoumax functions
|
||||||
|
#define strtoimax _strtoi64
|
||||||
|
#define strtoumax _strtoui64
|
||||||
|
|
||||||
|
// 7.8.2.4 The wcstoimax and wcstoumax functions
|
||||||
|
#define wcstoimax _wcstoi64
|
||||||
|
#define wcstoumax _wcstoui64
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _MSC_INTTYPES_H_ ]
|
|
@ -0,0 +1,247 @@
|
||||||
|
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||||
|
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. The name of the author may be used to endorse or promote products
|
||||||
|
// derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef _MSC_STDINT_H_ // [
|
||||||
|
#define _MSC_STDINT_H_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||||
|
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||||
|
// or compiler give many errors like this:
|
||||||
|
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
# include <wchar.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||||
|
#ifndef _W64
|
||||||
|
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||||
|
# define _W64 __w64
|
||||||
|
# else
|
||||||
|
# define _W64
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.1 Integer types
|
||||||
|
|
||||||
|
// 7.18.1.1 Exact-width integer types
|
||||||
|
|
||||||
|
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||||
|
// realize that, e.g. char has the same size as __int8
|
||||||
|
// so we give up on __intX for them.
|
||||||
|
#if (_MSC_VER < 1300)
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef signed short int16_t;
|
||||||
|
typedef signed int int32_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
#else
|
||||||
|
typedef signed __int8 int8_t;
|
||||||
|
typedef signed __int16 int16_t;
|
||||||
|
typedef signed __int32 int32_t;
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
typedef unsigned __int16 uint16_t;
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
#endif
|
||||||
|
typedef signed __int64 int64_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.1.2 Minimum-width integer types
|
||||||
|
typedef int8_t int_least8_t;
|
||||||
|
typedef int16_t int_least16_t;
|
||||||
|
typedef int32_t int_least32_t;
|
||||||
|
typedef int64_t int_least64_t;
|
||||||
|
typedef uint8_t uint_least8_t;
|
||||||
|
typedef uint16_t uint_least16_t;
|
||||||
|
typedef uint32_t uint_least32_t;
|
||||||
|
typedef uint64_t uint_least64_t;
|
||||||
|
|
||||||
|
// 7.18.1.3 Fastest minimum-width integer types
|
||||||
|
typedef int8_t int_fast8_t;
|
||||||
|
typedef int16_t int_fast16_t;
|
||||||
|
typedef int32_t int_fast32_t;
|
||||||
|
typedef int64_t int_fast64_t;
|
||||||
|
typedef uint8_t uint_fast8_t;
|
||||||
|
typedef uint16_t uint_fast16_t;
|
||||||
|
typedef uint32_t uint_fast32_t;
|
||||||
|
typedef uint64_t uint_fast64_t;
|
||||||
|
|
||||||
|
// 7.18.1.4 Integer types capable of holding object pointers
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
typedef signed __int64 intptr_t;
|
||||||
|
typedef unsigned __int64 uintptr_t;
|
||||||
|
#else // _WIN64 ][
|
||||||
|
typedef _W64 signed int intptr_t;
|
||||||
|
typedef _W64 unsigned int uintptr_t;
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
// 7.18.1.5 Greatest-width integer types
|
||||||
|
typedef int64_t intmax_t;
|
||||||
|
typedef uint64_t uintmax_t;
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.2 Limits of specified-width integer types
|
||||||
|
|
||||||
|
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||||
|
|
||||||
|
// 7.18.2.1 Limits of exact-width integer types
|
||||||
|
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||||
|
#define INT8_MAX _I8_MAX
|
||||||
|
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||||
|
#define INT16_MAX _I16_MAX
|
||||||
|
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||||
|
#define INT32_MAX _I32_MAX
|
||||||
|
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||||
|
#define INT64_MAX _I64_MAX
|
||||||
|
#define UINT8_MAX _UI8_MAX
|
||||||
|
#define UINT16_MAX _UI16_MAX
|
||||||
|
#define UINT32_MAX _UI32_MAX
|
||||||
|
#define UINT64_MAX _UI64_MAX
|
||||||
|
|
||||||
|
// 7.18.2.2 Limits of minimum-width integer types
|
||||||
|
#define INT_LEAST8_MIN INT8_MIN
|
||||||
|
#define INT_LEAST8_MAX INT8_MAX
|
||||||
|
#define INT_LEAST16_MIN INT16_MIN
|
||||||
|
#define INT_LEAST16_MAX INT16_MAX
|
||||||
|
#define INT_LEAST32_MIN INT32_MIN
|
||||||
|
#define INT_LEAST32_MAX INT32_MAX
|
||||||
|
#define INT_LEAST64_MIN INT64_MIN
|
||||||
|
#define INT_LEAST64_MAX INT64_MAX
|
||||||
|
#define UINT_LEAST8_MAX UINT8_MAX
|
||||||
|
#define UINT_LEAST16_MAX UINT16_MAX
|
||||||
|
#define UINT_LEAST32_MAX UINT32_MAX
|
||||||
|
#define UINT_LEAST64_MAX UINT64_MAX
|
||||||
|
|
||||||
|
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||||
|
#define INT_FAST8_MIN INT8_MIN
|
||||||
|
#define INT_FAST8_MAX INT8_MAX
|
||||||
|
#define INT_FAST16_MIN INT16_MIN
|
||||||
|
#define INT_FAST16_MAX INT16_MAX
|
||||||
|
#define INT_FAST32_MIN INT32_MIN
|
||||||
|
#define INT_FAST32_MAX INT32_MAX
|
||||||
|
#define INT_FAST64_MIN INT64_MIN
|
||||||
|
#define INT_FAST64_MAX INT64_MAX
|
||||||
|
#define UINT_FAST8_MAX UINT8_MAX
|
||||||
|
#define UINT_FAST16_MAX UINT16_MAX
|
||||||
|
#define UINT_FAST32_MAX UINT32_MAX
|
||||||
|
#define UINT_FAST64_MAX UINT64_MAX
|
||||||
|
|
||||||
|
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define INTPTR_MIN INT64_MIN
|
||||||
|
# define INTPTR_MAX INT64_MAX
|
||||||
|
# define UINTPTR_MAX UINT64_MAX
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define INTPTR_MIN INT32_MIN
|
||||||
|
# define INTPTR_MAX INT32_MAX
|
||||||
|
# define UINTPTR_MAX UINT32_MAX
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
// 7.18.2.5 Limits of greatest-width integer types
|
||||||
|
#define INTMAX_MIN INT64_MIN
|
||||||
|
#define INTMAX_MAX INT64_MAX
|
||||||
|
#define UINTMAX_MAX UINT64_MAX
|
||||||
|
|
||||||
|
// 7.18.3 Limits of other integer types
|
||||||
|
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define PTRDIFF_MIN _I64_MIN
|
||||||
|
# define PTRDIFF_MAX _I64_MAX
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define PTRDIFF_MIN _I32_MIN
|
||||||
|
# define PTRDIFF_MAX _I32_MAX
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
#define SIG_ATOMIC_MIN INT_MIN
|
||||||
|
#define SIG_ATOMIC_MAX INT_MAX
|
||||||
|
|
||||||
|
#ifndef SIZE_MAX // [
|
||||||
|
# ifdef _WIN64 // [
|
||||||
|
# define SIZE_MAX _UI64_MAX
|
||||||
|
# else // _WIN64 ][
|
||||||
|
# define SIZE_MAX _UI32_MAX
|
||||||
|
# endif // _WIN64 ]
|
||||||
|
#endif // SIZE_MAX ]
|
||||||
|
|
||||||
|
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||||
|
#ifndef WCHAR_MIN // [
|
||||||
|
# define WCHAR_MIN 0
|
||||||
|
#endif // WCHAR_MIN ]
|
||||||
|
#ifndef WCHAR_MAX // [
|
||||||
|
# define WCHAR_MAX _UI16_MAX
|
||||||
|
#endif // WCHAR_MAX ]
|
||||||
|
|
||||||
|
#define WINT_MIN 0
|
||||||
|
#define WINT_MAX _UI16_MAX
|
||||||
|
|
||||||
|
#endif // __STDC_LIMIT_MACROS ]
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.4 Limits of other integer types
|
||||||
|
|
||||||
|
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||||
|
|
||||||
|
// 7.18.4.1 Macros for minimum-width integer constants
|
||||||
|
|
||||||
|
#define INT8_C(val) val##i8
|
||||||
|
#define INT16_C(val) val##i16
|
||||||
|
#define INT32_C(val) val##i32
|
||||||
|
#define INT64_C(val) val##i64
|
||||||
|
|
||||||
|
#define UINT8_C(val) val##ui8
|
||||||
|
#define UINT16_C(val) val##ui16
|
||||||
|
#define UINT32_C(val) val##ui32
|
||||||
|
#define UINT64_C(val) val##ui64
|
||||||
|
|
||||||
|
// 7.18.4.2 Macros for greatest-width integer constants
|
||||||
|
#define INTMAX_C INT64_C
|
||||||
|
#define UINTMAX_C UINT64_C
|
||||||
|
|
||||||
|
#endif // __STDC_CONSTANT_MACROS ]
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _MSC_STDINT_H_ ]
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAM emulation class //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This class emulates the system RAM (64KB), the interface is pretty //
|
||||||
|
// simple: constructor, reset, peek, poke. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
#define RAM_CPP
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "ram.h"
|
||||||
|
|
||||||
|
CRam::CRam()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
CRam::~CRam()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRam::Reset(void)
|
||||||
|
{
|
||||||
|
//MDFNMP_AddRAM(65536, 0x0000, mRamData);
|
||||||
|
std::memset(mRamData, DEFAULT_RAM_CONTENTS, RAM_SIZE);
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAM object header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition for the RAM class //
|
||||||
|
// that emulates the Handy system RAM (64K) //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef RAM_H
|
||||||
|
#define RAM_H
|
||||||
|
|
||||||
|
#define RAM_SIZE 65536
|
||||||
|
#define RAM_ADDR_MASK 0xffff
|
||||||
|
#define DEFAULT_RAM_CONTENTS 0xff
|
||||||
|
|
||||||
|
struct HOME_HEADER
|
||||||
|
{
|
||||||
|
uint16 jump;
|
||||||
|
uint16 load_address;
|
||||||
|
uint16 size;
|
||||||
|
uint8 magic[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
class CRam : public CLynxBase
|
||||||
|
{
|
||||||
|
|
||||||
|
// Function members
|
||||||
|
|
||||||
|
public:
|
||||||
|
CRam() MDFN_COLD;
|
||||||
|
~CRam() MDFN_COLD;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void Reset(void) MDFN_COLD;
|
||||||
|
|
||||||
|
void Poke(uint32 addr, uint8 data){ mRamData[addr]=data;};
|
||||||
|
uint8 Peek(uint32 addr){ return(mRamData[addr]);};
|
||||||
|
uint32 ReadCycle(void) {return 5;};
|
||||||
|
uint32 WriteCycle(void) {return 5;};
|
||||||
|
uint32 ObjectSize(void) {return RAM_SIZE;};
|
||||||
|
uint8* GetRamPointer(void) { return mRamData; };
|
||||||
|
|
||||||
|
// Data members
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 mRamData[RAM_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ROM emulation class //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This class emulates the system ROM (512B), the interface is pretty //
|
||||||
|
// simple: constructor, reset, peek, poke. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "rom.h"
|
||||||
|
|
||||||
|
CRom::CRom(const uint8 *romfile, uint32 length)
|
||||||
|
{
|
||||||
|
mWriteEnable=FALSE;
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
std::memset(mRomData, DEFAULT_ROM_CONTENTS, ROM_SIZE);
|
||||||
|
|
||||||
|
std::memcpy(mRomData, romfile, std::min<uint32>(ROM_SIZE, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRom::Reset(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ROM object header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition and inline code for //
|
||||||
|
// the class the emulates the internal 512 byte ROM embedded in Mikey //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef ROM_H
|
||||||
|
#define ROM_H
|
||||||
|
|
||||||
|
#define ROM_SIZE 0x200
|
||||||
|
#define ROM_ADDR_MASK 0x01ff
|
||||||
|
#define DEFAULT_ROM_CONTENTS 0x88
|
||||||
|
|
||||||
|
#define BROM_START 0xfe00
|
||||||
|
#define BROM_SIZE 0x200
|
||||||
|
#define VECTOR_START 0xfffa
|
||||||
|
#define VECTOR_SIZE 0x6
|
||||||
|
|
||||||
|
class CRom : public CLynxBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CRom(const uint8 *, uint32) MDFN_COLD;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Reset(void) MDFN_COLD;
|
||||||
|
void Poke(uint32 addr,uint8 data) { if(mWriteEnable) mRomData[addr&ROM_ADDR_MASK]=data;};
|
||||||
|
uint8 Peek(uint32 addr) { return(mRomData[addr&ROM_ADDR_MASK]);};
|
||||||
|
uint32 ReadCycle(void) {return 5;};
|
||||||
|
uint32 WriteCycle(void) {return 5;};
|
||||||
|
uint32 ObjectSize(void) {return ROM_SIZE;};
|
||||||
|
|
||||||
|
// Data members
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool mWriteEnable;
|
||||||
|
private:
|
||||||
|
uint8 mRomData[ROM_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,457 @@
|
||||||
|
// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
|
||||||
|
|
||||||
|
#include "Blip_Buffer.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
||||||
|
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||||
|
General Public License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
#ifdef BLARGG_ENABLE_OPTIMIZER
|
||||||
|
#include BLARGG_ENABLE_OPTIMIZER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
|
||||||
|
|
||||||
|
Blip_Buffer::Blip_Buffer()
|
||||||
|
{
|
||||||
|
factor_ = (blip_u64)ULLONG_MAX;
|
||||||
|
offset_ = 0;
|
||||||
|
buffer_ = 0;
|
||||||
|
buffer_size_ = 0;
|
||||||
|
sample_rate_ = 0;
|
||||||
|
reader_accum_ = 0;
|
||||||
|
bass_shift_ = 0;
|
||||||
|
clock_rate_ = 0;
|
||||||
|
bass_freq_ = 16;
|
||||||
|
length_ = 0;
|
||||||
|
|
||||||
|
// assumptions code makes about implementation-defined features
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// right shift of negative value preserves sign
|
||||||
|
buf_t_ i = -0x7FFFFFFE;
|
||||||
|
assert( (i >> 1) == -0x3FFFFFFF );
|
||||||
|
|
||||||
|
// casting to short truncates to 16 bits and sign-extends
|
||||||
|
i = 0x18000;
|
||||||
|
assert( (short) i == -0x8000 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Blip_Buffer::~Blip_Buffer()
|
||||||
|
{
|
||||||
|
if ( buffer_size_ != silent_buf_size )
|
||||||
|
free( buffer_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
Silent_Blip_Buffer::Silent_Blip_Buffer()
|
||||||
|
{
|
||||||
|
factor_ = 0;
|
||||||
|
buffer_ = buf;
|
||||||
|
buffer_size_ = silent_buf_size;
|
||||||
|
memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Buffer::clear( int entire_buffer )
|
||||||
|
{
|
||||||
|
offset_ = 0;
|
||||||
|
reader_accum_ = 0;
|
||||||
|
modified_ = 0;
|
||||||
|
if ( buffer_ )
|
||||||
|
{
|
||||||
|
long count = (entire_buffer ? buffer_size_ : samples_avail());
|
||||||
|
memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
|
||||||
|
{
|
||||||
|
if ( buffer_size_ == silent_buf_size )
|
||||||
|
{
|
||||||
|
assert( 0 );
|
||||||
|
return "Internal (tried to resize Silent_Blip_Buffer)";
|
||||||
|
}
|
||||||
|
|
||||||
|
// start with maximum length that resampled time can represent
|
||||||
|
blip_s64 new_size = (ULLONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
|
||||||
|
|
||||||
|
// simple safety check, since code elsewhere may not be safe for sizes approaching (2 ^ 31).
|
||||||
|
if(new_size > ((1LL << 30) - 1))
|
||||||
|
new_size = (1LL << 30) - 1;
|
||||||
|
|
||||||
|
if ( msec != blip_max_length )
|
||||||
|
{
|
||||||
|
blip_s64 s = ((blip_s64)new_rate * (msec + 1) + 999) / 1000;
|
||||||
|
if ( s < new_size )
|
||||||
|
new_size = s;
|
||||||
|
else
|
||||||
|
assert( 0 ); // fails if requested buffer length exceeds limit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( buffer_size_ != new_size )
|
||||||
|
{
|
||||||
|
void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
|
||||||
|
if ( !p )
|
||||||
|
return "Out of memory";
|
||||||
|
|
||||||
|
//if(new_size > buffer_size_)
|
||||||
|
// memset(buffer_ + buffer_size_, 0, (new_size + blip_buffer_extra_) * sizeof *buffer_
|
||||||
|
|
||||||
|
buffer_ = (buf_t_*) p;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_size_ = new_size;
|
||||||
|
assert( buffer_size_ != silent_buf_size );
|
||||||
|
|
||||||
|
// update things based on the sample rate
|
||||||
|
sample_rate_ = new_rate;
|
||||||
|
length_ = new_size * 1000 / new_rate - 1;
|
||||||
|
if ( msec )
|
||||||
|
assert( length_ == msec ); // ensure length is same as that passed in
|
||||||
|
if ( clock_rate_ )
|
||||||
|
clock_rate( clock_rate_ );
|
||||||
|
bass_freq( bass_freq_ );
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
return 0; // success
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
|
||||||
|
{
|
||||||
|
double ratio = (double) sample_rate_ / rate;
|
||||||
|
blip_s64 factor = (blip_s64) floor( ratio * (1LL << BLIP_BUFFER_ACCURACY) + 0.5 );
|
||||||
|
assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
|
||||||
|
return (blip_resampled_time_t) factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Buffer::bass_freq( int freq )
|
||||||
|
{
|
||||||
|
bass_freq_ = freq;
|
||||||
|
int shift = 31;
|
||||||
|
if ( freq > 0 )
|
||||||
|
{
|
||||||
|
shift = 13;
|
||||||
|
long f = (freq << 16) / sample_rate_;
|
||||||
|
while ( (f >>= 1) && --shift ) { }
|
||||||
|
}
|
||||||
|
bass_shift_ = shift;
|
||||||
|
//printf("%d\n", bass_shift_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Buffer::end_frame( blip_time_t t )
|
||||||
|
{
|
||||||
|
offset_ += t * factor_;
|
||||||
|
assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Buffer::remove_silence( long count )
|
||||||
|
{
|
||||||
|
assert( count <= samples_avail() ); // tried to remove more samples than available
|
||||||
|
offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
|
||||||
|
}
|
||||||
|
|
||||||
|
long Blip_Buffer::count_samples( blip_time_t t ) const
|
||||||
|
{
|
||||||
|
unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
|
||||||
|
unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
|
||||||
|
return (long) (last_sample - first_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_time_t Blip_Buffer::count_clocks( long count ) const
|
||||||
|
{
|
||||||
|
if ( !factor_ )
|
||||||
|
{
|
||||||
|
assert( 0 ); // sample rate and clock rates must be set first
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( count > buffer_size_ )
|
||||||
|
count = buffer_size_;
|
||||||
|
blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
|
||||||
|
return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Buffer::remove_samples( long count )
|
||||||
|
{
|
||||||
|
if ( count )
|
||||||
|
{
|
||||||
|
remove_silence( count );
|
||||||
|
|
||||||
|
// copy remaining samples to beginning and clear old samples
|
||||||
|
long remain = samples_avail() + blip_buffer_extra_;
|
||||||
|
memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
|
||||||
|
memset( buffer_ + remain, 0, count * sizeof *buffer_ );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blip_Synth_
|
||||||
|
|
||||||
|
Blip_Synth_Fast_::Blip_Synth_Fast_()
|
||||||
|
{
|
||||||
|
buf = 0;
|
||||||
|
last_amp = 0;
|
||||||
|
delta_factor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Synth_Fast_::volume_unit( double new_unit )
|
||||||
|
{
|
||||||
|
delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !BLIP_BUFFER_FAST
|
||||||
|
|
||||||
|
Blip_Synth_::Blip_Synth_( short* p, int w ) :
|
||||||
|
impulses( p ),
|
||||||
|
width( w )
|
||||||
|
{
|
||||||
|
volume_unit_ = 0.0;
|
||||||
|
kernel_unit = 0;
|
||||||
|
buf = 0;
|
||||||
|
last_amp = 0;
|
||||||
|
delta_factor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef PI
|
||||||
|
#define PI 3.1415926535897932384626433832795029
|
||||||
|
|
||||||
|
static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
|
||||||
|
{
|
||||||
|
if ( cutoff >= 0.999 )
|
||||||
|
cutoff = 0.999;
|
||||||
|
|
||||||
|
if ( treble < -300.0 )
|
||||||
|
treble = -300.0;
|
||||||
|
if ( treble > 5.0 )
|
||||||
|
treble = 5.0;
|
||||||
|
|
||||||
|
double const maxh = 4096.0;
|
||||||
|
double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
|
||||||
|
double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
|
||||||
|
double const to_angle = PI / 2 / maxh / oversample;
|
||||||
|
for ( int i = 0; i < count; i++ )
|
||||||
|
{
|
||||||
|
double angle = ((i - count) * 2 + 1) * to_angle;
|
||||||
|
double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
|
||||||
|
double cos_nc_angle = cos( maxh * cutoff * angle );
|
||||||
|
double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
|
||||||
|
double cos_angle = cos( angle );
|
||||||
|
|
||||||
|
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
|
||||||
|
double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
|
||||||
|
double b = 2.0 - cos_angle - cos_angle;
|
||||||
|
double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
|
||||||
|
|
||||||
|
out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_eq_t::generate( float* out, int count ) const
|
||||||
|
{
|
||||||
|
// lower cutoff freq for narrow kernels with their wider transition band
|
||||||
|
// (8 points->1.49, 16 points->1.15)
|
||||||
|
double oversample = blip_res * 2.25 / count + 0.85;
|
||||||
|
double half_rate = sample_rate * 0.5;
|
||||||
|
if ( cutoff_freq )
|
||||||
|
oversample = half_rate / cutoff_freq;
|
||||||
|
double cutoff = rolloff_freq * oversample / half_rate;
|
||||||
|
|
||||||
|
gen_sinc( out, count, blip_res * oversample, treble, cutoff );
|
||||||
|
|
||||||
|
// apply (half of) hamming window
|
||||||
|
double to_fraction = PI / (count - 1);
|
||||||
|
for ( int i = count; i--; )
|
||||||
|
out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Synth_::adjust_impulse()
|
||||||
|
{
|
||||||
|
// sum pairs for each phase and add error correction to end of first half
|
||||||
|
int const size = impulses_size();
|
||||||
|
for ( int p = blip_res; p-- >= blip_res / 2; )
|
||||||
|
{
|
||||||
|
int p2 = blip_res - 2 - p;
|
||||||
|
long error = kernel_unit;
|
||||||
|
for ( int i = 1; i < size; i += blip_res )
|
||||||
|
{
|
||||||
|
error -= impulses [i + p ];
|
||||||
|
error -= impulses [i + p2];
|
||||||
|
}
|
||||||
|
if ( p == p2 )
|
||||||
|
error /= 2; // phase = 0.5 impulse uses same half for both sides
|
||||||
|
impulses [size - blip_res + p] += (short) error;
|
||||||
|
//printf( "error: %ld\n", error );
|
||||||
|
}
|
||||||
|
|
||||||
|
//for ( int i = blip_res; i--; printf( "\n" ) )
|
||||||
|
// for ( int j = 0; j < width / 2; j++ )
|
||||||
|
// printf( "%5ld,", impulses [j * blip_res + i + 1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Synth_::treble_eq( blip_eq_t const& eq )
|
||||||
|
{
|
||||||
|
float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
|
||||||
|
|
||||||
|
int const half_size = blip_res / 2 * (width - 1);
|
||||||
|
eq.generate( &fimpulse [blip_res], half_size );
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// need mirror slightly past center for calculation
|
||||||
|
for ( i = blip_res; i--; )
|
||||||
|
fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
|
||||||
|
|
||||||
|
// starts at 0
|
||||||
|
for ( i = 0; i < blip_res; i++ )
|
||||||
|
fimpulse [i] = 0.0f;
|
||||||
|
|
||||||
|
// find rescale factor
|
||||||
|
double total = 0.0;
|
||||||
|
for ( i = 0; i < half_size; i++ )
|
||||||
|
total += fimpulse [blip_res + i];
|
||||||
|
|
||||||
|
//double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
|
||||||
|
//double const base_unit = 37888.0; // allows treble to +5 dB
|
||||||
|
double const base_unit = 32768.0; // necessary for blip_unscaled to work
|
||||||
|
double rescale = base_unit / 2 / total;
|
||||||
|
kernel_unit = (long) base_unit;
|
||||||
|
|
||||||
|
// integrate, first difference, rescale, convert to int
|
||||||
|
double sum = 0.0;
|
||||||
|
double next = 0.0;
|
||||||
|
int const impulses_size_local = this->impulses_size();
|
||||||
|
for ( i = 0; i < impulses_size_local; i++ )
|
||||||
|
{
|
||||||
|
impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
|
||||||
|
sum += fimpulse [i];
|
||||||
|
next += fimpulse [i + blip_res];
|
||||||
|
}
|
||||||
|
adjust_impulse();
|
||||||
|
|
||||||
|
// volume might require rescaling
|
||||||
|
double vol = volume_unit_;
|
||||||
|
if ( vol )
|
||||||
|
{
|
||||||
|
volume_unit_ = 0.0;
|
||||||
|
volume_unit( vol );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Synth_::volume_unit( double new_unit )
|
||||||
|
{
|
||||||
|
if ( new_unit != volume_unit_ )
|
||||||
|
{
|
||||||
|
// use default eq if it hasn't been set yet
|
||||||
|
if ( !kernel_unit )
|
||||||
|
treble_eq( -8.0 );
|
||||||
|
|
||||||
|
volume_unit_ = new_unit;
|
||||||
|
double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
|
||||||
|
|
||||||
|
if ( factor > 0.0 )
|
||||||
|
{
|
||||||
|
int shift = 0;
|
||||||
|
|
||||||
|
// if unit is really small, might need to attenuate kernel
|
||||||
|
while ( factor < 2.0 )
|
||||||
|
{
|
||||||
|
shift++;
|
||||||
|
factor *= 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( shift )
|
||||||
|
{
|
||||||
|
kernel_unit >>= shift;
|
||||||
|
assert( kernel_unit > 0 ); // fails if volume unit is too low
|
||||||
|
|
||||||
|
// keep values positive to avoid round-towards-zero of sign-preserving
|
||||||
|
// right shift for negative values
|
||||||
|
long offset = 0x8000 + (1 << (shift - 1));
|
||||||
|
long offset2 = 0x8000 >> shift;
|
||||||
|
for ( int i = impulses_size(); i--; )
|
||||||
|
impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
|
||||||
|
adjust_impulse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delta_factor = (int) floor( factor + 0.5 );
|
||||||
|
//printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
|
||||||
|
{
|
||||||
|
long count = samples_avail();
|
||||||
|
if ( count > max_samples )
|
||||||
|
count = max_samples;
|
||||||
|
|
||||||
|
if ( count )
|
||||||
|
{
|
||||||
|
int const bass = BLIP_READER_BASS( *this );
|
||||||
|
BLIP_READER_BEGIN( reader, *this );
|
||||||
|
|
||||||
|
if ( !stereo )
|
||||||
|
{
|
||||||
|
for ( blip_long n = count; n; --n )
|
||||||
|
{
|
||||||
|
blip_long s = BLIP_READER_READ( reader );
|
||||||
|
if ( (blip_sample_t) s != s )
|
||||||
|
s = 0x7FFF - (s >> 24);
|
||||||
|
*out++ = (blip_sample_t) s;
|
||||||
|
BLIP_READER_NEXT( reader, bass );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( blip_long n = count; n; --n )
|
||||||
|
{
|
||||||
|
blip_long s = BLIP_READER_READ( reader );
|
||||||
|
if ( (blip_sample_t) s != s )
|
||||||
|
s = 0x7FFF - (s >> 24);
|
||||||
|
*out = (blip_sample_t) s;
|
||||||
|
out += 2;
|
||||||
|
BLIP_READER_NEXT( reader, bass );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BLIP_READER_END( reader, *this );
|
||||||
|
|
||||||
|
remove_samples( count );
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
|
||||||
|
{
|
||||||
|
if ( buffer_size_ == silent_buf_size )
|
||||||
|
{
|
||||||
|
assert( 0 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
|
||||||
|
|
||||||
|
int const sample_shift = blip_sample_bits - 16;
|
||||||
|
int prev = 0;
|
||||||
|
while ( count-- )
|
||||||
|
{
|
||||||
|
blip_long s = (blip_long) *in++ << sample_shift;
|
||||||
|
*out += s - prev;
|
||||||
|
prev = s;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
*out -= prev;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,498 @@
|
||||||
|
// Band-limited sound synthesis buffer
|
||||||
|
// Various changes and hacks for use in Mednafen.
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define blip_inline inline __attribute__((always_inline))
|
||||||
|
#else
|
||||||
|
#define blip_inline inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
// Blip_Buffer 0.4.1
|
||||||
|
#ifndef BLIP_BUFFER_H
|
||||||
|
#define BLIP_BUFFER_H
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
typedef int32_t blip_long;
|
||||||
|
typedef uint32_t blip_ulong;
|
||||||
|
typedef int64_t blip_s64;
|
||||||
|
typedef uint64_t blip_u64;
|
||||||
|
|
||||||
|
// Time unit at source clock rate
|
||||||
|
typedef blip_long blip_time_t;
|
||||||
|
|
||||||
|
// Output samples are 16-bit signed, with a range of -32768 to 32767
|
||||||
|
typedef short blip_sample_t;
|
||||||
|
enum { blip_sample_max = 32767 };
|
||||||
|
|
||||||
|
class Blip_Buffer {
|
||||||
|
public:
|
||||||
|
typedef const char* blargg_err_t;
|
||||||
|
|
||||||
|
// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
|
||||||
|
// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
|
||||||
|
// isn't enough memory, returns error without affecting current buffer setup.
|
||||||
|
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
|
||||||
|
|
||||||
|
// Set number of source time units per second
|
||||||
|
void clock_rate( long );
|
||||||
|
|
||||||
|
// End current time frame of specified duration and make its samples available
|
||||||
|
// (along with any still-unread samples) for reading with read_samples(). Begins
|
||||||
|
// a new time frame at the end of the current frame.
|
||||||
|
void end_frame( blip_time_t time );
|
||||||
|
|
||||||
|
// Read at most 'max_samples' out of buffer into 'dest', removing them from from
|
||||||
|
// the buffer. Returns number of samples actually read and removed. If stereo is
|
||||||
|
// true, increments 'dest' one extra time after writing each sample, to allow
|
||||||
|
// easy interleving of two channels into a stereo output buffer.
|
||||||
|
long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
|
||||||
|
|
||||||
|
// Additional optional features
|
||||||
|
|
||||||
|
// Current output sample rate
|
||||||
|
long sample_rate() const;
|
||||||
|
|
||||||
|
// Length of buffer, in milliseconds
|
||||||
|
int length() const;
|
||||||
|
|
||||||
|
// Number of source time units per second
|
||||||
|
long clock_rate() const;
|
||||||
|
|
||||||
|
// Set frequency high-pass filter frequency, where higher values reduce bass more
|
||||||
|
void bass_freq( int frequency );
|
||||||
|
|
||||||
|
// Number of samples delay from synthesis to samples read out
|
||||||
|
int output_latency() const;
|
||||||
|
|
||||||
|
// Remove all available samples and clear buffer to silence. If 'entire_buffer' is
|
||||||
|
// false, just clears out any samples waiting rather than the entire buffer.
|
||||||
|
void clear( int entire_buffer = 1 );
|
||||||
|
|
||||||
|
// Number of samples available for reading with read_samples()
|
||||||
|
long samples_avail() const;
|
||||||
|
|
||||||
|
// Remove 'count' samples from those waiting to be read
|
||||||
|
void remove_samples( long count );
|
||||||
|
|
||||||
|
// Experimental features
|
||||||
|
|
||||||
|
// Count number of clocks needed until 'count' samples will be available.
|
||||||
|
// If buffer can't even hold 'count' samples, returns number of clocks until
|
||||||
|
// buffer becomes full.
|
||||||
|
blip_time_t count_clocks( long count ) const;
|
||||||
|
|
||||||
|
// Number of raw samples that can be mixed within frame of specified duration.
|
||||||
|
long count_samples( blip_time_t duration ) const;
|
||||||
|
|
||||||
|
// Mix 'count' samples from 'buf' into buffer.
|
||||||
|
void mix_samples( blip_sample_t const* buf, long count );
|
||||||
|
|
||||||
|
// not documented yet
|
||||||
|
void set_modified() { modified_ = 1; }
|
||||||
|
int clear_modified() { int b = modified_; modified_ = 0; return b; }
|
||||||
|
typedef blip_u64 blip_resampled_time_t;
|
||||||
|
void remove_silence( long count );
|
||||||
|
blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
|
||||||
|
blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
|
||||||
|
blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
|
||||||
|
public:
|
||||||
|
Blip_Buffer();
|
||||||
|
~Blip_Buffer();
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
|
typedef blip_resampled_time_t resampled_time_t;
|
||||||
|
blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
|
||||||
|
blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
|
||||||
|
private:
|
||||||
|
// noncopyable
|
||||||
|
Blip_Buffer( const Blip_Buffer& );
|
||||||
|
Blip_Buffer& operator = ( const Blip_Buffer& );
|
||||||
|
public:
|
||||||
|
typedef blip_time_t buf_t_;
|
||||||
|
blip_u64 factor_;
|
||||||
|
blip_resampled_time_t offset_;
|
||||||
|
buf_t_* buffer_;
|
||||||
|
blip_long buffer_size_;
|
||||||
|
blip_long reader_accum_;
|
||||||
|
int bass_shift_;
|
||||||
|
private:
|
||||||
|
long sample_rate_;
|
||||||
|
long clock_rate_;
|
||||||
|
int bass_freq_;
|
||||||
|
int length_;
|
||||||
|
int modified_;
|
||||||
|
friend class Blip_Reader;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BLIP_BUFFER_ACCURACY 32
|
||||||
|
#define BLIP_PHASE_BITS 8
|
||||||
|
|
||||||
|
// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
|
||||||
|
// but reduce maximum buffer size.
|
||||||
|
//#ifndef BLIP_BUFFER_ACCURACY
|
||||||
|
// #define BLIP_BUFFER_ACCURACY 16
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
|
||||||
|
// noticeable broadband noise when synthesizing high frequency square waves.
|
||||||
|
// Affects size of Blip_Synth objects since they store the waveform directly.
|
||||||
|
//#ifndef BLIP_PHASE_BITS
|
||||||
|
// #if BLIP_BUFFER_FAST
|
||||||
|
// #define BLIP_PHASE_BITS 8
|
||||||
|
// #else
|
||||||
|
// #define BLIP_PHASE_BITS 6
|
||||||
|
// #endif
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
typedef blip_u64 blip_resampled_time_t;
|
||||||
|
int const blip_widest_impulse_ = 16;
|
||||||
|
int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
|
||||||
|
int const blip_res = 1 << BLIP_PHASE_BITS;
|
||||||
|
class blip_eq_t;
|
||||||
|
|
||||||
|
class Blip_Synth_Fast_ {
|
||||||
|
public:
|
||||||
|
Blip_Buffer* buf;
|
||||||
|
int last_amp;
|
||||||
|
int delta_factor;
|
||||||
|
|
||||||
|
void volume_unit( double );
|
||||||
|
Blip_Synth_Fast_();
|
||||||
|
void treble_eq( blip_eq_t const& ) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Blip_Synth_ {
|
||||||
|
public:
|
||||||
|
Blip_Buffer* buf;
|
||||||
|
int last_amp;
|
||||||
|
int delta_factor;
|
||||||
|
|
||||||
|
void volume_unit( double );
|
||||||
|
Blip_Synth_( short* impulses, int width );
|
||||||
|
void treble_eq( blip_eq_t const& );
|
||||||
|
private:
|
||||||
|
double volume_unit_;
|
||||||
|
short* const impulses;
|
||||||
|
int const width;
|
||||||
|
blip_long kernel_unit;
|
||||||
|
int impulses_size() const { return blip_res / 2 * width + 1; }
|
||||||
|
void adjust_impulse();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Quality level. Start with blip_good_quality.
|
||||||
|
const int blip_med_quality = 8;
|
||||||
|
const int blip_good_quality = 12;
|
||||||
|
const int blip_high_quality = 16;
|
||||||
|
|
||||||
|
// Range specifies the greatest expected change in amplitude. Calculate it
|
||||||
|
// by finding the difference between the maximum and minimum expected
|
||||||
|
// amplitudes (max - min).
|
||||||
|
template<int quality,int range>
|
||||||
|
class Blip_Synth {
|
||||||
|
public:
|
||||||
|
// Set overall volume of waveform
|
||||||
|
void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
|
||||||
|
|
||||||
|
// Configure low-pass filter (see blip_buffer.txt)
|
||||||
|
void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
|
||||||
|
|
||||||
|
// Get/set Blip_Buffer used for output
|
||||||
|
Blip_Buffer* output() const { return impl.buf; }
|
||||||
|
void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
|
||||||
|
|
||||||
|
// Update amplitude of waveform at given time. Using this requires a separate
|
||||||
|
// Blip_Synth for each waveform.
|
||||||
|
void update( blip_time_t time, int amplitude );
|
||||||
|
|
||||||
|
// Low-level interface
|
||||||
|
|
||||||
|
// Add an amplitude transition of specified delta, optionally into specified buffer
|
||||||
|
// rather than the one set with output(). Delta can be positive or negative.
|
||||||
|
// The actual change in amplitude is delta * (volume / range)
|
||||||
|
void offset( blip_time_t, int delta, Blip_Buffer* ) const;
|
||||||
|
void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
|
||||||
|
|
||||||
|
// Works directly in terms of fractional output samples. Contact author for more info.
|
||||||
|
void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
|
||||||
|
|
||||||
|
// Same as offset(), except code is inlined for higher performance
|
||||||
|
void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
|
||||||
|
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
|
||||||
|
}
|
||||||
|
void offset_inline( blip_time_t t, int delta ) const {
|
||||||
|
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
#if BLIP_BUFFER_FAST
|
||||||
|
Blip_Synth_Fast_ impl;
|
||||||
|
#else
|
||||||
|
Blip_Synth_ impl;
|
||||||
|
typedef short imp_t;
|
||||||
|
imp_t impulses [blip_res * (quality / 2) + 1];
|
||||||
|
public:
|
||||||
|
Blip_Synth() : impl( impulses, quality ) { }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Low-pass equalization parameters
|
||||||
|
class blip_eq_t {
|
||||||
|
public:
|
||||||
|
// Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
|
||||||
|
// treble, small positive values (0 to 5.0) increase treble.
|
||||||
|
blip_eq_t( double treble_db = 0 );
|
||||||
|
|
||||||
|
// See blip_buffer.txt
|
||||||
|
blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
|
||||||
|
|
||||||
|
private:
|
||||||
|
double treble;
|
||||||
|
long rolloff_freq;
|
||||||
|
long sample_rate;
|
||||||
|
long cutoff_freq;
|
||||||
|
void generate( float* out, int count ) const;
|
||||||
|
friend class Blip_Synth_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int const blip_sample_bits = 30;
|
||||||
|
|
||||||
|
// Dummy Blip_Buffer to direct sound output to, for easy muting without
|
||||||
|
// having to stop sound code.
|
||||||
|
class Silent_Blip_Buffer : public Blip_Buffer {
|
||||||
|
buf_t_ buf [blip_buffer_extra_ + 1];
|
||||||
|
public:
|
||||||
|
// The following cannot be used (an assertion will fail if attempted):
|
||||||
|
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
|
||||||
|
blip_time_t count_clocks( long count ) const;
|
||||||
|
void mix_samples( blip_sample_t const* buf, long count );
|
||||||
|
|
||||||
|
Silent_Blip_Buffer();
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined (__GNUC__) || _MSC_VER >= 1100
|
||||||
|
#define BLIP_RESTRICT __restrict
|
||||||
|
#else
|
||||||
|
#define BLIP_RESTRICT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Optimized reading from Blip_Buffer, for use in custom sample output
|
||||||
|
|
||||||
|
// Begin reading from buffer. Name should be unique to the current block.
|
||||||
|
#define BLIP_READER_BEGIN( name, blip_buffer ) \
|
||||||
|
const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
|
||||||
|
blip_long name##_reader_accum = (blip_buffer).reader_accum_
|
||||||
|
|
||||||
|
// Get value to pass to BLIP_READER_NEXT()
|
||||||
|
#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
|
||||||
|
|
||||||
|
// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
|
||||||
|
// code at the cost of having no bass control
|
||||||
|
int const blip_reader_default_bass = 9;
|
||||||
|
|
||||||
|
// Current sample
|
||||||
|
#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
|
||||||
|
|
||||||
|
// Current raw sample in full internal resolution
|
||||||
|
#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
|
||||||
|
|
||||||
|
// Advance to next sample
|
||||||
|
#define BLIP_READER_NEXT( name, bass ) \
|
||||||
|
(void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
|
||||||
|
|
||||||
|
// End reading samples from buffer. The number of samples read must now be removed
|
||||||
|
// using Blip_Buffer::remove_samples().
|
||||||
|
#define BLIP_READER_END( name, blip_buffer ) \
|
||||||
|
(void) ((blip_buffer).reader_accum_ = name##_reader_accum)
|
||||||
|
|
||||||
|
|
||||||
|
// Compatibility with older version
|
||||||
|
const long blip_unscaled = 65535;
|
||||||
|
const int blip_low_quality = blip_med_quality;
|
||||||
|
const int blip_best_quality = blip_high_quality;
|
||||||
|
|
||||||
|
// Deprecated; use BLIP_READER macros as follows:
|
||||||
|
// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
|
||||||
|
// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
|
||||||
|
// r.read() -> BLIP_READER_READ( r )
|
||||||
|
// r.read_raw() -> BLIP_READER_READ_RAW( r )
|
||||||
|
// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
|
||||||
|
// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
|
||||||
|
// r.end( buf ) -> BLIP_READER_END( r, buf )
|
||||||
|
class Blip_Reader {
|
||||||
|
public:
|
||||||
|
int begin( Blip_Buffer& );
|
||||||
|
blip_long read() const { return accum >> (blip_sample_bits - 16); }
|
||||||
|
blip_long read_raw() const { return accum; }
|
||||||
|
void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
|
||||||
|
void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Blip_Buffer::buf_t_* buf;
|
||||||
|
blip_long accum;
|
||||||
|
};
|
||||||
|
|
||||||
|
// End of public interface
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
template<int quality,int range>
|
||||||
|
blip_inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
|
||||||
|
int delta, Blip_Buffer* blip_buf ) const
|
||||||
|
{
|
||||||
|
// Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
|
||||||
|
// need for a longer buffer as set by set_sample_rate().
|
||||||
|
assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
|
||||||
|
delta *= impl.delta_factor;
|
||||||
|
blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
|
||||||
|
int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
|
||||||
|
|
||||||
|
#if BLIP_BUFFER_FAST
|
||||||
|
blip_long left = buf [0] + delta;
|
||||||
|
|
||||||
|
// Kind of crappy, but doing shift after multiply results in overflow.
|
||||||
|
// Alternate way of delaying multiply by delta_factor results in worse
|
||||||
|
// sub-sample resolution.
|
||||||
|
blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
|
||||||
|
left -= right;
|
||||||
|
right += buf [1];
|
||||||
|
|
||||||
|
buf [0] = left;
|
||||||
|
buf [1] = right;
|
||||||
|
#else
|
||||||
|
|
||||||
|
int const fwd = (blip_widest_impulse_ - quality) / 2;
|
||||||
|
int const rev = fwd + quality - 2;
|
||||||
|
int const mid = quality / 2 - 1;
|
||||||
|
|
||||||
|
imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
|
||||||
|
|
||||||
|
#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
|
||||||
|
defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
|
||||||
|
|
||||||
|
// straight forward implementation resulted in better code on GCC for x86
|
||||||
|
|
||||||
|
#define ADD_IMP( out, in ) \
|
||||||
|
buf [out] += (blip_long) imp [blip_res * (in)] * delta
|
||||||
|
|
||||||
|
#define BLIP_FWD( i ) {\
|
||||||
|
ADD_IMP( fwd + i, i );\
|
||||||
|
ADD_IMP( fwd + 1 + i, i + 1 );\
|
||||||
|
}
|
||||||
|
#define BLIP_REV( r ) {\
|
||||||
|
ADD_IMP( rev - r, r + 1 );\
|
||||||
|
ADD_IMP( rev + 1 - r, r );\
|
||||||
|
}
|
||||||
|
|
||||||
|
BLIP_FWD( 0 )
|
||||||
|
if ( quality > 8 ) BLIP_FWD( 2 )
|
||||||
|
if ( quality > 12 ) BLIP_FWD( 4 )
|
||||||
|
{
|
||||||
|
ADD_IMP( fwd + mid - 1, mid - 1 );
|
||||||
|
ADD_IMP( fwd + mid , mid );
|
||||||
|
imp = impulses + phase;
|
||||||
|
}
|
||||||
|
if ( quality > 12 ) BLIP_REV( 6 )
|
||||||
|
if ( quality > 8 ) BLIP_REV( 4 )
|
||||||
|
BLIP_REV( 2 )
|
||||||
|
|
||||||
|
ADD_IMP( rev , 1 );
|
||||||
|
ADD_IMP( rev + 1, 0 );
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// for RISC processors, help compiler by reading ahead of writes
|
||||||
|
|
||||||
|
#define BLIP_FWD( i ) {\
|
||||||
|
blip_long t0 = i0 * delta + buf [fwd + i];\
|
||||||
|
blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
|
||||||
|
i0 = imp [blip_res * (i + 2)];\
|
||||||
|
buf [fwd + i] = t0;\
|
||||||
|
buf [fwd + 1 + i] = t1;\
|
||||||
|
}
|
||||||
|
#define BLIP_REV( r ) {\
|
||||||
|
blip_long t0 = i0 * delta + buf [rev - r];\
|
||||||
|
blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
|
||||||
|
i0 = imp [blip_res * (r - 1)];\
|
||||||
|
buf [rev - r] = t0;\
|
||||||
|
buf [rev + 1 - r] = t1;\
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_long i0 = *imp;
|
||||||
|
BLIP_FWD( 0 )
|
||||||
|
if ( quality > 8 ) BLIP_FWD( 2 )
|
||||||
|
if ( quality > 12 ) BLIP_FWD( 4 )
|
||||||
|
{
|
||||||
|
blip_long t0 = i0 * delta + buf [fwd + mid - 1];
|
||||||
|
blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
|
||||||
|
imp = impulses + phase;
|
||||||
|
i0 = imp [blip_res * mid];
|
||||||
|
buf [fwd + mid - 1] = t0;
|
||||||
|
buf [fwd + mid ] = t1;
|
||||||
|
}
|
||||||
|
if ( quality > 12 ) BLIP_REV( 6 )
|
||||||
|
if ( quality > 8 ) BLIP_REV( 4 )
|
||||||
|
BLIP_REV( 2 )
|
||||||
|
|
||||||
|
blip_long t0 = i0 * delta + buf [rev ];
|
||||||
|
blip_long t1 = *imp * delta + buf [rev + 1];
|
||||||
|
buf [rev ] = t0;
|
||||||
|
buf [rev + 1] = t1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef BLIP_FWD
|
||||||
|
#undef BLIP_REV
|
||||||
|
|
||||||
|
template<int quality,int range>
|
||||||
|
#if BLIP_BUFFER_FAST
|
||||||
|
blip_inline
|
||||||
|
#endif
|
||||||
|
void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
|
||||||
|
{
|
||||||
|
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int quality,int range>
|
||||||
|
#if BLIP_BUFFER_FAST
|
||||||
|
blip_inline
|
||||||
|
#endif
|
||||||
|
void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
|
||||||
|
{
|
||||||
|
int delta = amp - impl.last_amp;
|
||||||
|
impl.last_amp = amp;
|
||||||
|
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_inline blip_eq_t::blip_eq_t( double t ) :
|
||||||
|
treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
|
||||||
|
blip_inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
|
||||||
|
treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
|
||||||
|
|
||||||
|
blip_inline int Blip_Buffer::length() const { return length_; }
|
||||||
|
blip_inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
|
||||||
|
blip_inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
|
||||||
|
blip_inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
|
||||||
|
blip_inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
|
||||||
|
blip_inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
|
||||||
|
|
||||||
|
blip_inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
|
||||||
|
{
|
||||||
|
buf = blip_buf.buffer_;
|
||||||
|
accum = blip_buf.reader_accum_;
|
||||||
|
return blip_buf.bass_shift_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int const blip_max_length = 0;
|
||||||
|
int const blip_default_length = 250;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,146 @@
|
||||||
|
|
||||||
|
// Blip_Buffer 0.3.0. http://www.slack.net/~ant/nes-emu/
|
||||||
|
|
||||||
|
#include "Stereo_Buffer.h"
|
||||||
|
|
||||||
|
/* Library Copyright (C) 2004 Shay Green. Blip_Buffer is free software;
|
||||||
|
you can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
General Public License as published by the Free Software Foundation;
|
||||||
|
either version 2 of the License, or (at your option) any later version.
|
||||||
|
Stereo_Buffer is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details. You should have received a copy of the GNU General
|
||||||
|
Public License along with Stereo_Buffer; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
Stereo_Buffer::Stereo_Buffer() {
|
||||||
|
stereo_added = false;
|
||||||
|
was_stereo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stereo_Buffer::~Stereo_Buffer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stereo_Buffer::set_sample_rate( long rate, int msec )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < buf_count; i++ ) {
|
||||||
|
if ( bufs [i].set_sample_rate( rate, msec ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stereo_Buffer::clock_rate( long rate )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < buf_count; i++ )
|
||||||
|
bufs [i].clock_rate( rate );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stereo_Buffer::bass_freq( int bass )
|
||||||
|
{
|
||||||
|
for ( unsigned i = 0; i < buf_count; i++ )
|
||||||
|
bufs [i].bass_freq( bass );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stereo_Buffer::clear()
|
||||||
|
{
|
||||||
|
stereo_added = false;
|
||||||
|
was_stereo = false;
|
||||||
|
for ( int i = 0; i < buf_count; i++ )
|
||||||
|
bufs [i].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stereo_Buffer::end_frame( blip_time_t clock_count, bool stereo )
|
||||||
|
{
|
||||||
|
for ( unsigned i = 0; i < buf_count; i++ )
|
||||||
|
{
|
||||||
|
bufs [i].end_frame( clock_count );
|
||||||
|
}
|
||||||
|
stereo_added |= stereo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
long Stereo_Buffer::read_samples( blip_sample_t* out, long max_samples )
|
||||||
|
{
|
||||||
|
long count = bufs [0].samples_avail();
|
||||||
|
if ( count > max_samples / 2 )
|
||||||
|
count = max_samples / 2;
|
||||||
|
if ( count )
|
||||||
|
{
|
||||||
|
if ( stereo_added || was_stereo )
|
||||||
|
{
|
||||||
|
mix_stereo( out, count );
|
||||||
|
|
||||||
|
bufs [0].remove_samples( count );
|
||||||
|
bufs [1].remove_samples( count );
|
||||||
|
bufs [2].remove_samples( count );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mix_mono( out, count );
|
||||||
|
|
||||||
|
bufs [0].remove_samples( count );
|
||||||
|
|
||||||
|
bufs [1].remove_silence( count );
|
||||||
|
bufs [2].remove_silence( count );
|
||||||
|
}
|
||||||
|
|
||||||
|
// to do: this might miss opportunities for optimization
|
||||||
|
if ( !bufs [0].samples_avail() ) {
|
||||||
|
was_stereo = stereo_added;
|
||||||
|
stereo_added = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stereo_Buffer::mix_stereo( blip_sample_t* out, long count )
|
||||||
|
{
|
||||||
|
Blip_Reader l_left;
|
||||||
|
Blip_Reader l_right;
|
||||||
|
Blip_Reader l_center;
|
||||||
|
|
||||||
|
l_left.begin( bufs [1] );
|
||||||
|
l_right.begin( bufs [2] );
|
||||||
|
int bass = l_center.begin( bufs [0] );
|
||||||
|
|
||||||
|
while ( count-- )
|
||||||
|
{
|
||||||
|
int c = l_center.read();
|
||||||
|
out [0] = c + l_left.read();
|
||||||
|
out [1] = c + l_right.read();
|
||||||
|
out += 2;
|
||||||
|
|
||||||
|
l_center.next( bass );
|
||||||
|
l_left.next( bass );
|
||||||
|
l_right.next( bass );
|
||||||
|
}
|
||||||
|
|
||||||
|
l_center.end( bufs [0] );
|
||||||
|
l_right.end( bufs [2] );
|
||||||
|
l_left.end( bufs [1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stereo_Buffer::mix_mono( blip_sample_t* out, long count )
|
||||||
|
{
|
||||||
|
Blip_Reader in;
|
||||||
|
int bass = in.begin( bufs [0] );
|
||||||
|
|
||||||
|
while ( count-- )
|
||||||
|
{
|
||||||
|
int sample = in.read();
|
||||||
|
out [0] = sample;
|
||||||
|
out [1] = sample;
|
||||||
|
out += 2;
|
||||||
|
in.next( bass );
|
||||||
|
}
|
||||||
|
|
||||||
|
in.end( bufs [0] );
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
|
||||||
|
// Simple stereo Blip_Buffer for sound emulators whose oscillators output
|
||||||
|
// either on the left only, center, or right only.
|
||||||
|
|
||||||
|
// Blip_Buffer 0.3.0. Copyright (C) 2003-2004 Shay Green. GNU GPL license.
|
||||||
|
|
||||||
|
#ifndef STEREO_BUFFER_H
|
||||||
|
#define STEREO_BUFFER_H
|
||||||
|
|
||||||
|
#include "Blip_Buffer.h"
|
||||||
|
|
||||||
|
class Stereo_Buffer {
|
||||||
|
public:
|
||||||
|
Stereo_Buffer();
|
||||||
|
~Stereo_Buffer();
|
||||||
|
|
||||||
|
// Same as in Blip_Buffer (see Blip_Buffer.h)
|
||||||
|
bool set_sample_rate( long, int msec = 0 );
|
||||||
|
void clock_rate( long );
|
||||||
|
void bass_freq( int );
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Buffers to output synthesis to
|
||||||
|
Blip_Buffer* left();
|
||||||
|
Blip_Buffer* center();
|
||||||
|
Blip_Buffer* right();
|
||||||
|
|
||||||
|
// Same as in Blip_Buffer. For more efficient operation, pass false
|
||||||
|
// for was_stereo if the left and right buffers had nothing added
|
||||||
|
// to them for this frame.
|
||||||
|
void end_frame( blip_time_t, bool was_stereo = true );
|
||||||
|
|
||||||
|
// Output is stereo with channels interleved, left before right. Counts
|
||||||
|
// are in samples, *not* pairs.
|
||||||
|
long samples_avail() const;
|
||||||
|
long read_samples( blip_sample_t*, long );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// noncopyable
|
||||||
|
Stereo_Buffer( const Stereo_Buffer& );
|
||||||
|
Stereo_Buffer& operator = ( const Stereo_Buffer& );
|
||||||
|
|
||||||
|
enum { buf_count = 3 };
|
||||||
|
Blip_Buffer bufs [buf_count];
|
||||||
|
bool stereo_added;
|
||||||
|
bool was_stereo;
|
||||||
|
|
||||||
|
void mix_stereo( blip_sample_t*, long );
|
||||||
|
void mix_mono( blip_sample_t*, long );
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Blip_Buffer* Stereo_Buffer::left() {
|
||||||
|
return &bufs [1];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Blip_Buffer* Stereo_Buffer::center() {
|
||||||
|
return &bufs [0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Blip_Buffer* Stereo_Buffer::right() {
|
||||||
|
return &bufs [2];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline long Stereo_Buffer::samples_avail() const {
|
||||||
|
return bufs [0].samples_avail();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,445 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Susie object header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition for the Suzy class //
|
||||||
|
// which provides math and sprite support to the emulator //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SUSIE_H
|
||||||
|
#define SUSIE_H
|
||||||
|
|
||||||
|
#ifdef TRACE_SUSIE
|
||||||
|
|
||||||
|
#define TRACE_SUSIE0(msg) _RPT1(_CRT_WARN,"CSusie::"msg" (Time=%012d)\n",gSystemCycleCount)
|
||||||
|
#define TRACE_SUSIE1(msg,arg1) _RPT2(_CRT_WARN,"CSusie::"msg" (Time=%012d)\n",arg1,gSystemCycleCount)
|
||||||
|
#define TRACE_SUSIE2(msg,arg1,arg2) _RPT3(_CRT_WARN,"CSusie::"msg" (Time=%012d)\n",arg1,arg2,gSystemCycleCount)
|
||||||
|
#define TRACE_SUSIE3(msg,arg1,arg2,arg3) _RPT4(_CRT_WARN,"CSusie::"msg" (Time=%012d)\n",arg1,arg2,arg3,gSystemCycleCount)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TRACE_SUSIE0(msg)
|
||||||
|
#define TRACE_SUSIE1(msg,arg1)
|
||||||
|
#define TRACE_SUSIE2(msg,arg1,arg2)
|
||||||
|
#define TRACE_SUSIE3(msg,arg1,arg2,arg3)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CSystem;
|
||||||
|
|
||||||
|
#define SUSIE_START 0xfc00
|
||||||
|
#define SUSIE_SIZE 0x100
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 160
|
||||||
|
#define SCREEN_HEIGHT 102
|
||||||
|
|
||||||
|
#define LINE_END 0x80
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define button values
|
||||||
|
//
|
||||||
|
|
||||||
|
#define BUTTON_A 0x0001
|
||||||
|
#define BUTTON_B 0x0002
|
||||||
|
#define BUTTON_OPT2 0x0004
|
||||||
|
#define BUTTON_OPT1 0x0008
|
||||||
|
#define BUTTON_LEFT 0x0010
|
||||||
|
#define BUTTON_RIGHT 0x0020
|
||||||
|
#define BUTTON_UP 0x0040
|
||||||
|
#define BUTTON_DOWN 0x0080
|
||||||
|
#define BUTTON_PAUSE 0x0100
|
||||||
|
|
||||||
|
|
||||||
|
enum {line_error=0,line_abs_literal,line_literal,line_packed};
|
||||||
|
enum {math_finished=0,math_divide,math_multiply,math_init_divide,math_init_multiply};
|
||||||
|
|
||||||
|
enum {sprite_background_shadow=0,
|
||||||
|
sprite_background_noncollide,
|
||||||
|
sprite_boundary_shadow,
|
||||||
|
sprite_boundary,
|
||||||
|
sprite_normal,
|
||||||
|
sprite_noncollide,
|
||||||
|
sprite_xor_shadow,
|
||||||
|
sprite_shadow};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 Fc1:1;
|
||||||
|
uint8 Fc2:1;
|
||||||
|
uint8 Fc3:1;
|
||||||
|
uint8 reserved:1;
|
||||||
|
uint8 Ac1:1;
|
||||||
|
uint8 Ac2:1;
|
||||||
|
uint8 Ac3:1;
|
||||||
|
uint8 Ac4:1;
|
||||||
|
#else
|
||||||
|
uint8 Ac4:1;
|
||||||
|
uint8 Ac3:1;
|
||||||
|
uint8 Ac2:1;
|
||||||
|
uint8 Ac1:1;
|
||||||
|
uint8 reserved:1;
|
||||||
|
uint8 Fc3:1;
|
||||||
|
uint8 Fc2:1;
|
||||||
|
uint8 Fc1:1;
|
||||||
|
#endif
|
||||||
|
}Bits;
|
||||||
|
uint8 Byte;
|
||||||
|
};
|
||||||
|
}TSPRINIT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 Up:1;
|
||||||
|
uint8 Down:1;
|
||||||
|
uint8 Left:1;
|
||||||
|
uint8 Right:1;
|
||||||
|
uint8 Option1:1;
|
||||||
|
uint8 Option2:1;
|
||||||
|
uint8 Inside:1;
|
||||||
|
uint8 Outside:1;
|
||||||
|
#else
|
||||||
|
uint8 Outside:1;
|
||||||
|
uint8 Inside:1;
|
||||||
|
uint8 Option2:1;
|
||||||
|
uint8 Option1:1;
|
||||||
|
uint8 Right:1;
|
||||||
|
uint8 Left:1;
|
||||||
|
uint8 Down:1;
|
||||||
|
uint8 Up:1;
|
||||||
|
#endif
|
||||||
|
}Bits;
|
||||||
|
uint8 Byte;
|
||||||
|
};
|
||||||
|
}TJOYSTICK;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 spare:5;
|
||||||
|
uint8 Cart1IO:1;
|
||||||
|
uint8 Cart0IO:1;
|
||||||
|
uint8 Pause:1;
|
||||||
|
#else
|
||||||
|
uint8 Pause:1;
|
||||||
|
uint8 Cart0IO:1;
|
||||||
|
uint8 Cart1IO:1;
|
||||||
|
uint8 spare:5;
|
||||||
|
#endif
|
||||||
|
}Bits;
|
||||||
|
uint8 Byte;
|
||||||
|
};
|
||||||
|
}TSWITCHES;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 A;
|
||||||
|
uint8 B;
|
||||||
|
uint8 C;
|
||||||
|
uint8 D;
|
||||||
|
#else
|
||||||
|
uint8 D;
|
||||||
|
uint8 C;
|
||||||
|
uint8 B;
|
||||||
|
uint8 A;
|
||||||
|
#endif
|
||||||
|
}Bytes;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint16 AB;
|
||||||
|
uint16 CD;
|
||||||
|
#else
|
||||||
|
uint16 CD;
|
||||||
|
uint16 AB;
|
||||||
|
#endif
|
||||||
|
}Words;
|
||||||
|
uint32 Long;
|
||||||
|
};
|
||||||
|
}TMATHABCD;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 E;
|
||||||
|
uint8 F;
|
||||||
|
uint8 G;
|
||||||
|
uint8 H;
|
||||||
|
#else
|
||||||
|
uint8 H;
|
||||||
|
uint8 G;
|
||||||
|
uint8 F;
|
||||||
|
uint8 E;
|
||||||
|
#endif
|
||||||
|
}Bytes;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint16 EF;
|
||||||
|
uint16 GH;
|
||||||
|
#else
|
||||||
|
uint16 GH;
|
||||||
|
uint16 EF;
|
||||||
|
#endif
|
||||||
|
}Words;
|
||||||
|
uint32 Long;
|
||||||
|
};
|
||||||
|
}TMATHEFGH;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 J;
|
||||||
|
uint8 K;
|
||||||
|
uint8 L;
|
||||||
|
uint8 M;
|
||||||
|
#else
|
||||||
|
uint8 M;
|
||||||
|
uint8 L;
|
||||||
|
uint8 K;
|
||||||
|
uint8 J;
|
||||||
|
#endif
|
||||||
|
}Bytes;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint16 JK;
|
||||||
|
uint16 LM;
|
||||||
|
#else
|
||||||
|
uint16 LM;
|
||||||
|
uint16 JK;
|
||||||
|
#endif
|
||||||
|
}Words;
|
||||||
|
uint32 Long;
|
||||||
|
};
|
||||||
|
}TMATHJKLM;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint8 xx2;
|
||||||
|
uint8 xx1;
|
||||||
|
uint8 N;
|
||||||
|
uint8 P;
|
||||||
|
#else
|
||||||
|
uint8 P;
|
||||||
|
uint8 N;
|
||||||
|
uint8 xx1;
|
||||||
|
uint8 xx2;
|
||||||
|
#endif
|
||||||
|
}Bytes;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
uint16 xx1;
|
||||||
|
uint16 NP;
|
||||||
|
#else
|
||||||
|
uint16 NP;
|
||||||
|
uint16 xx1;
|
||||||
|
#endif
|
||||||
|
}Words;
|
||||||
|
uint32 Long;
|
||||||
|
};
|
||||||
|
}TMATHNP;
|
||||||
|
|
||||||
|
|
||||||
|
class CSusie : public CLynxBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSusie(CSystem& parent) MDFN_COLD;
|
||||||
|
~CSusie() MDFN_COLD;
|
||||||
|
|
||||||
|
void Reset(void) MDFN_COLD;
|
||||||
|
|
||||||
|
uint8 Peek(uint32 addr);
|
||||||
|
void Poke(uint32 addr,uint8 data);
|
||||||
|
uint32 ReadCycle(void) {return 9;};
|
||||||
|
uint32 WriteCycle(void) {return 5;};
|
||||||
|
uint32 ObjectSize(void) {return SUSIE_SIZE;};
|
||||||
|
|
||||||
|
void SetButtonData(uint32 data) {mJOYSTICK.Byte=(uint8)data;mSWITCHES.Byte=(uint8)(data>>8);};
|
||||||
|
uint32 GetButtonData(void) {return mJOYSTICK.Byte+(mSWITCHES.Byte<<8);};
|
||||||
|
|
||||||
|
uint32 PaintSprites(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DoMathDivide(void);
|
||||||
|
void DoMathMultiply(void);
|
||||||
|
uint32 LineInit(uint32 voff);
|
||||||
|
uint32 LineGetPixel(void);
|
||||||
|
uint32 LineGetBits(uint32 bits);
|
||||||
|
|
||||||
|
void ProcessPixel(uint32 hoff,uint32 pixel);
|
||||||
|
void WritePixel(uint32 hoff,uint32 pixel);
|
||||||
|
uint32 ReadPixel(uint32 hoff);
|
||||||
|
void WriteCollision(uint32 hoff,uint32 pixel);
|
||||||
|
uint32 ReadCollision(uint32 hoff);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSystem& mSystem;
|
||||||
|
|
||||||
|
uint32 cycles_used;
|
||||||
|
|
||||||
|
Uuint16 mTMPADR; // ENG
|
||||||
|
Uuint16 mTILTACUM; // ENG
|
||||||
|
Uuint16 mHOFF; // CPU
|
||||||
|
Uuint16 mVOFF; // CPU
|
||||||
|
Uuint16 mVIDBAS; // CPU
|
||||||
|
Uuint16 mCOLLBAS; // CPU
|
||||||
|
Uuint16 mVIDADR; // ENG
|
||||||
|
Uuint16 mCOLLADR; // ENG
|
||||||
|
Uuint16 mSCBNEXT; // SCB
|
||||||
|
Uuint16 mSPRDLINE; // SCB
|
||||||
|
Uuint16 mHPOSSTRT; // SCB
|
||||||
|
Uuint16 mVPOSSTRT; // SCB
|
||||||
|
Uuint16 mSPRHSIZ; // SCB
|
||||||
|
Uuint16 mSPRVSIZ; // SCB
|
||||||
|
Uuint16 mSTRETCH; // ENG
|
||||||
|
Uuint16 mTILT; // ENG
|
||||||
|
Uuint16 mSPRDOFF; // ENG
|
||||||
|
Uuint16 mSPRVPOS; // ENG
|
||||||
|
Uuint16 mCOLLOFF; // CPU
|
||||||
|
Uuint16 mVSIZACUM; // ENG
|
||||||
|
Uuint16 mHSIZACUM; // K.s creation
|
||||||
|
Uuint16 mHSIZOFF; // CPU
|
||||||
|
Uuint16 mVSIZOFF; // CPU
|
||||||
|
Uuint16 mSCBADR; // ENG
|
||||||
|
Uuint16 mPROCADR; // ENG
|
||||||
|
|
||||||
|
TMATHABCD mMATHABCD; // ENG
|
||||||
|
TMATHEFGH mMATHEFGH; // ENG
|
||||||
|
TMATHJKLM mMATHJKLM; // ENG
|
||||||
|
TMATHNP mMATHNP; // ENG
|
||||||
|
int mMATHAB_sign;
|
||||||
|
int mMATHCD_sign;
|
||||||
|
int mMATHEFGH_sign;
|
||||||
|
|
||||||
|
int mSPRCTL0_Type; // SCB
|
||||||
|
int mSPRCTL0_Vflip;
|
||||||
|
int mSPRCTL0_Hflip;
|
||||||
|
int mSPRCTL0_PixelBits;
|
||||||
|
|
||||||
|
int mSPRCTL1_StartLeft; // SCB
|
||||||
|
int mSPRCTL1_StartUp;
|
||||||
|
int mSPRCTL1_SkipSprite;
|
||||||
|
int mSPRCTL1_ReloadPalette;
|
||||||
|
int mSPRCTL1_ReloadDepth;
|
||||||
|
int mSPRCTL1_Sizing;
|
||||||
|
int mSPRCTL1_Literal;
|
||||||
|
|
||||||
|
int mSPRCOLL_Number; //CPU
|
||||||
|
int mSPRCOLL_Collide;
|
||||||
|
|
||||||
|
int mSPRSYS_StopOnCurrent; //CPU
|
||||||
|
int mSPRSYS_LeftHand;
|
||||||
|
int mSPRSYS_VStretch;
|
||||||
|
int mSPRSYS_NoCollide;
|
||||||
|
int mSPRSYS_Accumulate;
|
||||||
|
int mSPRSYS_SignedMath;
|
||||||
|
int mSPRSYS_Status;
|
||||||
|
int mSPRSYS_UnsafeAccess;
|
||||||
|
int mSPRSYS_LastCarry;
|
||||||
|
int mSPRSYS_Mathbit;
|
||||||
|
int mSPRSYS_MathInProgress;
|
||||||
|
|
||||||
|
uint32 mSUZYBUSEN; // CPU
|
||||||
|
|
||||||
|
TSPRINIT mSPRINIT; // CPU
|
||||||
|
|
||||||
|
uint32 mSPRGO; // CPU
|
||||||
|
int mEVERON;
|
||||||
|
|
||||||
|
uint8 mPenIndex[16]; // SCB
|
||||||
|
|
||||||
|
// Line rendering related variables
|
||||||
|
|
||||||
|
uint32 mLineType;
|
||||||
|
uint32 mLineShiftRegCount;
|
||||||
|
uint32 mLineShiftReg;
|
||||||
|
uint32 mLineRepeatCount;
|
||||||
|
uint32 mLinePixel;
|
||||||
|
uint32 mLinePacketBitsLeft;
|
||||||
|
|
||||||
|
int mCollision;
|
||||||
|
|
||||||
|
uint8 *mRamPointer;
|
||||||
|
|
||||||
|
uint32 mLineBaseAddress;
|
||||||
|
uint32 mLineCollisionAddress;
|
||||||
|
|
||||||
|
int hquadoff, vquadoff;
|
||||||
|
|
||||||
|
// Joystick switches
|
||||||
|
|
||||||
|
TJOYSTICK mJOYSTICK;
|
||||||
|
TSWITCHES mSWITCHES;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Systembase object class definition //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition for the systembase //
|
||||||
|
// class that is required to get around cross dependencies between //
|
||||||
|
// cpu/mikie/system classes //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SYSBASE_H
|
||||||
|
#define SYSBASE_H
|
||||||
|
|
||||||
|
|
||||||
|
class CSystemBase
|
||||||
|
{
|
||||||
|
// Function members
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~CSystemBase() {};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void Reset()=0;
|
||||||
|
virtual void Poke_CPU(uint32 addr,uint8 data)=0;
|
||||||
|
virtual uint8 Peek_CPU(uint32 addr)=0;
|
||||||
|
virtual void PokeW_CPU(uint32 addr,uint16 data)=0;
|
||||||
|
virtual uint16 PeekW_CPU(uint32 addr)=0;
|
||||||
|
|
||||||
|
virtual void Poke_RAM(uint32 addr,uint8 data)=0;
|
||||||
|
virtual uint8 Peek_RAM(uint32 addr)=0;
|
||||||
|
virtual void PokeW_RAM(uint32 addr,uint16 data)=0;
|
||||||
|
virtual uint16 PeekW_RAM(uint32 addr)=0;
|
||||||
|
|
||||||
|
virtual uint8* GetRamPointer()=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,264 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// System object class //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This class provides the glue to bind of of the emulation objects //
|
||||||
|
// together via peek/poke handlers and pass thru interfaces to lower //
|
||||||
|
// objects, all control of the emulator is done via this class. Update() //
|
||||||
|
// does most of the work and each call emulates one CPU instruction and //
|
||||||
|
// updates all of the relevant hardware if required. It must be remembered //
|
||||||
|
// that if that instruction involves setting SPRGO then, it will cause a //
|
||||||
|
// sprite painting operation and then a corresponding update of all of the //
|
||||||
|
// hardware which will usually involve recursive calls to Update, see //
|
||||||
|
// Mikey SPRGO code for more details. //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define SYSTEM_CPP
|
||||||
|
|
||||||
|
//#include <crtdbg.h>
|
||||||
|
//#define TRACE_SYSTEM
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
CSystem::CSystem(const uint8 *game, uint32 gamesize, const uint8 *bios, uint32 biossize, int pagesize0, int pagesize1, bool lowpass)
|
||||||
|
{
|
||||||
|
// load lynxboot.img
|
||||||
|
mRom = new CRom(bios, biossize);
|
||||||
|
|
||||||
|
mCart = new CCart(game, gamesize, pagesize0, pagesize1);
|
||||||
|
mRam = new CRam();
|
||||||
|
|
||||||
|
mMikie = new CMikie(*this);
|
||||||
|
mSusie = new CSusie(*this);
|
||||||
|
|
||||||
|
// Instantiate the memory map handler
|
||||||
|
mMemMap = new CMemMap(*this);
|
||||||
|
|
||||||
|
// Now the handlers are set we can instantiate the CPU as is will use handlers on reset
|
||||||
|
mCpu = new C65C02(*this);
|
||||||
|
|
||||||
|
mMikie->mikbuf.set_sample_rate(44100, 60);
|
||||||
|
mMikie->mikbuf.clock_rate((long int)(16000000 / 4));
|
||||||
|
mMikie->mikbuf.bass_freq(60);
|
||||||
|
mMikie->miksynth.volume(0.50);
|
||||||
|
mMikie->miksynth.treble_eq(lowpass ? -35 : 0);
|
||||||
|
|
||||||
|
// Now init is complete do a reset, this will cause many things to be reset twice
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSystem::~CSystem()
|
||||||
|
{
|
||||||
|
delete mCart;
|
||||||
|
delete mRom;
|
||||||
|
delete mRam;
|
||||||
|
delete mCpu;
|
||||||
|
delete mMikie;
|
||||||
|
delete mSusie;
|
||||||
|
delete mMemMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSystem::Reset()
|
||||||
|
{
|
||||||
|
gSystemCycleCount=0;
|
||||||
|
gNextTimerEvent=0;
|
||||||
|
// gCPUBootAddress=0;
|
||||||
|
gSystemIRQ=FALSE;
|
||||||
|
gSystemNMI=FALSE;
|
||||||
|
gSystemCPUSleep=FALSE;
|
||||||
|
gSystemHalt=FALSE;
|
||||||
|
gSuzieDoneTime = 0;
|
||||||
|
|
||||||
|
mMemMap->Reset();
|
||||||
|
mCart->Reset();
|
||||||
|
mRom->Reset();
|
||||||
|
mRam->Reset();
|
||||||
|
mMikie->Reset();
|
||||||
|
mSusie->Reset();
|
||||||
|
mCpu->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int Load(MDFNFILE *fp)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lynxie = new CSystem(fp->data, fp->size);
|
||||||
|
|
||||||
|
switch(lynxie->CartGetRotate())
|
||||||
|
{
|
||||||
|
case CART_ROTATE_LEFT:
|
||||||
|
MDFNGameInfo->rotated = MDFN_ROTATE270;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CART_ROTATE_RIGHT:
|
||||||
|
MDFNGameInfo->rotated = MDFN_ROTATE90;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(MDFNGameInfo->MD5, lynxie->mCart->MD5, 16);
|
||||||
|
MDFNGameInfo->GameSetMD5Valid = FALSE;
|
||||||
|
|
||||||
|
MDFN_printf(_("ROM: %dKiB\n"), (lynxie->mCart->InfoROMSize + 1023) / 1024);
|
||||||
|
MDFN_printf(_("ROM CRC32: 0x%08x\n"), lynxie->mCart->CRC32());
|
||||||
|
MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());
|
||||||
|
|
||||||
|
MDFNGameInfo->fps = (uint32)(59.8 * 65536 * 256);
|
||||||
|
|
||||||
|
if(MDFN_GetSettingB("lynx.lowpass"))
|
||||||
|
{
|
||||||
|
lynxie->mMikie->miksynth.treble_eq(-35);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lynxie->mMikie->miksynth.treble_eq(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void CSystem::Advance(int buttons, uint32 *vbuff, int16 *sbuff, int &sbuffsize)
|
||||||
|
{
|
||||||
|
// this check needs to occur at least once every 250 million cycles or better
|
||||||
|
mMikie->CheckWrap();
|
||||||
|
|
||||||
|
|
||||||
|
SetButtonData(buttons);
|
||||||
|
|
||||||
|
uint32 start = gSystemCycleCount;
|
||||||
|
|
||||||
|
// audio start frame
|
||||||
|
mMikie->startTS = start;
|
||||||
|
|
||||||
|
mMikie->mpDisplayCurrent = vbuff;
|
||||||
|
|
||||||
|
// go to next frame end, or no more than 200,000 cycles to avoid exploding the output buffer (was set at 60ms limit)
|
||||||
|
while (mMikie->mpDisplayCurrent && gSystemCycleCount - start < 200000)
|
||||||
|
// while (gSystemCycleCount - start < 700000) // what's the magic significance?
|
||||||
|
{
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// total cycles executed is now gSystemCycleCount - start
|
||||||
|
mMikie->mikbuf.end_frame((gSystemCycleCount - start) >> 2);
|
||||||
|
sbuffsize = mMikie->mikbuf.read_samples(sbuff, sbuffsize) / 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
static MDFNSetting LynxSettings[] =
|
||||||
|
{
|
||||||
|
{ "lynx.rotateinput", MDFNSF_NOFLAGS, gettext_noop("Virtually rotate D-pad along with screen."), NULL, MDFNST_BOOL, "1" },
|
||||||
|
{ "lynx.lowpass", MDFNSF_CAT_SOUND, gettext_noop("Enable sound output lowpass filter."), NULL, MDFNST_BOOL, "1" },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
static const InputDeviceInputInfoStruct IDII[] =
|
||||||
|
{
|
||||||
|
{ "a", "A (outer)", 8, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||||
|
{ "b", "B (inner)", 7, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||||
|
{ "option_2", "Option 2 (lower)", 5, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||||
|
{ "option_1", "Option 1 (upper)", 4, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||||
|
|
||||||
|
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right", { "up", "right", "down" } },
|
||||||
|
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left", { "down", "left", "up" } },
|
||||||
|
{ "up", "UP ↑", 0, IDIT_BUTTON, "down", { "right", "down", "left" } },
|
||||||
|
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up", { "left", "up", "right" } },
|
||||||
|
{ "pause", "PAUSE", 6, IDIT_BUTTON, NULL },
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
static const FileExtensionSpecStruct KnownExtensions[] =
|
||||||
|
{
|
||||||
|
{ ".lnx", gettext_noop("Atari Lynx ROM Image") },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
MDFNGI EmulatedLynx =
|
||||||
|
{
|
||||||
|
"lynx",
|
||||||
|
"Atari Lynx",
|
||||||
|
KnownExtensions,
|
||||||
|
MODPRIO_INTERNAL_HIGH,
|
||||||
|
NULL,
|
||||||
|
&InputInfo,
|
||||||
|
Load,
|
||||||
|
TestMagic,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
CloseGame,
|
||||||
|
SetLayerEnableMask,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
false,
|
||||||
|
StateAction,
|
||||||
|
Emulate,
|
||||||
|
SetInput,
|
||||||
|
DoSimpleCommand,
|
||||||
|
LynxSettings,
|
||||||
|
MDFN_MASTERCLOCK_FIXED(16000000),
|
||||||
|
0,
|
||||||
|
|
||||||
|
false, // Multires possible?
|
||||||
|
|
||||||
|
160, // lcm_width
|
||||||
|
102, // lcm_height
|
||||||
|
NULL, // Dummy
|
||||||
|
|
||||||
|
|
||||||
|
160, // Nominal width
|
||||||
|
102, // Nominal height
|
||||||
|
|
||||||
|
160, // Framebuffer width
|
||||||
|
102, // Framebuffer height
|
||||||
|
|
||||||
|
2, // Number of output sound channels
|
||||||
|
};
|
||||||
|
*/
|
|
@ -0,0 +1,220 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 K. Wilkins
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from
|
||||||
|
// the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Handy - An Atari Lynx Emulator //
|
||||||
|
// Copyright (c) 1996,1997 //
|
||||||
|
// K. Wilkins //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// System object header file //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// This header file provides the interface definition and inline code for //
|
||||||
|
// the system object, this object if what binds together all of the Handy //
|
||||||
|
// hardware enmulation objects, its the glue that holds the system together //
|
||||||
|
// //
|
||||||
|
// K. Wilkins //
|
||||||
|
// August 1997 //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Revision History: //
|
||||||
|
// ----------------- //
|
||||||
|
// //
|
||||||
|
// 01Aug1997 KW Document header added & class documented. //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SYSTEM_H
|
||||||
|
#define SYSTEM_H
|
||||||
|
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define HANDY_SYSTEM_FREQ 16000000
|
||||||
|
#define HANDY_TIMER_FREQ 20
|
||||||
|
|
||||||
|
#define HANDY_FILETYPE_LNX 0
|
||||||
|
#define HANDY_FILETYPE_HOMEBREW 1
|
||||||
|
#define HANDY_FILETYPE_SNAPSHOT 2
|
||||||
|
#define HANDY_FILETYPE_ILLEGAL 3
|
||||||
|
|
||||||
|
#define HANDY_SCREEN_WIDTH 160
|
||||||
|
#define HANDY_SCREEN_HEIGHT 102
|
||||||
|
//
|
||||||
|
// Define the global variable list
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifdef SYSTEM_CPP
|
||||||
|
uint32 gSuzieDoneTime = 0;
|
||||||
|
uint32 gSystemCycleCount=0;
|
||||||
|
uint32 gNextTimerEvent=0;
|
||||||
|
uint32 gCPUBootAddress=0;
|
||||||
|
uint32 gSystemIRQ=FALSE;
|
||||||
|
uint32 gSystemNMI=FALSE;
|
||||||
|
uint32 gSystemCPUSleep=FALSE;
|
||||||
|
uint32 gSystemHalt=FALSE;
|
||||||
|
#else
|
||||||
|
extern uint32 gSystemCycleCount;
|
||||||
|
extern uint32 gSuzieDoneTime;
|
||||||
|
extern uint32 gNextTimerEvent;
|
||||||
|
extern uint32 gCPUBootAddress;
|
||||||
|
extern uint32 gSystemIRQ;
|
||||||
|
extern uint32 gSystemNMI;
|
||||||
|
extern uint32 gSystemCPUSleep;
|
||||||
|
extern uint32 gSystemHalt;
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define the interfaces before we start pulling in the classes
|
||||||
|
// as many classes look for articles from the interfaces to
|
||||||
|
// allow compilation
|
||||||
|
|
||||||
|
#include "sysbase.h"
|
||||||
|
|
||||||
|
class CSystem;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Now pull in the parts that build the system
|
||||||
|
//
|
||||||
|
#include "lynxbase.h"
|
||||||
|
#include "ram.h"
|
||||||
|
#include "rom.h"
|
||||||
|
#include "memmap.h"
|
||||||
|
#include "cart.h"
|
||||||
|
#include "susie.h"
|
||||||
|
#include "mikie.h"
|
||||||
|
#include "c65c02.h"
|
||||||
|
|
||||||
|
#define TOP_START 0xfc00
|
||||||
|
#define TOP_MASK 0x03ff
|
||||||
|
#define TOP_SIZE 0x400
|
||||||
|
#define SYSTEM_SIZE 65536
|
||||||
|
|
||||||
|
class CSystem : public CSystemBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSystem(const uint8 *, uint32, const uint8*, uint32, int, int, bool) MDFN_COLD;
|
||||||
|
~CSystem() MDFN_COLD;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Reset() MDFN_COLD;
|
||||||
|
|
||||||
|
inline void Update()
|
||||||
|
{
|
||||||
|
// Only update if there is a predicted timer event
|
||||||
|
if(gSystemCycleCount>=gNextTimerEvent)
|
||||||
|
{
|
||||||
|
mMikie->Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step the processor through 1 instruction
|
||||||
|
mCpu->Update();
|
||||||
|
|
||||||
|
// If the CPU is asleep then skip to the next timer event
|
||||||
|
if(gSystemCPUSleep)
|
||||||
|
{
|
||||||
|
gSystemCycleCount=gNextTimerEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Advance(int buttons, uint32 *vbuff, int16 *sbuff, int &sbuffsize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// We MUST have separate CPU & RAM peek & poke handlers as all CPU accesses must
|
||||||
|
// go thru the address generator at $FFF9
|
||||||
|
//
|
||||||
|
// BUT, Mikie video refresh & Susie see the whole system as RAM
|
||||||
|
//
|
||||||
|
// Complete and utter wankers, its taken me 1 week to find the 2 lines
|
||||||
|
// in all the documentation that mention this fact, the mother of all
|
||||||
|
// bugs has been found and FIXED.......
|
||||||
|
|
||||||
|
// CPU
|
||||||
|
inline void Poke_CPU(uint32 addr, uint8 data) { mMemoryHandlers[addr]->Poke(addr,data);};
|
||||||
|
inline uint8 Peek_CPU(uint32 addr) { return mMemoryHandlers[addr]->Peek(addr);};
|
||||||
|
inline void PokeW_CPU(uint32 addr,uint16 data) { mMemoryHandlers[addr]->Poke(addr,data&0xff);addr++;mMemoryHandlers[addr]->Poke(addr,data>>8);};
|
||||||
|
inline uint16 PeekW_CPU(uint32 addr) {return ((mMemoryHandlers[addr]->Peek(addr))+(mMemoryHandlers[addr]->Peek(addr+1)<<8));};
|
||||||
|
|
||||||
|
// RAM
|
||||||
|
inline void Poke_RAM(uint32 addr, uint8 data) { mRam->Poke(addr,data);};
|
||||||
|
inline uint8 Peek_RAM(uint32 addr) { return mRam->Peek(addr);};
|
||||||
|
inline void PokeW_RAM(uint32 addr,uint16 data) { mRam->Poke(addr,data&0xff);addr++;mRam->Poke(addr,data>>8);};
|
||||||
|
inline uint16 PeekW_RAM(uint32 addr) {return ((mRam->Peek(addr))+(mRam->Peek(addr+1)<<8));};
|
||||||
|
|
||||||
|
// High level cart access for debug etc
|
||||||
|
inline void Poke_CART(uint32 addr, uint8 data) {mCart->Poke(addr,data);};
|
||||||
|
inline uint8 Peek_CART(uint32 addr) {return mCart->Peek(addr);};
|
||||||
|
inline void CartBank(EMMODE bank) {mCart->BankSelect(bank);};
|
||||||
|
inline uint32 CartSize() {return mCart->ObjectSize();};
|
||||||
|
|
||||||
|
// Low level cart access for Suzy, Mikey
|
||||||
|
inline void Poke_CARTB0(uint8 data) {mCart->Poke0(data);};
|
||||||
|
inline void Poke_CARTB1(uint8 data) {mCart->Poke1(data);};
|
||||||
|
inline uint8 Peek_CARTB0() {return mCart->Peek0();}
|
||||||
|
inline uint8 Peek_CARTB1() {return mCart->Peek1();}
|
||||||
|
inline void CartAddressStrobe(bool strobe) {mCart->CartAddressStrobe(strobe);};
|
||||||
|
inline void CartAddressData(bool data) {mCart->CartAddressData(data);};
|
||||||
|
|
||||||
|
// Low level CPU access
|
||||||
|
void SetRegs(C6502_REGS ®s) {mCpu->SetRegs(regs);};
|
||||||
|
void GetRegs(C6502_REGS ®s) {mCpu->GetRegs(regs);};
|
||||||
|
|
||||||
|
// Mikey system interfacing
|
||||||
|
void ComLynxCable(int status) { mMikie->ComLynxCable(status); };
|
||||||
|
void ComLynxRxData(int data) { mMikie->ComLynxRxData(data); };
|
||||||
|
void ComLynxTxCallback(void (*function)(int data,uint32 objref),uint32 objref) { mMikie->ComLynxTxCallback(function,objref); };
|
||||||
|
|
||||||
|
// Suzy system interfacing
|
||||||
|
uint32 PaintSprites() {return mSusie->PaintSprites();};
|
||||||
|
|
||||||
|
// Miscellaneous
|
||||||
|
void SetButtonData(uint32 data) {mSusie->SetButtonData(data);};
|
||||||
|
uint32 GetButtonData() {return mSusie->GetButtonData();};
|
||||||
|
void SetCycleBreakpoint(uint32 breakpoint) {mCycleCountBreakpoint=breakpoint;};
|
||||||
|
uint8* GetRamPointer() {return mRam->GetRamPointer();};
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint32 mCycleCountBreakpoint;
|
||||||
|
CLynxBase *mMemoryHandlers[SYSTEM_SIZE];
|
||||||
|
CCart *mCart;
|
||||||
|
CRom *mRom;
|
||||||
|
CMemMap *mMemMap;
|
||||||
|
CRam *mRam;
|
||||||
|
C65C02 *mCpu;
|
||||||
|
CMikie *mMikie;
|
||||||
|
CSusie *mSusie;
|
||||||
|
|
||||||
|
// old globals
|
||||||
|
uint32 gSuzieDoneTime;
|
||||||
|
uint32 gSystemCycleCount;
|
||||||
|
uint32 gNextTimerEvent;
|
||||||
|
//uint32 gCPUBootAddress;
|
||||||
|
uint32 gSystemIRQ;
|
||||||
|
uint32 gSystemNMI;
|
||||||
|
uint32 gSystemCPUSleep;
|
||||||
|
uint32 gSystemHalt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue