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" },
|
||||
{ "GEN", "Genesis" },
|
||||
{ "SMS", "Sega Master System" },
|
||||
{ "PSX", "Sony PlayStation" }
|
||||
{ "PSX", "Sony PlayStation" },
|
||||
{ "LYNX", "Atari Lynx" },
|
||||
};
|
||||
|
||||
public string TargetSystem = null;
|
||||
|
|
|
@ -331,6 +331,10 @@ namespace BizHawk.Emulation.Common
|
|||
case ".WSC":
|
||||
game.System = "WSWAN";
|
||||
break;
|
||||
|
||||
case ".LNX":
|
||||
game.System = "LYNX";
|
||||
break;
|
||||
}
|
||||
|
||||
game.Name = Path.GetFileNameWithoutExtension(fileName).Replace('_', ' ');
|
||||
|
|
|
@ -39,6 +39,9 @@ namespace BizHawk.Emulation.Common
|
|||
Option("GBA", "Bios", GBA_JDebug);
|
||||
}
|
||||
|
||||
FirmwareAndOption("e4ed47fae31693e016b081c6bda48da5b70d7ccb", "LYNX", "Boot", "lynxboot.img", "Boot Rom");
|
||||
|
||||
|
||||
//FirmwareAndOption("24F67BDEA115A2C847C8813A262502EE1607B7DF", "NDS", "Bios_Arm7", "biosnds7.rom", "ARM7 Bios");
|
||||
//FirmwareAndOption("BFAAC75F101C135E32E2AAF541DE6B1BE4C8C62D", "NDS", "Bios_Arm9", "biosnds9.rom", "ARM9 Bios");
|
||||
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.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\Input.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