Merge branch 'master' into release

This commit is contained in:
adelikat 2017-08-05 13:51:56 -05:00
commit def444cc36
69 changed files with 5212 additions and 1163 deletions

View File

@ -4,7 +4,11 @@
;2 = Super Game with extra ROM
;3 = F-18 Hornet Mapper
;4 = Double Dragon and Rampage
;5 = Rescue on Fractulus
;6 = Dev Cart
md5:0D9452D4DB4D1E1CF843F4F10605EB7D Dev Cart A78 NTSC=true;board=0
md5:31FBCF03946E804FC2D77CCA5D61C928 Mode Test A78 NTSC=true;board=0
md5:91041AADD1700A7A4076F4005F2C362F Diagnostics A78 NTSC=true;board=0
md5:89E7B20E7E0C629D00C6CA68949A216F Test Rom A78 NTSC=true;board=0
md5:4332c24e4f3bc72e7fe1b77adf66c2b7 3D Asteroids A78 NTSC=true;board=0
@ -124,7 +128,7 @@ md5:865457e0e0f48253b08f77b9e18f93b2 Pole Position II A78 PAL=true;board=0
md5:66e7230f7ef9d14db82d76b06b241bc0 Q-bert A78 NTSC=true;board=0
md5:ac03806cef2558fc795a7d5d8dba7bc0 Rampage A78 NTSC=true;board=4
md5:383ed9bd1efb9b6cb3388a777678c928 Realsports Baseball A78 NTSC=true;board=1
md5:8f7eb10ad0bd75474abf0c6c36c08486 Rescue on Fractalus A78 NTSC=true;board=0
md5:8f7eb10ad0bd75474abf0c6c36c08486 Rescue on Fractalus A78 NTSC=true;board=5
md5:43525a0405184875c2ecfd0196886a34 Rip Off A78 NTSC=true;board=0
md5:106b409c6f4c219b1a3b3d099ead3b2b Rip Off A78 PAL=true;board=0
md5:505f05e7f161f62ccd749dab3c4a204b Robot Finds Kitten A78 NTSC=true;board=0
@ -136,8 +140,8 @@ md5:1ee26fc6b06b4c9ba74931914b7e719d Scramble A78 PAL=true;board=0
md5:65fe82f419f6583a0f9a736242cb303d Scramble A78 PAL=true;board=0
md5:980c35ae9625773a450aa7ef51751c04 Scrapyard Dog A78 NTSC=true;board=1
md5:53db322c201323fe2ca8f074c0a2bf86 Scrapyard Dog A78 PAL=true;board=1
md5:b697d9c2d1b9f6cb21041286d1bbfa7f Sentinel A78 NTSC=true;board=1;Pokey=true
md5:5469b4de0608f23a5c4f98f331c9e75f Sentinel A78 PAL=true;board=1;Pokey=true
md5:b697d9c2d1b9f6cb21041286d1bbfa7f Sentinel A78 NTSC=true;board=1
md5:5469b4de0608f23a5c4f98f331c9e75f Sentinel A78 PAL=true;board=1
md5:2d643ac548c40e58c99d0fe433ba4ba0 Sirius A78 NTSC=true;board=1;RAM=8
md5:a84c1b2300fbfbf21b1c02387f613dad Space Duel A78 PAL=true;board=0
md5:771cb4609347657f63e6f0eb26036e35 Space Duel A78 NTSC=true;board=0

View File

@ -310,6 +310,7 @@ sha1:203523818A348361584CDEBE47AEB860808757FC U Jurassic Boy 2 (Sachen) NES boa
sha1:C1D82F6BE8AF524F951FC7C9D41604E59F9FE92A G Dragon Wars (USA) (Proto) NES board=MAPPER004;PAD_H=0;PAD_V=0
sha1:22FCC2D33F6715D63E04235A0A7CCB0C8DC489C5 Mortal Kombat 3 Extra 60 (Unl) [!] NES board=MK3E60;PAD_H=1;PAD_V=0
sha1:8928F7293C12EE7D3FC90BECC68AE5261802EAA6 AV Super Real Pachinko (Unl) NES board=MAPPER066;PAD_H=0;PAD_V=1
sha1:3FB806A4A5625920935880BB5C9545EF23250C33 Don Doko Don 2 (J) [a1] NES board=TAITO-TC0190FMC+PAL16R4;WRAM=0;VRAM=0
;;;;;;;;;;;;;;;;;;;-----------------------------------------------------------------------
;mmc3 homebrews that need chip specification

File diff suppressed because it is too large Load Diff

View File

@ -32,9 +32,6 @@ namespace BizHawk.Client.ApiHawk
return CoreSystem.Atari2600;
case "A78":
return CoreSystem.Atari2600;
case "A7800":
return CoreSystem.Atari7800;
case "Coleco":

View File

@ -167,7 +167,7 @@ namespace BizHawk.Client.Common
private bool HandleArchiveBinding(HawkFile file)
{
var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC", "GBA" };
var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC", "GBA", "32X" };
// try binding normal rom extensions first
if (!file.IsBound)
@ -939,10 +939,9 @@ namespace BizHawk.Client.Common
break;
case "A78":
var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv");
if (!VersionInfo.DeveloperBuild)
if (game["Pokey"] && game.OptionValue("Pokey") == "true") // A7800Hawk does not emulate Pokey so route it to Emu7800
{
nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath); // Don't expose A7800Hawk in releases yet
nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath);
}
else
{

View File

@ -542,7 +542,7 @@ namespace BizHawk.Client.Common
public bool NES_InQuickNES = true;
public bool SNES_InSnes9x = true;
public bool GBA_UsemGBA = true;
public bool A78_UseEmu7800 = true;
public bool A78_UseEmu7800 = false;
public bool SGB_UseBsnes = false;
public bool CoreForcingViaGameDB = true;
public string LibretroCore;

View File

@ -125,6 +125,7 @@ namespace BizHawk.Client.Common
["Toggle Left Difficulty"] = 'l',
["Toggle Right Difficulty"] = 'r',
["BW"] = 'b',
["Open"] = 'O',
["Close"] = 'C',

View File

@ -340,6 +340,12 @@
<Compile Include="config\A7800\A7800ControllerSettings.Designer.cs">
<DependentUpon>A7800ControllerSettings.cs</DependentUpon>
</Compile>
<Compile Include="config\A7800\A7800FilterSettings.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="config\A7800\A7800FilterSettings.Designer.cs">
<DependentUpon>A7800FilterSettings.cs</DependentUpon>
</Compile>
<Compile Include="config\INTV\IntvControllerSettings.cs">
<SubType>Form</SubType>
</Compile>
@ -1161,7 +1167,6 @@
</Compile>
<Compile Include="tools\VirtualPads\schema\A26Schema.cs" />
<Compile Include="tools\VirtualPads\schema\A78Schema.cs" />
<Compile Include="tools\VirtualPads\schema\A7800HawkSchema.cs" />
<Compile Include="tools\VirtualPads\schema\AppleIISchema.cs" />
<Compile Include="tools\VirtualPads\schema\C64Schema.cs" />
<Compile Include="tools\VirtualPads\schema\ColecoSchema.cs" />
@ -1311,6 +1316,9 @@
<EmbeddedResource Include="config\A7800\A7800ControllerSettings.resx">
<DependentUpon>A7800ControllerSettings.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="config\A7800\A7800FilterSettings.resx">
<DependentUpon>A7800FilterSettings.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="config\INTV\IntvControllerSettings.resx">
<DependentUpon>IntvControllerSettings.cs</DependentUpon>
</EmbeddedResource>

View File

@ -722,6 +722,17 @@ namespace BizHawk.Client.EmuHawk
return filterProgram;
}
public void Blank()
{
GLManager.Activate(CR_GraphicsControl);
GL.BeginScene();
GL.BindRenderTarget(null);
GL.SetClearColor(Color.Black);
GL.Clear(OpenTK.Graphics.OpenGL.ClearBufferMask.ColorBufferBit);
GL.EndScene();
presentationPanel.GraphicsControl.SwapBuffers();
}
void UpdateSourceDrawingWork(JobInfo job)
{
bool vsync = false;

View File

@ -51,11 +51,11 @@ namespace BizHawk.Client.EmuHawk
return new[]
{
".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF",
".EXE", ".PRG", ".D64", "*G64", ".CRT", ".TAP"
".EXE", ".PRG", ".D64", "*G64", ".CRT", ".TAP", ".32X"
};
}
return new[] { ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF" };
return new[] { ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", ".32X" };
}
}

View File

@ -301,7 +301,8 @@
this.AtariSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.A7800SubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.A7800ControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.GBSubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.A7800FilterSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.GBSubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.GBcoreSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.LoadGBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator28 = new System.Windows.Forms.ToolStripSeparator();
@ -2736,7 +2737,8 @@
// A7800SubMenu
//
this.A7800SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.A7800ControllerSettingsMenuItem});
this.A7800ControllerSettingsMenuItem,
this.A7800FilterSettingsMenuItem});
this.A7800SubMenu.Name = "A7800SubMenu";
this.A7800SubMenu.Size = new System.Drawing.Size(51, 19);
this.A7800SubMenu.Text = "&A7800";
@ -2746,12 +2748,19 @@
//
this.A7800ControllerSettingsMenuItem.Name = "A7800ControllerSettingsMenuItem";
this.A7800ControllerSettingsMenuItem.Size = new System.Drawing.Size(125, 22);
this.A7800ControllerSettingsMenuItem.Text = "Settings...";
this.A7800ControllerSettingsMenuItem.Click += new System.EventHandler(this.A7800SettingsToolStripMenuItem_Click);
//
// GBSubMenu
//
this.GBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.A7800ControllerSettingsMenuItem.Text = "Controller Settings";
this.A7800ControllerSettingsMenuItem.Click += new System.EventHandler(this.A7800ControllerSettingsToolStripMenuItem_Click);
//
// A7800FilterSettingsMenuItem
//
this.A7800FilterSettingsMenuItem.Name = "A7800FilterSettingsMenuItem";
this.A7800FilterSettingsMenuItem.Size = new System.Drawing.Size(125, 22);
this.A7800FilterSettingsMenuItem.Text = "Filter Settings";
this.A7800FilterSettingsMenuItem.Click += new System.EventHandler(this.A7800FilterSettingsToolStripMenuItem_Click);
//
// GBSubMenu
//
this.GBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.GBcoreSettingsToolStripMenuItem,
this.LoadGBInSGBMenuItem,
this.toolStripSeparator28,
@ -4208,6 +4217,7 @@
private System.Windows.Forms.ToolStripMenuItem GenesisSettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem AtariSettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem A7800ControllerSettingsMenuItem;
private System.Windows.Forms.ToolStripMenuItem A7800FilterSettingsMenuItem;
private System.Windows.Forms.ToolStripMenuItem MovieSettingsMenuItem;
private System.Windows.Forms.ToolStripMenuItem CoresSubMenu;
private System.Windows.Forms.ToolStripMenuItem GBInSGBMenuItem;

View File

@ -1984,13 +1984,19 @@ namespace BizHawk.Client.EmuHawk
private void A7800SubMenu_DropDownOpened(object sender, EventArgs e)
{
A7800ControllerSettingsMenuItem.Enabled = !Global.MovieSession.Movie.IsActive;
A7800FilterSettingsMenuItem.Enabled = !Global.MovieSession.Movie.IsActive;
}
private void A7800SettingsToolStripMenuItem_Click(object sender, EventArgs e)
private void A7800ControllerSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new A7800ControllerSettings().ShowDialog();
}
private void A7800FilterSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new A7800FilterSettings().ShowDialog();
}
#endregion
#region GB

View File

@ -34,6 +34,7 @@ using BizHawk.Emulation.Cores.Nintendo.SNES9X;
using BizHawk.Emulation.Cores.Consoles.SNK;
using BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive;
using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy;
using BizHawk.Emulation.Cores.Atari.A7800Hawk;
namespace BizHawk.Client.EmuHawk
{
@ -1725,8 +1726,11 @@ namespace BizHawk.Client.EmuHawk
case "A26":
AtariSubMenu.Visible = true;
break;
case "A7800":
A7800SubMenu.Visible = true;
case "A78":
if (Emulator is A7800Hawk)
{
A7800SubMenu.Visible = true;
}
break;
case "PSX":
PSXSubMenu.Visible = true;
@ -1970,14 +1974,32 @@ namespace BizHawk.Client.EmuHawk
var video = _currentVideoProvider;
Size currVideoSize = new Size(video.BufferWidth, video.BufferHeight);
Size currVirtualSize = new Size(video.VirtualWidth, video.VirtualHeight);
bool resizeFramebuffer = false;
if (currVideoSize != _lastVideoSize || currVirtualSize != _lastVirtualSize)
resizeFramebuffer = true;
bool isZero = false;
if (currVideoSize.Width == 0 || currVideoSize.Height == 0 || currVirtualSize.Width == 0 || currVirtualSize.Height == 0)
isZero = true;
//don't resize if the new size is 0 somehow; we'll wait until we have a sensible size
if(isZero)
resizeFramebuffer = false;
if(resizeFramebuffer)
{
_lastVideoSize = currVideoSize;
_lastVirtualSize = currVirtualSize;
FrameBufferResized();
}
GlobalWin.DisplayManager.UpdateSource(video);
//rendering flakes out egregiously if we have a zero size
//can we fix it later not to?
if(isZero)
GlobalWin.DisplayManager.Blank();
else
GlobalWin.DisplayManager.UpdateSource(video);
}
// sends a simulation of a plain alt key keystroke
@ -3627,6 +3649,7 @@ namespace BizHawk.Client.EmuHawk
UpdateDumpIcon();
SetMainformMovieInfo();
CurrentlyOpenRomArgs = args;
GlobalWin.DisplayManager.Blank();
Global.Rewinder.Initialize();

View File

@ -0,0 +1,121 @@
namespace BizHawk.Client.EmuHawk
{
partial class A7800FilterSettings
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(A7800FilterSettings));
this.OkBtn = new System.Windows.Forms.Button();
this.CancelBtn = new System.Windows.Forms.Button();
this.label4 = new System.Windows.Forms.Label();
this.Port1ComboBox = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// OkBtn
//
this.OkBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.OkBtn.Location = new System.Drawing.Point(170, 112);
this.OkBtn.Name = "OkBtn";
this.OkBtn.Size = new System.Drawing.Size(60, 23);
this.OkBtn.TabIndex = 3;
this.OkBtn.Text = "&OK";
this.OkBtn.UseVisualStyleBackColor = true;
this.OkBtn.Click += new System.EventHandler(this.OkBtn_Click);
//
// CancelBtn
//
this.CancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.CancelBtn.Location = new System.Drawing.Point(236, 112);
this.CancelBtn.Name = "CancelBtn";
this.CancelBtn.Size = new System.Drawing.Size(60, 23);
this.CancelBtn.TabIndex = 4;
this.CancelBtn.Text = "&Cancel";
this.CancelBtn.UseVisualStyleBackColor = true;
this.CancelBtn.Click += new System.EventHandler(this.CancelBtn_Click);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(12, 44);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(35, 13);
this.label4.TabIndex = 15;
this.label4.Text = "Filter: ";
//
// Port1ComboBox
//
this.Port1ComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.Port1ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.Port1ComboBox.FormattingEnabled = true;
this.Port1ComboBox.Location = new System.Drawing.Point(12, 60);
this.Port1ComboBox.Name = "Port1ComboBox";
this.Port1ComboBox.Size = new System.Drawing.Size(284, 21);
this.Port1ComboBox.TabIndex = 13;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 14);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(286, 13);
this.label1.TabIndex = 17;
this.label1.Text = "A7800 Filter Settings: Needed For Tower Toppler and Jinks";
//
// A7800FilterSettings
//
this.AcceptButton = this.OkBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.CancelBtn;
this.ClientSize = new System.Drawing.Size(308, 147);
this.Controls.Add(this.label1);
this.Controls.Add(this.label4);
this.Controls.Add(this.Port1ComboBox);
this.Controls.Add(this.CancelBtn);
this.Controls.Add(this.OkBtn);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "A7800FilterSettings";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Filter Settings";
this.Load += new System.EventHandler(this.A7800FilterSettings_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button OkBtn;
private System.Windows.Forms.Button CancelBtn;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.ComboBox Port1ComboBox;
private System.Windows.Forms.Label label1;
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Linq;
using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Emulation.Cores.Atari.A7800Hawk;
namespace BizHawk.Client.EmuHawk
{
public partial class A7800FilterSettings : Form
{
private A7800Hawk.A7800SyncSettings _syncSettings;
public A7800FilterSettings()
{
InitializeComponent();
}
private void A7800FilterSettings_Load(object sender, EventArgs e)
{
_syncSettings = ((A7800Hawk)Global.Emulator).GetSyncSettings().Clone();
var possibleFilters = A7800Hawk.ValidFilterTypes.Select(t => t.Key);
foreach (var val in possibleFilters)
{
Port1ComboBox.Items.Add(val);
}
Port1ComboBox.SelectedItem = _syncSettings.Filter;
}
private void OkBtn_Click(object sender, EventArgs e)
{
bool changed = _syncSettings.Filter != Port1ComboBox.SelectedItem.ToString();
if (changed)
{
_syncSettings.Filter = Port1ComboBox.SelectedItem.ToString();
GlobalWin.MainForm.PutCoreSyncSettings(_syncSettings);
}
DialogResult = DialogResult.OK;
Close();
}
private void CancelBtn_Click(object sender, EventArgs e)
{
GlobalWin.OSD.AddMessage("Filter settings aborted");
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

@ -0,0 +1,624 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAwAMDAQAAAABABoBgAAxgAAACAgEAAAAAQA6AIAAC4HAAAYGBAAAAAEAOgBAAAWCgAAEBAQAAAA
BAAoAQAA/gsAADAwAAAAAAgAqA4AACYNAAAgIAAAAAAIAKgIAADOGwAAGBgAAAAACADIBgAAdiQAABAQ
AAAAAAgAaAUAAD4rAAAwMAAAAAAgAKglAACmMAAAICAAAAAAIACoEAAATlYAABgYAAAAACAAiAkAAPZm
AAAQEAAAAAAgAGgEAAB+cAAAKAAAADAAAABgAAAAAQAEAAAAAACABAAAAAAAAAAAAAAQAAAAEAAAAAAA
AAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP//
/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAHR3AAAAAAAAAAAAAAAAAAAAAAAAAAAAdHdEcAAAAAAAAAAAAAAAAA
AAAAAAAAAHd0d3QAAAAAAAAAAAAAAAAAAAAAAAAAAEd8d3UAAAAAAAAAAAAAAAAAAAAAAAAAB3yHfHZw
AAAAAAAAAAAAAAAAAAAAAAAAd3fIyHVwAAAAAAAAAAAAAAAAAAAAAAAAfHh3jIxwAAAAAAAAAAAAAAAA
AAAAAAAHd8jIyHdgAAAAAAAAAAAAAAAAAAAAAAAHd4yHfIdAAAAAAAAAAAAAAAAAAAAAAAAHyMjIyMhQ
AAAAAAAAAAAAAAAAAAAAAAB3d3eMh4dgAAAAAAAAAAAAAAAAAAAAAAB8jIyIfIdQAAAAAAAAAAAAAAAA
AAAAAAB3h4jIiMh3AAAAAAAAAAAAAAAAAAAAAAB8jIeHeIjHAAAAAAAAAAAAAAAAAAAAAAeIiHh4eMiE
AAAAAAAAAAAAB0dHcAAAAAd8h4eIiIiHcAAAAAAAAAB0d3d3RwAAAAeIeIiIiIh3RwAAAAAAAHR3d8h3
dAAAAAfIh4iIiHiIx0cAAAAAdHh3eIeHhwAAAAeHiIiIiIiId3R3dHR0eHd4h4eHhAAAAAd4eIiIiIiH
x3d2d3eId4iIiIiIhwAAAAd4eIiI+IiIh3d3eHh3iIiIiIeHwAAAAAfIjHeIiIiIyIeHh4iIiIiIiIiI
cAAAAAeIQ0R3h3iIiMiIiIiIiIiIiIiEAAAAAAfIR3d3d0iIiIh4iIeIiIiIiHhAAAAAAAB4d3d3SHiI
h4fTiIi3iIiIeIwAAAAAAAB3h4d3eIeIiHiJiIuIiIh4jHAAAAAAAAAHyId3h3h4iIh4iIiIiIiHeAAA
AAAAAAAAB8iMiMjIiIiIh4h3aMjHAAAAAAAAAAAAAAdYyIeIiIiMjId6d4eAAAAAAAAAAAAAAAAHdsjH
eIeH6MiId3AAAAAAAAAAAAAAAIiIh4V8jIh4eIfHcAAAAAAAAAAAAACIiIh3AAAHd3h3fHcAAAAAAAAA
AAAAAAiIjHgAAAAAAHx8eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////
AAD///////8AAP///////wAA//h/////AAD/4D////8AAP/AP////wAA/8A/////AAD/gB////8AAP8A
H////wAA/wAf////AAD+AB////8AAP4AH////wAA/gAf////AAD8AB////8AAPwAH////wAA/AAP////
AAD8AA////8AAPgAD//+BwAA+AAH//ADAAD4AAP/wAMAAPgAAP8AAwAA+AAAAAADAAD4AAAAAAMAAPgA
AAAABwAA+AAAAAAHAAD4AAAAAA8AAPgAAAAAHwAA/AAAAAA/AAD8AAAAAH8AAP4AAAAA/wAA/4AAAAP/
AAD/4AAAB/8AAP/4AAAf/wAA/8AAAH//AAD8A+AD//8AAPgP/A///wAA////////AAD///////8AAP//
/////wAA////////AAD///////8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAQAAAAAAAAC
AAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/
AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdwAAAAAAAAAAAAAAAA
AAd0dAAAAAAAAAAAAAAAAAB3x3cAAAAAAAAAAAAAAAAAd3fHcAAAAAAAAAAAAAAAB3yMh3AAAAAAAAAA
AAAAAAfIeMdwAAAAAAAAAAAAAAAHjIyHQAAAAAAAAAAAAAAAfId4yHAAAAAAAAAAAAAAAHjIyIdQAAAA
AAAAAAAAAAB3iId4YAAAAAAAAAdwAAAAjIiIiIUAAAAAAHd3dAAAB4iIiHh8cAAAAHd3x4dwAAd4iIiI
h3Z3d3R3yIh4cAAHh4iIiIfHd3d4iIiIh3AAB3jHiIiIiHeHiIiIiIwAAAh3dXh4iMiIiIiIiIhwAAAA
yGd0d4iIeIi4iIiMAAAAAIeHd4iIh32IiIiIcAAAAAAAd4jIyIiIiHeHyAAAAAAAAAB3h4iIh8h3dwAA
AAAAAAAIh8fIh4eIaAAAAAAAAACIiHAAB8jIyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
////////////////////n////g////wP///8B///+Af///gH///4B///8Af///AH///wB//n8AP/A+AB
/AHgAAAB4AAAAeAAAAPgAAAH8AAAD/AAAB/8AAA//wAA//4AA//weA//////////////////////////
//8oAAAAGAAAADAAAAABAAQAAAAAACABAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAgAAAgAAAAICAAIAA
AACAAIAAgIAAAICAgADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRwAAAAAAAAAAAAB3dAAAAAAAAAAAAA
d8dwAAAAAAAAAAAAfId3AAAAAAAAAAAHeMjHAAAAAAAAAAAHyHh3AAAAAAAAAAAHh3eEAAAAAAAAAAAI
yIiHAAAAAHd2cAAIiIiIQAAAd3d4UACHiIiId3d3eHiIcACHh4iIyHeHiIiIcAAIR3d4iIiIiIiMAAAH
d3eIh3iIiIhwAAAAeMh4iIiHiMAAAAAAAHfIiMh4aAAAAAAAiIgHyIfIAAAAAAAIgAAAAIAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wD///8A////AP///wD8f/8A+H//APB/
/wDwP/8A4D//AOA//wDgP/8A4D/BAOAfAQDAAAEAwAABAOAAAwDgAAcA8AAfAPwAPwDwgP8A5/f/AP//
/wD///8A////ACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACA
AAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAd1AAAAAAAAB8cAAAAAAAB4eAAAAAAAAHyMgAAAAAAAiIhwAAAHcACI
iHcAd3hwAIz4jIeIiIAAd3eIiIiIAACHeIiIiHAAAACMeMh4AAAAiAAIgAAAAAAAAAAAAAAAAAAAAAAA
AAD//wAA//8AAP//AADj/wAA4/8AAMP/AADB/wAAwfkAAMDBAADAAQAAwAMAAMAHAADwDwAAzn8AAP//
AAD//wAAKAAAADAAAABgAAAAAQAIAAAAAAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAA9OzsAZD8/AGg8
PABtPj4AQkNDAEZIRwBWQkIAV0REAF5AQABbRkYAVklJAFxPTwBTU1MAXFJSAF5ZWQBkQEAAYUREAGZF
RQBqQkEAYEtLAGNPTwBwQUEAfUZGAHJKSgB2SUkAfU9PAGBRUQBgVFQAZlZWAGZYWABqWVkAclZWAHpU
VAB9W1oAbmJiAGtoaABtaWkAcWdnAHdnZwB8Y2MAe2pqAHJxcQB+dHQAd3l5AHl6egCGT08AiU9PAIFP
UACGU1MAjVFRAIlWVgCMV1cAg1xbAIxaWQCQUlIAlVJSAJFXVgCXVVUAmVVVAJZaWQCSXV0AlV9eAJpZ
WgCeW1sAml5eAKBZWgCgXFwAql9fAIRmZQCIZWQAhWtrAI5ragCTYmEAnGBhAJ9kYwCaZmYAk25uAJ1s
awCFdHQAiXd3AIt+fgCWd3cAmHR0AJV5eQCbfHwAo2JhAKZhYQChZWUApGVkAKplZACsZGQAqmhnAKZr
agCnbGsAqmloAKlubQCsbW0AtGZnALhsbACxb3AAv29wAKVxcACrc3IAr35+ALN0cwC5c3MAvXBxALR4
dgC1fHsAunt6AMNtbgDGb3AAw3FyAMZwcQDGdXUAyHR1AMp3eADBeXkAxnt7AMB/fgDLensANLBSAEWf
TgBBtFwAPMdnADHkdgDciiIAvoF/AISrdwDln0sA35lhAN2XfADgmmEA8LdlAO61cAArWPIALWT+AEh5
+gDOf4AAfoCAAHiA1ABZv9wAZrnUAGK+2ABxnv4Ad6P/ADPX/QBw0OcAW+D7AIKEgwCPgoIAjI2NAJuC
ggCUiIgAmYqKAJGSkgCjhIQAqoKCAKKLiwC+hIMAsoqKALaSgQCum5sAsZubALqqlQCdgr4Ar6ytALGh
oAC6pKQAwoSDAMyBggDGiIYAyYiHAMWMigDMjIoA0ISFANKHiADUjIwA2Y6NAMCUjQDIk44A0JCPANaP
kADHlZQAzpSSAMScmwDUkpIA2ZSVANWYlgDampcA2ZeYANWcnADam5sA4p2cAMChjwDeoJ4A5aCFAOaj
jQDlpJoA2p6hAMOkowDOoaEAy62tANegoADdoqEA2aGpANGsrwDdq6kAwbG4ANGysQDdtLQA2ri3AOGk
owDjqKYA66ylAOGnqADjq6oA6a2rAOOwrwDssK4A5K+wAOaztADttLIA57i2AO24tgDmurgA6rq6APC1
swDyuLYA9Ly5APi+uwD1wL0A+cC9AKKMwACkk8QAqprMALSayACptsEAlaDkAOy/wACRxtQAgOv9AJnr
9wDEwsoA5sbGAOzCwgDuyMcA7MzMAPPEwgDxy8oA9dPTAPja2gAAAAAAAAAAAP///wAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAoIJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAACYXODs4BCUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
KTNDQ0M7OAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALllbYmJZQBcAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYYWNwcHBwWy8mAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFLanBwcHBwYz0eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABpqcHBwcHBwZVkUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl11w
cHBwcHBwcGcSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIXdwcHBwcHBwcGkSAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXBwcHBwcHBwd2wYAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAACXbnBwdXB5dXl0eW4hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAid3R5eXl5eXl5q6wzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9eXV5
i7CxsbGxsblLKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABndYuwsbm8uby5vMFnHgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJt3q7G3vMHB1cLBwdWuEgAAAAAAAAAAAAAAAAAA
AAAAAAAeEhMSCiUAAAAAAAAAAEexsbm/1dXZ2dnZ1da5ZgwAAAAAAAAAAAAAAAAAAAAjEjNZaW5qXRMl
AAAAAAAAADW5s7/V2N7i4uLi3dzZrQQPAAAAAAAAAAAAAAAAHxhZbm5uaWltd6ASAAAAAAAAAEmzvMLZ
3uP29/fw4uTkuUAWCy0AAAAAAAAAAB4YYXd3gG13vbm5vb8zAAAAAAAAAE6xwdXd4/b6+/r38OTl1Vlc
OAMIFAweFBQSM2mtrYB3vdXT0NXExNU1AAAAAAAAAE65wtXe8Pr7/Pz79+fn1WphZ25pXV1mbHetrXd3
tdXT4vXw49nZ3NYgAAAAAAAAAEu3wdje9vv7/Pz79+fn34B3d2xtoHeud66uudXT4vD39/Dj49zk5G0A
AAAAAAAAAD2xwcwoH0/L/Pukyenp5K27u7m5uczM0Nve4vb3+vr56OPl5eXl1igAAAAAAAAAADWxwQgB
BQYNmveZK/Dp6cG/wcTV2eP3+vr6+/r6+ejm5ufn5+nkIgAAAAAAAAAAAJmruR4sjC2WLFCdDd3p6dXW
1tXI3vn67pCO9Ojp6efo5+fm59wiAAAAAAAAAAAAAABLsZ0FmC0qKgHMRcjp6dzc1Y2KiO3RlfKTj+np
5ubm5eXk1SIAAAAAAAAAAAAAAACdab/Lp5aWnEfV1cHm6ebk6pGSiabZ8fOU0uXl5eTk3NyuRQAAAAAA
AAAAAAAAAAAAn0ux0KFTaMHBv7nC6efp3Ovv7OTm3OPl3Nzc3NfW1U6fAAAAAAAAAAAAAAAAAAAAAABF
Wa25t7yxs7Gw5+fn5Obk18XG3NyBfHvD1cSgNQAAAAAAAAAAAAAAAAAAAAAAAAAAAFUzarGwsHl5sefn
39zEgoZ/hL19fnqirj2jAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATj09ZXV0cLzn3NXChYeDub+1pbQ9
VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0rXj+rpInTBDcHCz5NW/ucG5u7GAM1QAAAAAAAAAAAAAAAAA
AAAAAAAAAADLytDi9tOemQAAAAAAUy9EecLEsa1uPTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPj11Mme
VakAAAAAAAAAAAAATS84M0akAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////
AAD///////8AAP///////wAA//h/////AAD/4D////8AAP/AP////wAA/8A/////AAD/gB////8AAP8A
H////wAA/wAf////AAD+AB////8AAP4AH////wAA/gAf////AAD8AB////8AAPwAH////wAA/AAP////
AAD8AA////8AAPgAD//+BwAA+AAH//ADAAD4AAP/wAMAAPgAAP8AAwAA+AAAAAADAAD4AAAAAAMAAPgA
AAAABwAA+AAAAAAHAAD4AAAAAA8AAPgAAAAAHwAA/AAAAAA/AAD8AAAAAH8AAP4AAAAA/wAA/4AAAAP/
AAD/4AAAB/8AAP/4AAAf/wAA/8AAAH//AAD8A+AD//8AAPgP/A///wAA////////AAD///////8AAP//
/////wAA////////AAD///////8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAE
AAAAAAAAAAAAAAABAAAAAQAAAAAAAFFNTQBRUlIAU1RUAGJHRwBiT08Aa0lIAGJTUwBrVlYAYllZAGZc
XABpWloAb1xbAHNTUwB7V1YAc1hXAHFbWwBkZWUAaWFhAG5kZABpamkAcGFhAHlubgB2cHAAf3V1AH55
eQB8fX0AgUpKAI1PTwCLWFcAhlhYAI9ZWQCKXFsAm1ZWAJJZWQCWWVgAmlpbAJtcWwCiXFwAl2BfAIBg
YACAZ2YAgG9vAI9oaACWZWQAmGBhAJ5kZACcaWoAmm9vAIV0dACNcHAAiXZ2AIB8fACac3IAm3V0AJ51
dQCZfHwAnHx8AKNmZgCnZmYAqmJiAK5jYwCvb24AtWVmALBtbgC5bW0AvmxtAKx+fQCxcnIAtHBwALZz
dACydXQAtnd2ALlwcAC5dnYAt3p5ALh5eAC8fHsAun18ALx+fQDGb3AAxnBxAMdzdADAd3YAyHJzAMlz
dADJdXYAynd4AMd/fwDMe3wAzXx9AHunbwBhvHIAYsN4ANuLOwC2hn4A4Zt5APC3ZABte9sAX47+AHWM
5QAl0foAY+P8AIeDgwCFhoYAioSEAJOIiACWi4sAmpKRAKGCgQCmhYUAqYGBAKuDhACniooApYyMAKiO
jQCyhYMAvoWEALeNjQCrj5AAr5eXALSVlAC9lJMAmbCEAK6RugDBgYAAwoSCAMWDhADChoQAxYeFAM6A
gQDFiIYAxoqIAMqIiQDMi4oAy4yKAMiPjQDPj44A0ISFANKJigDUi4wA04+NANWNjgDKkY8A0JCOANud
iQDWj5AAzJSTAM2XlgDGm5oA1pGSANOUkgDVl5EA1pOUANiVlgDYmJUA2ZeYANKenADbmpsA3pmYANuc
mgDbn5wA1aacAN6gngDqqZoA3Z+gAMyjowDCra0AxqysAMqpqQDboaAA3qKiAN6logDbp6UA3aWkANer
qgDWsbMA0rW0ANe0tADfs7IA4aSiAOGlpQDkp6UA46imAOWopgDsraIA6qimAOGoqADhrqwA6a2rAOqv
rADpsK4A7LGuAOGzswDlsbEA7bKxAO+1sgDotrYA5rm3AO+4twDot7sA6bq5AOu9uwDrv70A8bazAPG2
tADxuLUA9Lm2APC9uwD2vboA9L+9APi+uwD4v7wA8sC+APXAvgD5wL0AkILJAKqXzACsu8cAqr/LALLV
3QDawMIA48XFAOvDwQDswMAA7cTDAO/ExQDgxsgA8cbEAPTGxADwyskA9MvJAPLNzQD21dYA+NjZAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAMEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqHCEcBQAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAayU9PSYbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdQlBSQiJpAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAM0pSUlJQPRcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnUlJSUlJGFQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAFJSUlJSUkoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzUlJSWVJZfxAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAC5XWYqKioqGDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASoqMkpqa
mqAsAAAAAAAAAAAAAAAAAABoNAAAAAAAAACMjJyuvLy2toYHAAAAAAAAAAAAABcOIDouBgAAAAAAc4yc
tsHKysPAriIKAAAAAAAAABYgRk1LTX+DEAAAAABukqXB4ejo4dHPQCIEChcXEwggTXV/k66unKMpAAAA
AG6Srsro6ero0dN/Rk1NRk2Dg4STrsbh4cHAt2sAAAAAbpKuOXPe6ajW15KGg4OGk528yuHo5eHPz882
AAAAAAB4jCkDAxSoMabXt5yjt8ro3ePo5dbT09HTdAAAAAAAAABGcBFoGgFwdtfDwHxi2dpmZcrX09HP
z0MAAAAAAAAAAHh/qWwaOa6cz9PNZGPYsdzbzc3DwLk2AAAAAAAAAAAAAAAvhpKakoyg19HNyKS5wHtb
orZ/cwAAAAAAAAAAAAAAAAAANkaKWVm5zb1gYV6cXVxfNgAAAAAAAAAAAAAAAAAAALGvlTIuP1K5tqCR
l4xfLwAAAAAAAAAAAAAAAAAAsbPBenkAAAAAcCVYjE0scwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////////////////+f///+D////A////wH
///4B///+Af///gH///wB///8Af///AH/+fwA/8D4AH8AeAAAAHgAAAB4AAAA+AAAAfwAAAP8AAAH/wA
AD//AAD//gAD//B4D////////////////////////////ygAAAAYAAAAMAAAAAEACAAAAAAAQAIAAAAA
AAAAAAAAAAEAAAABAAAAAAAAWlJSAHBJSQB1SEgAe1dXAHdYWAB5WlkAel1dAGBiYgB1bGwAfWtrAHh2
dgB9fn4Ag01NAIRXVwCIV1cAhV9eAItbWgCgX14ApV1dAJhgXwCNYGAAnWtqAJhtbQCCdnYAh3x8AI15
eACeensAqGBgAKhoZwCga2oArGpqALNqagCzb28AtG1tALltbQCxb3AApnVzAKlzcwCqdHMApnp6AKd+
fgCpensAq3x7ALZ3dgC8dHQAvH59AMZvcADGcHEAxXN0AMhycwDJdncAynh5AMx5egDNfn8Ajo1wAOek
VgDGgH8A4p53AEZ2+gB8u4AAd8PaAIuEhACOh4cAjo6OAJ+DggCejo4Ao4SEAKSIiACsi4sAqo2MAK6P
jgC+gYAAvoaGAL+KiACskJAAtJeXALWenQC5np4At6iOAKmyjgC9nroAwYSDAMaGhADOhoYAxomHAMiK
iQDJjYwA0oeIANOOjwDUjY0A2ZiPANaPkADGkZEAx5eXAMySkADGnZwA1ZOSANeTlADWl5YA2JSVANGZ
mADan50A3J6dAOCcmwDVoJ8A7K2fAMOtrQDXo6IA3aCgAN+kpADVq6oA3ay3AMu0tADPtrYA3L+/AOCi
oQDhpqUA5KelAOinpgDlq6gA46usAOOvrQDqrqwA7LGuAOayswDjtrQA5re1AOqysQDts7EA57y6AO+8
ugDrvL0A8LOwAPC1sgDwtrQA87q3APS6twD2vboA8b69APi/vAD2wb4A+cC9AJmTzwDHqMMAu8PMAIHf
8QDByNAA7cLCAO3FwwDvxsQA5cjIAOzOzgDwxcQA9cbEAPPP0AD10tIAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BQMJAAAAAAAAAAAAAAAAAAAAAAAAAAAPHBMNAAAAAAAAAAAAAAAAAAAAAAAAABojLy8TAAAAAAAAAAAA
AAAAAAAAAAAAAB0wMDAiPgAAAAAAAAAAAAAAAAAAAAAAQjAwMDAtGAAAAAAAAAAAAAAAAAAAAAAAFzIy
NTU5CgAAAAAAAAAAAAAAAAAAAAAAIjZYWFxcBwAAAAAAAAAAAAAAAAAAAAAANlxtdW11JQAAAAAAAAAA
PgcRDgkAAAAAXG1/lISAZgMAAAAAABkVLC5SVhcAAABNY3WWnJuLfB8UBAcQHkhWaX91dSsAAABNY2BM
mJeCiVJSVl9laX+WloSJgEIAAAAAXAEIC0tGjnR0dJaRk5qNjIyJQwAAAAAAJkNADBtdjIaPO1GSPYuJ
hnVEAAAAAAAAAClISWRcd4xwkGp8UE90VwAAAAAAAAAAAAAAKSQ1NYZ7OjhbPDdGAAAAAAAAAAAAAHNv
YGsAKyJoXFYmRwAAAAAAAAAAAAAAcnIAAAAAAAAATgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP//
/wD///8A////APx//wD4f/8A8H//APA//wDgP/8A4D//AOA//wDgP8EA4B8BAMAAAQDAAAEA4AADAOAA
BwDwAB8A/AA/APCA/wDn9/8A////AP///wD///8AKAAAABAAAAAgAAAAAQAIAAAAAAAAAQAAAAAAAAAA
AAAAAQAAAAEAAAAAAABjZGQAdmRjAHtpaQB/eHgAgU9PAKBaWgCFbm0AlWtqAKptbgCwZ2cAsGhoAKxw
cACteHkAvnJyAMZvcADGcHEAy3l5AMx9fgCFmXQAwIB/ANeUfQDhoX8AlIqJAJWMjACYiIgAoIaGAK2K
igCxh4cAvoGAALKKigC4iYgAuJWVAL2cnACss50AuqKhAL+mpgDLgoIAxImHAMeNjADLkI8AxpWTANCS
kQDYlZUA1J6dANqZmgDdnp4A1J+oAMaiogDOr68AzLKyANi5uADhpaIA4qypAOWtqADrrqsA4bKwAOay
sgDtuLYA57++AOy4uADxtLIA8be0APa9ugDswL4A9sG+ALCcxwC5ncIA06zBALnH0QC2ytQA7sPDAPLS
0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAZBgUAAAAAAAAAAAAAAAAACw8KAAAAAAAAAAAAAAAAGhAQDgAAAAAAAAAAAAAAAAkRESUYAAAA
AAAAAAAAAAAlKy4uBwAAAAAAAAcDAAAAKzlHPCYCAAAYCB0oKgAAAC0wSDs0FB0nLDlAOiwAAAANAQQb
Pi9DRkVBPzUAAAAAJB4cKz5EQjMiNSkAAAAAAAAAHwwRNxYVEyQAAAAAAAAxMgAAACEgAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAD//wAA4/8AAOP/AADD/wAAwf8AAMH5
AADAwQAAwAEAAMADAADABwAA8A8AAM5/AAD//wAA//8AACgAAAAwAAAAYAAAAAEAIAAAAAAAgCUAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAkAAAAJAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAUAAAAOAEBAVUAAABUAAAANQAAABAAAAABAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAkFBSUvGRl5TCkpwlYuLtxDJCTQFw0NmQAA
AEkAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGAwMKE8rK6V6RET2klJR/5ZS
U/+OT0//ZDc38B0QEJoAAAAyAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYDAwYVzAwoopP
T/ygXVz/oFtb/55ZWf+bWFf/k1NT/1UvL9wGAwNcAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AARNKipxhk5O+adkY/+uZWX/tWdo/7VmZ/+qYWH/nltb/3hERPcfERGCAAAAFgAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAADEZGS1zQ0LXqGdm/7ptbf/Fb3D/x3Bx/8hwcf/BbW7/q2Vl/4hPT/82HR2gAAAAIAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAB1gxMYyYXl3/vXFx/8Zwcf/HcHH/x3Bx/8dwcf/HcHH/uG1t/5NY
V/9EJia2AAAAKQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPB8fNH1MS+K4cnH/x3Fy/8dwcf/HcHH/x3Bx/8dw
cf/HcHH/wHBx/51gX/9PLCzGAAAAMwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAMAAAAAAAAAAAAAAAAAAAAALhAQFIZXVs/RjIz/1Y2O/9qYmP/eoaL/46qr/+aysv/ot7f/6rm5/+m4
uf/otbX/5q+v/+uvrf/jqab/wYeF/28/P/QhEhKvAAAAXwAAACgAAAANAAAABQAAAAMAAAACAAAAAwAA
AAUAAAAKAAAAFQAAADAdDg9oSSkptHZHRu2dYmL+t3Z1/758e/+6enn/tnh3/7d5eP+8fn3/w4SD/7Z6
ef9eODfbBgICTgAAAAgAAAAAAAAAAAAAAAAAAAAAPhwcJJVjYuPXkZH/2JOU/92fn//iqqr/57O0/+u8
vP/uwsL/78XG/+/Exf/twMD/67i4/+60sv/wtrP/zZKQ/5taWv9xQED2MRsaxAgEBIcAAABaAAAAQQAA
ADcAAAA2AAAAOwAAAEUEAgJZHA4OfUcnJ7l5SkntqGxr/8CAfv/DgoH/vH59/7p+ff/DiIb/zZGP/9GT
kf/UlJP/1peV/9eZl/+GVlbuGQsLVwAAAAcAAAAAAAAAAAAAAAAAAAAARiIiLZ9rauvZk5P/2peY/+Ck
pP/lsLD/6ru7/+/Fxf/yzMz/9NDQ//PPz//xycr/7sDA//K5tv/1u7j/36Kg/6dmZf+mZWX/j1ZW/WM6
OutDJSXQNBwcvDAaGrQ0HBy1PiIivUwsLMtkPDzfh1VU9a1xcP/EhIP/xIWE/7+Cgf/Ch4b/zZST/9mk
ov/grq3/4a6t/96lo//eoJ7/36Kg/+Cjof+IWVjnGwwMQwAAAAIAAAAAAAAAAAAAAAAAAAAARyQkL6Br
auzZk5P/25qb/+GnqP/ntLT/7cDA//LLy//209T/+NjY//fX1//00ND/8cbG//W9u//4vrz/46ak/7d0
c/+vb27/s3Jy/7d2df+ucXD/pWpp/6Npaf+nbWz/sHVz/7p9fP/EhYT/yImI/8WIhv/DiIb/ypGP/9eg
n//hr63/57q5/+rCwP/rwsD/6bq4/+evrf/nq6n/6q6r/9qgnv9wRkbDBwAAHgAAAAAAAAAAAAAAAAAA
AAAAAAAASCQkLZ1nZuvYkpP/25uc/+Opqv/qtrf/7cHB//TOzv/52Nj/+tzc//na2v/xz9D/8MfH//fA
vv/6wb7/6a6r/8OBgP/DgoD/vX58/7h7ev+8fn3/woOC/8aHhv/HiYj/xoqJ/8aLif/Ijoz/zZST/9eg
nv/hrav/6Lm3/+zCwf/uyMf/78nH/+/Dwf/uvLr/7ba0/+60sf/vtLL/8ri1/7J+fflMKSltAAAABAAA
AAAAAAAAAAAAAAAAAAAAAAAAQyEhI5JcXOPWj5D/3Juc/8qVlf+BZmb/bl5e/4l4eP/AqKj/8tPT//LO
zv+5p6b/w6qq//fBv//7wr//8LWy/86Ojf/Ojoz/0ZGP/9GSkP/OkY//zpOR/9GamP/VoJ//2qel/+Gv
rf/nt7X/6727/+3Dwf/wycf/8czL//LLyf/yxsT/8cC+//G7uf/yubf/87m3//S7uP/4vrv/1J6c/3JH
RrAdCgsWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANRcXEYJNTcvPiIn/15aW/2VNTf85Ojr/Q0VF/0JF
RP9dXFz/n5GR/+S/v/+bh4f/hXp6/+25uP/7wr//9bu4/9qcmv/Zmpj/252b/96gnf/ipKH/5q+s/+u+
vP/vycf/8srI/+3Hxv/wysj/9c7M//TNy//0ysj/9MbE//TBv//1vrz/9r26//e9u//4vrv/+L+8//vB
vv/hqqf/g1ZVzDwcHC4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAW4+Ppq/env/05OT/2ZX
V/9rbm7/fX9//3l6ev99f3//cHJy/5F9ff+ff3//XFhY/9eop//8wr//+L+8/+Wppv/ipaP/5qil/96i
pP/Kmaz/1qi1//LGxP/tyMf/qb3J/23E3P9kw9//vMTN//jDwP/3wb//+MC9//i/vf/5v73/+b+8//i/
vP/3vrv/+L68/92mo/+IWlnRRSMjOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFcv
L0mbX1/y15GS/6GAgP9XV1b/iYuL/4CBgf98fX3/cnR0/1dPT/++j4//km9w/9Sfnv/6wL3/+cC9/+6z
sP/ssK3/0Z+u/4OH1P9YffD/QGPs/7KYyv/Ct7z/Ytrz/3Ts//8s2f//cbvU//m+u//4v7z/+L67//e9
uv/1vLn/9Lq3//O5tv/zuLX/0puZ/4RVVctGIyM4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAADIXFwdrPDySq2ts/diZmf/ApKT/sKur/4CBgP95enr/iYiI/49zdP/do6P/36Ch/96e
nv/zuLX/+sK///W7uP/1ubT/qZC//2qY+/9tnf//MGT6/56FxP/esK//nMbS/57n8/9+z+T/ybG3//a6
t//zubb/8re0//C1s//utLH/7rKw/+qvrP++iIb9dklJtkMgISoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHIyMSazw8kZ5hYvXNjI3/2aSk/7OMjP+bd3f/sIKC/9KV
lv/cnJz/2peY/9aRkf/koqL/+sG+//nAvf/5v7z/4amw/6qZx/+aouP/qpvP/+mxtv/2urj/6rGv/+S6
u//ptrX/466n/+Ovqf/ssK7/6q6s/+isqv/oq6n/2J2b/6JubfFoPT2NOxoaFwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBoaCFowMFd7SEjAomZm9sWC
gv/XkZL/25SV/9iSk//Wj5D/1IyN/9KHiP/UiIj/8bOx//rCv//3vbv/9ru4//O3s//xuLX/7q6e/+ej
hf/npIn/7bCp/+Otp/+KsX3/ULdm/1WjWv+7oYz/5KWk/9uenP+4gH79glJRzVYuLlQgCAkGAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAA8HBwQVy4uS3FBQaCPV1fjsG5v/cmAgf/ShYb/0YKD/85+f//LeXr/2I2M//e8uf/1vLn/7rOx/+2y
sP/lpJX/5qFY/+6xXP/djS3/35h9/86gl/9SwW7/Nd90/0WxXP+vlH//wYSE/49cW+VlOTmBQR4eHAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGk7OhqIWFd8oG5u8J5qav+eX2D/tmts/8Z0df/KdHX/yXJz/92T
k//3vLn/7LGu/+Snpf/dm5L/4Z1q/+61dP/fmmX/15WM/9eYlv/Bm43/r6uR/6uNgP+WYWDtbkBAnUwn
JzQVAQECAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiFJSBnhC
QgpqNDQJWSUlB08dHQdfKisKfENDFJJWViinbGtRvYOCjtOcm8/pt7X157y6/7eOjfhxRUW7aTk5m4RK
StehWlr6uGdo/8Zwcf/dkpH/8bSx/+OnpP/YmZj/1ZWT/9ealP/Vl5X/0JCP/8eIhv+zdnb/lFtc6nA/
QKRSKio/JQwNBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADTn6AB2qioDMuUlCHBhYU8voCAWcCBgXTEhoaLzZGQqdeensngrKvn47Sz/NOop/+yiIfyi2Bgs2k+
PlZXKysPAAAAAUYlJRxcMTFYcj4+pYpMTeWmXF3+xnl5/9+Zl//dnJr/z46M/8KCgf+vc3L/ll9e831L
S8hlOTl/TigoMy0REQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABzQUIDnmprDriGhifHlpZMzp6eeNCgoZ7On5+2yJqaybuPj9WnfHzVj2RkunVJ
SYNbLy8/PRQUCgAAAAAAAAAAAAAAAAAAAAAAAAAAKRUVBU0pKSphNDRtd0BAsotNTd2ZW1vrkVlY4HtJ
Sb5lOTmCUysrQTsbGxEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWCwsA2Y4OA5xQkImdkhIRHhKSll0R0dibUBAWWI2
NkNUKCgoOhISDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMhkZB0km
Jh5LJiYsRSEhITATFAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP//
/////wAA////////AAD///////8AAP///////wAA////////AAD/+H////8AAP/gH////wAA/8Af////
AAD/gA////8AAP+AD////wAA/wAP////AAD/AA////8AAP4AB////wAA/gAH////AAD8AAf///8AAPwA
B////wAA/AAH////AAD8AAf///8AAPgAB////wAA+AAH//4HAAD4AAP/8AEAAPgAAf/AAQAA8AAA/wAA
AADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAEAAPAAAAAAAQAA8AAAAAADAADwAAAAAAcAAPAA
AAAADwAA+AAAAAAfAAD4AAAAAD8AAPwAAAAAfwAA/gAAAAD/AAD/gAAAA/8AAP/gAAAH/wAAgAAAAB//
AAAAAAAAf/8AAAAD4AP//wAAgB/8H///AAD///////8AAP///////wAA////////AAD///////8AAP//
/////wAA////////AAAoAAAAIAAAAEAAAAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAYAAAAZAAAAGQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAARCQkYOh8fb0ooKK80HByiCQUFTAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAIhERFmA2Np2ITUz3lVNT/4dLS/5IKCi9AAAALwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAANjODiBllhY+61kZP+vY2P/pV5e/3xHRvEhEhJfAAAAAgAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAASSgoN41VVeS6bW3/xW9w/8dwcf+9bG3/klZW/jogIIEAAAAGAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ1RkWcs2xs/8dxcv/HcHH/x3Bx/8Zwcf+iYWH/SSkpmAAA
AAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUC0tMZtgX+fGcnP/x3Bx/8dwcf/HcHH/x3Fy/61q
av9UMTGqAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxRER1tm9v/8hxcv/HcHH/x3Bx/8dw
cf/HcnP/tnRz/185OboAAAAZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAACIxXV7TEdHT/yHJz/8l1
dv/Kd3j/ynd4/8p4eP/Bf37/bURDywAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABNKysjo2Zm4Mt4
ef/NfH3/z4GC/9GFhf/RhYb/0YWF/82Mi/9+UVHeCAICOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAJAAAACwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAGc+
Pkm1c3P30IGC/9OJiv/XkZL/2ZaW/9mWl//YlJX/2JmY/5hnZfMeEBBrAAAABwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA0FAgItHhAQWzAbG4IqFxeHDQcHWwAAABkAAAAAAAAAAAAA
AAAAAAAAek1MdMN/f//VjI3/2piZ/9+io//hqKn/4qmp/+Clpf/jpqT/wImH/04xMLwAAAA6AAAABQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABEbDg5GRygokW5CQs+MVlbxnGJh/JdfXvxnPz7hHA8PbgAA
AAwAAAAAAAAAAAAAAACMW1qbz4qK/9qXl//gpqb/5rKz/+q6u//rvLz/6La2/+qxr//epKL/j1lZ+DUc
HLACAQFPAAAAHQAAAA8AAAAPAAAAEwAAACIbDg5MVDExnYZUU+SpbWz+uXl4/7x+fP/AgoD/xoeF/72A
f/9fOzu1AAAAHAAAAAAAAAAAAAAABJhkZK/VkZH/3Z+g/+axsf/twMD/8svL//LNzf/vxcX/8Lq4/+6z
sf+1dHP/j1VU+144N9g7IiKqMhwclDcfH5RGKSmiYTw7v4tZWOiydXT+woOC/8aKiP/Ol5X/2aWj/9ui
of/cnpz/2pyb/35TUrgAAAAVAAAAAAAAAAAAAAAFmmVkstaTk//hpaX/7Lm6//TLy//419f/+NnZ//TP
z//1wb//9Lq3/8aGhP+1dHP/s3Rz/6xwb/+pb27+rnNy/7Z7ev/BhIL/yY2L/8+WlP/apqT/5be2/+vB
v//rvrz/6bKw/+uvrf/Um5n/bUVEgAAAAAMAAAAAAAAAAAAAAAOTXV2q1ZGR/9CYmP+dfX7/o4yM/9e8
vP/z0tL/zLOz/+u8u//5v7z/1peV/8uLif/Ki4r/yoyL/86Ukv/TnJv/2qSi/+Gtq//nuLb/7cPB//DJ
x//xxsT/8b+9//G6t//zubf/77az/6d1dM89Hx8lAAAAAAAAAAAAAAAAAAAAAIJOTojNiIn/jGlp/01O
Tv9UVlb/dnNz/7uhof+Pfn7/xJ+e//zCv//lqKb/3J2b/+Chnv/hpaT/7Ly5/+vHxv/MxMn/0MjN//LK
yf/1x8X/9sLA//a/vP/3vrv/+L+8//S7uP+5hoXhYTo5RwAAAAAAAAAAAAAAAAAAAAAAAAAAaTs7RrVz
dPKmfn7/cXJx/4SGhv97fX3/b2Zm/516ev+7kJD/+sG+//C2s//lqqr/rpbA/3aB2/+ql83/tMHK/2jc
9P9OzOz/2r3B//q/vP/3vrv/9ry6//a8uf/ss7D/tYGA32c+Pk0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAvEhIHg01Njbp9fvrCn5//nI+P/4R7ev+fgID/2Jyd/9ybnP/ytrT/+b+8/+ewtf+Mld3/ZI36/5eI
zv/Ttrn/sNLc/6/Czv/stLT/8re0/++0sf/tsq//2qCe/6Rxb8phODg+AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABCIB8MeUZGbqRpata8gYH8x4mJ/9eTk//YkpP/04qL/+Cbmv/5wL3/9726/+Sw
t//Zrrn/56qY/+2smf/lr6n/nLWJ/4Gtdf/Pppn/3qGf/7yEg/KJWViYTyoqIAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQh0dGXJAQGOXXl7NtnR1/8V7fP/MfH3/znt8/+il
o//0urj/7LCu/+Whg//rq13/35VX/9Kek/9yvXz/ZbNv/6iCdfqYY2O/aj4+TCUJCgcAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACcamsBjFRVB4FERAh9PT0JjU1ND6VnZx+/hINF0JqZiNOjoty0iIf2hFBQw5lX
V8+wY2P4xXR0/+aioP/oq6j/2pqT/92fif/Vlor/yYqJ/7N8efiVZmPGdERFYkEfHxIAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAALiFhgXFkJEdx5CQSMqSknbNlZWbz5uaws2cnOXBlJPnqH18r4dc
XFFULy8OSCUlFm07O0+FSUmeoV1d3sF9fPrGhoX/snZ295xkZNiFUlKbbD4+T0UdHxIAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc0JDA5FgYRKdbm46onR0Zp9ycnuWampzhFlZVmY6
OikvDAwHAAAAAAAAAAAAAAAAAAAAAB0ODgRULCwhbjo7UXhERGVrPDxHTCYmGxAAAQMAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP//////////////////////D////gf///wH///4A///+AP///AD///wA///8AP//+AD
///gA//D4AH+AeAA+ADgAAAAwAAAAMAAAADAAAAB4AAAA+AAAAfgAAAP8AAAH/wAAD8AAAD/AAAD/wB4
D//H////////////////////KAAAABgAAAAwAAAAAQAgAAAAAABgCQAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAABMAAAAtAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAgIO1cwMM1qOjrsHhAQmwAA
ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAATCgogfUhI6ahgYP6lXV3+f0hI9wIBAT0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsGBgFPLy6kuW1t/sZv
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
</value>
</data>
</root>

View File

@ -602,7 +602,7 @@
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(359, 27);
this.label8.TabIndex = 20;
this.label8.Text = " • Best compatibility\r\n • May have trouble with OpenGL-based cores (Saturn,N64)\r\n" +
this.label8.Text = " • Best compatibility\r\n • May have trouble with OpenGL-based cores (N64)\r\n" +
"";
//
// rbD3D9

View File

@ -2808,7 +2808,7 @@ namespace BizHawk.Client.EmuHawk
}
if (strCompare != "00")
{
Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber), int.Parse(strCompare, NumberStyles.HexNumber)));
Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber), int.Parse(strCompare, NumberStyles.HexNumber), true, Cheat.CompareType.Equal));
}
//Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber), )
}

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using NLua;
using BizHawk.Client.Common;
@ -246,11 +248,11 @@ namespace BizHawk.Client.EmuHawk
if (Engaged())
{
var selection = Tastudio.GetSelection();
var selection = Tastudio.GetSelection().ToList();
foreach (var row in selection)
for (int i = 0; i < selection.Count; i++)
{
table[row] = row;
table[i] = selection[i];
}
}
@ -288,5 +290,74 @@ namespace BizHawk.Client.EmuHawk
}
}
}
public class TastudioBranchInfo
{
public string Id { get; set; }
public int Frame { get; set; }
public string Text { get; set; }
}
[LuaMethod("getbranches", "Returns a list of the current tastudio branches. Each entry will have the Id, Frame, and Text properties of the branch")]
public LuaTable GetBranches()
{
var table = Lua.NewTable();
if (Engaged())
{
var branches = Tastudio.CurrentTasMovie.Branches.Select(b => new
{
Id = b.UniqueIdentifier.ToString(),
Frame = b.Frame,
Text = b.UserText
})
.ToList();
for (int i = 0; i < branches.Count; i++)
{
table[i] = branches[i];
}
}
return table;
}
[LuaMethod("getbranchinput", "Gets the controller state of the given frame with the given branch identifier")]
public LuaTable GetBranchInput(string branchId, int frame)
{
var table = Lua.NewTable();
if (Engaged())
{
if (Tastudio.CurrentTasMovie.Branches.Any(b => b.UniqueIdentifier.ToString() == branchId))
{
var branch = Tastudio.CurrentTasMovie.Branches.First(b => b.UniqueIdentifier.ToString() == branchId);
if (frame < branch.InputLog.Count)
{
var input = branch.InputLog[frame];
var adapter = new Bk2ControllerAdapter
{
Definition = Global.MovieSession.MovieControllerAdapter.Definition
};
adapter.SetControllersAsMnemonic(input);
foreach (var button in adapter.Definition.BoolButtons)
{
table[button] = adapter.IsPressed(button);
}
foreach (var button in adapter.Definition.FloatControls)
{
table[button] = adapter.GetFloat(button);
}
}
}
}
return table;
}
}
}

View File

@ -44,8 +44,6 @@ namespace BizHawk.Client.EmuHawk
this.MakeDefaultCheckbox = new System.Windows.Forms.CheckBox();
this.label2 = new System.Windows.Forms.Label();
this.EmulatorVersionTextBox = new System.Windows.Forms.TextBox();
this.PlatformTextBox = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.CoreTextBox = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.BoardNameTextBox = new System.Windows.Forms.TextBox();
@ -134,29 +132,11 @@ namespace BizHawk.Client.EmuHawk
this.EmulatorVersionTextBox.Size = new System.Drawing.Size(162, 20);
this.EmulatorVersionTextBox.TabIndex = 7;
//
// PlatformTextBox
//
this.PlatformTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.PlatformTextBox.Location = new System.Drawing.Point(90, 106);
this.PlatformTextBox.Name = "PlatformTextBox";
this.PlatformTextBox.Size = new System.Drawing.Size(162, 20);
this.PlatformTextBox.TabIndex = 8;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 110);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(45, 13);
this.label3.TabIndex = 9;
this.label3.Text = "Platform";
//
// CoreTextBox
//
this.CoreTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CoreTextBox.Location = new System.Drawing.Point(90, 136);
this.CoreTextBox.Location = new System.Drawing.Point(90, 106);
this.CoreTextBox.Name = "CoreTextBox";
this.CoreTextBox.Size = new System.Drawing.Size(162, 20);
this.CoreTextBox.TabIndex = 10;
@ -164,7 +144,7 @@ namespace BizHawk.Client.EmuHawk
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(12, 140);
this.label4.Location = new System.Drawing.Point(12, 110);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(29, 13);
this.label4.TabIndex = 11;
@ -174,7 +154,7 @@ namespace BizHawk.Client.EmuHawk
//
this.BoardNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.BoardNameTextBox.Location = new System.Drawing.Point(90, 166);
this.BoardNameTextBox.Location = new System.Drawing.Point(90, 136);
this.BoardNameTextBox.Name = "BoardNameTextBox";
this.BoardNameTextBox.Size = new System.Drawing.Size(162, 20);
this.BoardNameTextBox.TabIndex = 12;
@ -182,7 +162,7 @@ namespace BizHawk.Client.EmuHawk
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(12, 170);
this.label5.Location = new System.Drawing.Point(12, 140);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(64, 13);
this.label5.TabIndex = 13;
@ -192,7 +172,7 @@ namespace BizHawk.Client.EmuHawk
//
this.GameNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.GameNameTextBox.Location = new System.Drawing.Point(90, 196);
this.GameNameTextBox.Location = new System.Drawing.Point(90, 166);
this.GameNameTextBox.Name = "GameNameTextBox";
this.GameNameTextBox.Size = new System.Drawing.Size(162, 20);
this.GameNameTextBox.TabIndex = 14;
@ -200,7 +180,7 @@ namespace BizHawk.Client.EmuHawk
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(12, 200);
this.label6.Location = new System.Drawing.Point(12, 170);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(64, 13);
this.label6.TabIndex = 15;
@ -219,8 +199,6 @@ namespace BizHawk.Client.EmuHawk
this.Controls.Add(this.BoardNameTextBox);
this.Controls.Add(this.label4);
this.Controls.Add(this.CoreTextBox);
this.Controls.Add(this.label3);
this.Controls.Add(this.PlatformTextBox);
this.Controls.Add(this.EmulatorVersionTextBox);
this.Controls.Add(this.label2);
this.Controls.Add(this.MakeDefaultCheckbox);
@ -248,8 +226,6 @@ namespace BizHawk.Client.EmuHawk
private CheckBox MakeDefaultCheckbox;
private Label label2;
private TextBox EmulatorVersionTextBox;
private TextBox PlatformTextBox;
private Label label3;
private TextBox CoreTextBox;
private Label label4;
private TextBox BoardNameTextBox;

View File

@ -19,7 +19,6 @@ namespace BizHawk.Client.EmuHawk
{
AuthorTextBox.Text = _movie.Author;
EmulatorVersionTextBox.Text = _movie.EmulatorVersion;
PlatformTextBox.Text = _movie.SystemID;
CoreTextBox.Text = _movie.Core;
BoardNameTextBox.Text = _movie.BoardName;
GameNameTextBox.Text = _movie.GameName;
@ -34,7 +33,6 @@ namespace BizHawk.Client.EmuHawk
}
_movie.EmulatorVersion = EmulatorVersionTextBox.Text;
_movie.SystemID = PlatformTextBox.Text;
_movie.Core = CoreTextBox.Text;
_movie.BoardName = BoardNameTextBox.Text;
_movie.GameName = GameNameTextBox.Text;

View File

@ -1,258 +0,0 @@
using System.Collections.Generic;
using System.Drawing;
using BizHawk.Common.ReflectionExtensions;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Atari.A7800Hawk;
namespace BizHawk.Client.EmuHawk
{
[Schema("A7800Hawk")]
public class A7800HawkSchema : IVirtualPadSchema
{
private string UnpluggedControllerName => typeof(UnpluggedController).DisplayName();
private string StandardControllerName => typeof(StandardController).DisplayName();
private string ProLineControllerName => typeof(ProLineController).DisplayName();
public IEnumerable<PadSchema> GetPadSchemas(IEmulator core)
{
var A78SyncSettings = ((A7800Hawk)core).GetSyncSettings().Clone();
var port1 = A78SyncSettings.Port1;
var port2 = A78SyncSettings.Port2;
if (port1 == StandardControllerName)
{
yield return JoystickController(1);
}
if (port2 == StandardControllerName)
{
yield return JoystickController(2);
}
if (port1 == ProLineControllerName)
{
yield return ProLineController(1);
}
if (port2 == ProLineControllerName)
{
yield return ProLineController(2);
}
}
private static PadSchema ProLineController(int controller)
{
return new PadSchema
{
DisplayName = "Player " + controller,
IsConsole = false,
DefaultSize = new Size(174, 74),
MaxSize = new Size(174, 74),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Up",
DisplayName = "",
Icon = Properties.Resources.BlueUp,
Location = new Point(23, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Down",
DisplayName = "",
Icon = Properties.Resources.BlueDown,
Location = new Point(23, 36),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Left",
DisplayName = "",
Icon = Properties.Resources.Back,
Location = new Point(2, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Right",
DisplayName = "",
Icon = Properties.Resources.Forward,
Location = new Point(44, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "1",
Location = new Point(120, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger 2",
DisplayName = "2",
Location = new Point(145, 24),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema JoystickController(int controller)
{
return new PadSchema
{
DisplayName = "Player " + controller,
IsConsole = false,
DefaultSize = new Size(174, 74),
MaxSize = new Size(174, 74),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Up",
DisplayName = "",
Icon = Properties.Resources.BlueUp,
Location = new Point(23, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Down",
DisplayName = "",
Icon = Properties.Resources.BlueDown,
Location = new Point(23, 36),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Left",
DisplayName = "",
Icon = Properties.Resources.Back,
Location = new Point(2, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Right",
DisplayName = "",
Icon = Properties.Resources.Forward,
Location = new Point(44, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "1",
Location = new Point(120, 24),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema PaddleController(int controller)
{
return new PadSchema
{
DisplayName = "Player " + controller,
IsConsole = false,
DefaultSize = new Size(250, 74),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Paddle",
DisplayName = "Paddle",
Location = new Point(23, 15),
Type = PadSchema.PadInputType.FloatSingle
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "1",
Location = new Point(12, 90),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema LightGunController(int controller)
{
return new PadSchema
{
DisplayName = "Light Gun",
IsConsole = false,
DefaultSize = new Size(356, 290),
MaxSize = new Size(356, 290),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " VPos",
Location = new Point(14, 17),
Type = PadSchema.PadInputType.TargetedPair,
TargetSize = new Size(256, 240),
SecondaryNames = new[]
{
"P" + controller + " HPos",
}
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "Trigger",
Location = new Point(284, 17),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema ConsoleButtons()
{
return new PadSchema
{
DisplayName = "Console",
IsConsole = true,
DefaultSize = new Size(215, 50),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "Select",
DisplayName = "Select",
Location = new Point(10, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "Reset",
DisplayName = "Reset",
Location = new Point(60, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "Power",
DisplayName = "Power",
Location = new Point(108, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "Pause",
DisplayName = "Pause",
Location = new Point(158, 15),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
}
}

View File

@ -4,6 +4,9 @@ using System.Drawing;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Atari.Atari7800;
using BizHawk.Common.ReflectionExtensions;
using BizHawk.Emulation.Cores.Atari.A7800Hawk;
namespace BizHawk.Client.EmuHawk
{
[Schema("A78")]
@ -11,7 +14,275 @@ namespace BizHawk.Client.EmuHawk
{
public IEnumerable<PadSchema> GetPadSchemas(IEmulator core)
{
switch (((Atari7800)core).ControlAdapter.ControlType.Name)
if (core is Atari7800)
{
return Emu7800Schema.GetPadSchemas((Atari7800)core);
}
return Atari7800HawkSchema.GetPadSchemas((A7800Hawk)core);
}
}
internal static class Atari7800HawkSchema
{
private static string UnpluggedControllerName => typeof(UnpluggedController).DisplayName();
private static string StandardControllerName => typeof(StandardController).DisplayName();
private static string ProLineControllerName => typeof(ProLineController).DisplayName();
public static IEnumerable<PadSchema> GetPadSchemas(A7800Hawk core)
{
var A78SyncSettings = core.GetSyncSettings().Clone();
var port1 = A78SyncSettings.Port1;
var port2 = A78SyncSettings.Port2;
if (port1 == StandardControllerName)
{
yield return JoystickController(1);
}
if (port2 == StandardControllerName)
{
yield return JoystickController(2);
}
if (port1 == ProLineControllerName)
{
yield return ProLineController(1);
}
if (port2 == ProLineControllerName)
{
yield return ProLineController(2);
}
}
private static PadSchema ProLineController(int controller)
{
return new PadSchema
{
DisplayName = "Player " + controller,
IsConsole = false,
DefaultSize = new Size(174, 74),
MaxSize = new Size(174, 74),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Up",
DisplayName = "",
Icon = Properties.Resources.BlueUp,
Location = new Point(23, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Down",
DisplayName = "",
Icon = Properties.Resources.BlueDown,
Location = new Point(23, 36),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Left",
DisplayName = "",
Icon = Properties.Resources.Back,
Location = new Point(2, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Right",
DisplayName = "",
Icon = Properties.Resources.Forward,
Location = new Point(44, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "1",
Location = new Point(120, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger 2",
DisplayName = "2",
Location = new Point(145, 24),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema JoystickController(int controller)
{
return new PadSchema
{
DisplayName = "Player " + controller,
IsConsole = false,
DefaultSize = new Size(174, 74),
MaxSize = new Size(174, 74),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Up",
DisplayName = "",
Icon = Properties.Resources.BlueUp,
Location = new Point(23, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Down",
DisplayName = "",
Icon = Properties.Resources.BlueDown,
Location = new Point(23, 36),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Left",
DisplayName = "",
Icon = Properties.Resources.Back,
Location = new Point(2, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Right",
DisplayName = "",
Icon = Properties.Resources.Forward,
Location = new Point(44, 24),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "1",
Location = new Point(120, 24),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema PaddleController(int controller)
{
return new PadSchema
{
DisplayName = "Player " + controller,
IsConsole = false,
DefaultSize = new Size(250, 74),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Paddle",
DisplayName = "Paddle",
Location = new Point(23, 15),
Type = PadSchema.PadInputType.FloatSingle
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "1",
Location = new Point(12, 90),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema LightGunController(int controller)
{
return new PadSchema
{
DisplayName = "Light Gun",
IsConsole = false,
DefaultSize = new Size(356, 290),
MaxSize = new Size(356, 290),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "P" + controller + " VPos",
Location = new Point(14, 17),
Type = PadSchema.PadInputType.TargetedPair,
TargetSize = new Size(256, 240),
SecondaryNames = new[]
{
"P" + controller + " HPos",
}
},
new PadSchema.ButtonSchema
{
Name = "P" + controller + " Trigger",
DisplayName = "Trigger",
Location = new Point(284, 17),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
private static PadSchema ConsoleButtons()
{
return new PadSchema
{
DisplayName = "Console",
IsConsole = true,
DefaultSize = new Size(215, 50),
Buttons = new[]
{
new PadSchema.ButtonSchema
{
Name = "Select",
DisplayName = "Select",
Location = new Point(10, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "Reset",
DisplayName = "Reset",
Location = new Point(60, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "Power",
DisplayName = "Power",
Location = new Point(108, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "Pause",
DisplayName = "Pause",
Location = new Point(158, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "BW",
DisplayName = "BW",
Location = new Point(158, 15),
Type = PadSchema.PadInputType.Boolean
}
}
};
}
}
internal static class Emu7800Schema
{
public static IEnumerable<PadSchema> GetPadSchemas(Atari7800 core)
{
switch (core.ControlAdapter.ControlType.Name)
{
case "Atari 7800 Joystick Controller":
yield return JoystickController(1);
@ -248,6 +519,13 @@ namespace BizHawk.Client.EmuHawk
DisplayName = "Pause",
Location = new Point(158, 15),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonSchema
{
Name = "BW",
DisplayName = "BW",
Location = new Point(158, 15),
Type = PadSchema.PadInputType.Boolean
}
}
};

View File

@ -264,7 +264,7 @@ namespace BizHawk.Client.EmuHawk
new PadSchema.ButtonSchema
{
Name = $"P{controller} Stick Horizontal",
SecondaryNames = new[] { $"P{controller} StickVertical" },
SecondaryNames = new[] { $"P{controller} Stick Vertical" },
MinValue = 0,
MidValue = 127,
MaxValue = 255,
@ -575,7 +575,7 @@ namespace BizHawk.Client.EmuHawk
new PadSchema.ButtonSchema
{
Name = $"P{controller} Right Stick Horizontal",
SecondaryNames = new[] { $"P{controller} Right StickVertical" },
SecondaryNames = new[] { $"P{controller} Right Stick Vertical" },
MinValue = 0,
MidValue = 127,
MaxValue = 255,

View File

@ -85,6 +85,8 @@ namespace BizHawk.Emulation.Common
string xaxis = constraint.Params[0] as string;
string yaxis = constraint.Params[1] as string;
float range = (float)constraint.Params[2];
if (!floatButtons.ContainsKey(xaxis)) break;
if (!floatButtons.ContainsKey(yaxis)) break;
double xval = floatButtons[xaxis];
double yval = floatButtons[yaxis];
double length = Math.Sqrt((xval * xval) + (yval * yval));

View File

@ -138,6 +138,7 @@ namespace BizHawk.Emulation.Common
// https://en.wikipedia.org/wiki/PlayStation_models#Comparison_of_models [w]
// https://github.com/petrockblog/RetroPie-Setup/wiki/PCSX-Core-Playstation-1 [g]
// http://redump.org/datfile/psx-bios/ also
// http://emulation.gametechwiki.com/index.php/File_Hashes [t]
var ps_10j = File("343883A7B555646DA8CEE54AADD2795B6E7DD070", 524288, "ps-10j.bin", "PSX BIOS (Version 1.0 J)", "Used on SCPH-1000, DTL-H1000 [g]. This is Rev for A hardware [w].");
var ps_11j = File("B06F4A861F74270BE819AA2A07DB8D0563A7CC4E", 524288, "ps-11j.bin", "PSX BIOS (Version 1.1 01/22/95)", "Used on SCPH-3000, DTL-H1000H [g]. This is for Rev B hardware [w].");
var ps_20a = File("649895EFD79D14790EABB362E94EB0622093DFB9", 524288, "ps-20a.bin", "PSX BIOS (Version 2.0 05/07/95 A)", "Used on DTL-H1001 [g]. This is for Rev B hardware [w].");
@ -151,6 +152,7 @@ namespace BizHawk.Emulation.Common
var ps_22a = File("10155D8D6E6E832D6EA66DB9BC098321FB5E8EBF", 524288, "ps-22a.bin", "PSX BIOS (Version 2.2 12/04/95 A)", "Used on SCPH-1001, DTL-H1201, DTL-H3001 [g]. This is for Rev C hardware [w].");
var ps_22e = File("B6A11579CAEF3875504FCF3831B8E3922746DF2C", 524288, "ps-22e.bin", "PSX BIOS (Version 2.2 12/04/95 E)", "Used on SCPH-1002, DTL-H1202, DTL-H3002 [g]. This is for Rev C hardware [w].");
var ps_22d = File("73107D468FC7CB1D2C5B18B269715DD889ECEF06", 524288, "ps-22d.bin", "PSX BIOS (Version 2.2 03/06/96 D)", "Used on DTL-H1100 [g]. This is for Rev C hardware, presumably.");
/*new*/var ps_22jv = File("15C94DA3CC5A38A582429575AF4198C487FE893C", 1048576, "ps-22j(v).bin", "PSX BIOS (Version 2.2 12/04/95 J)", "Used on SCPH-5903 [t].");
var ps_30j = File("B05DEF971D8EC59F346F2D9AC21FB742E3EB6917", 524288, "ps-30j.bin", "PSX BIOS (Version 3.0 09/09/96 J)", "Used on SCPH-5500 [g]. This is for Rev C hardware [w]. Recommended for (J) [f].");
var ps_30a = File("0555C6FAE8906F3F09BAF5988F00E55F88E9F30B", 524288, "ps-30a.bin", "PSX BIOS (Version 3.0 11/18/96 A)", "Used on SCPH-5501, SCPH-5503, SCPH-7003 [g]. This is for Rev C hardware [w]. Recommended for (U) [f].");
var ps_30e = File("F6BC2D1F5EB6593DE7D089C425AC681D6FFFD3F0", 524288, "ps-30e.bin", "PSX BIOS (Version 3.0 01/06/97 E)", "Used on SCPH-5502, SCPH-5552 [g]. This is for Rev C hardware [w]. Recommended for (E) [f].");
@ -158,11 +160,15 @@ namespace BizHawk.Emulation.Common
var ps_40j = File("77B10118D21AC7FFA9B35F9C4FD814DA240EB3E9", 524288, "ps-40j.bin", "PSX BIOS (Version 4.0 08/18/97 J)", "Used on SCPH-7000, SCPH-7500, SCPH-9000 [g]. This is for Rev C hardware [w].");
var ps_41a = File("14DF4F6C1E367CE097C11DEAE21566B4FE5647A9", 524288, "ps-41a.bin", "PSX BIOS (Version 4.1 12/16/97 A)", "Used on SCPH-7001, SCPH-7501, SCPH-7503, SCPH-9001, SCPH-9003, SCPH-9903 [g]. This is for Rev C hardware [w].");
var ps_41e = File("8D5DE56A79954F29E9006929BA3FED9B6A418C1D", 524288, "ps-41e.bin", "PSX BIOS (Version 4.1 12/16/97 E)", "Used on SCPH-7002, SCPH-7502, SCPH-9002 [g]. This is for Rev C hardware [w].");
/*new*/var ps_41aw = File("1B0DBDB23DA9DC0776AAC58D0755DC80FEA20975", 524288, "ps-41a(w).bin", "PSX BIOS (Version 4.1 11/14/97 A)", "Used on SCPH-7000W [t].");
var psone_43j = File("339A48F4FCF63E10B5B867B8C93CFD40945FAF6C", 524288, "psone-43j.bin", "PSX BIOS (Version 4.3 03/11/00 J)", "Used on PSone SCPH-100 [g]. This is for Rev C PSone hardware [w].");
var psone_44e = File("BEB0AC693C0DC26DAF5665B3314DB81480FA5C7C", 524288, "psone-44e.bin", "PSX BIOS (Version 4.4 03/24/00 E)", "Used on PSone SCPH-102 [g]. This is for Rev C PSone hardware [w].");
var psone_45a = File("DCFFE16BD90A723499AD46C641424981338D8378", 524288, "psone-45a.bin", "PSX BIOS (Version 4.5 05/25/00 A)", "Used on PSone SCPH-101 [g]. This is for Rev C PSone hardware [w].");
var psone_r5e = File("DBC7339E5D85827C095764FC077B41F78FD2ECAE", 524288, "psone-45e.bin", "PSX BIOS (Version 4.5 05/25/00 E)", "Used on PSone SCPH-102 [g]. This is for Rev C PSone hardware [w].");
var ps2_50j = File("D7D6BE084F51354BC951D8FA2D8D912AA70ABC5E", 4194304, "ps2-50j.bin", "PSX BIOS (Version 5.0 10/27/00 J)", "Found on a PS2 [p].");
var ps2_50j = File("D7D6BE084F51354BC951D8FA2D8D912AA70ABC5E", 4194304, "ps2-50j.bin", "PSX BIOS (Version 5.0 10/27/00 J)", "Found on a PS2 [p]. May be known as SCPH18000.BIN.");
/*new*/ var ps_dtl_h2000 = File("1A8D6F9453111B1D317BB7DAE300495FBF54600C", 524288, "DTLH2000.bin", "DTL-H2000 Devkit [t]");
/*new*/ var ps_ps3 = File("C40146361EB8CF670B19FDC9759190257803CAB7", 524288, "ps1_rom.bin", "PSX BIOS (Version 5.0 06/23/03 A)", "Found on a PS3. [t]");
ps_22j_bad.Bad = ps_22j_bad2.Bad = ps_30e_bad.Bad = true;
@ -191,14 +197,22 @@ namespace BizHawk.Emulation.Common
Option("PSX", "J", ps_22j_bad2, FirmwareOptionStatus.Bad);
Option("PSX", "U", ps_22a, FirmwareOptionStatus.Unacceptable);
Option("PSX", "E", ps_22e, FirmwareOptionStatus.Unacceptable);
Option("PSX", "J", ps_22d, FirmwareOptionStatus.Unacceptable);
Option("PSX", "E", ps_30e_bad, FirmwareOptionStatus.Bad);
Option("PSX", "J", ps_40j, FirmwareOptionStatus.Unacceptable);
Option("PSX", "U", ps_41a, FirmwareOptionStatus.Unacceptable);
Option("PSX", "E", ps_41e, FirmwareOptionStatus.Unacceptable);
Option("PSX", "J", psone_43j, FirmwareOptionStatus.Unacceptable);
Option("PSX", "E", psone_44e, FirmwareOptionStatus.Unacceptable);
Option("PSX", "U", psone_45a, FirmwareOptionStatus.Unacceptable);
Option("PSX", "E", psone_r5e, FirmwareOptionStatus.Unacceptable);
Option("PSX", "J", ps2_50j, FirmwareOptionStatus.Unacceptable);
Option("PSX", "J", ps_22jv, FirmwareOptionStatus.Unacceptable);
Option("PSX", "U", ps_41aw, FirmwareOptionStatus.Unacceptable);
Option("PSX", "U", ps_ps3, FirmwareOptionStatus.Unacceptable);
Option("PSX", "U", ps_dtl_h2000, FirmwareOptionStatus.Unacceptable); //not really sure what to do with this one, let's just call it region free
Option("PSX", "E", ps_dtl_h2000, FirmwareOptionStatus.Unacceptable);
Option("PSX", "J", ps_dtl_h2000, FirmwareOptionStatus.Unacceptable);
Firmware("AppleII", "AppleIIe", "AppleIIe.rom");
var appleII_AppleIIe = File("B8EA90ABE135A0031065E01697C4A3A20D51198B", 16384, "AppleIIe.rom", "Apple II e");

View File

@ -359,7 +359,8 @@
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperDefault.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperSG.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperSGE.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperF18.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperF18.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperFractalus.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperRampage.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Mappers\MapperBase.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\MemoryMap.cs">
@ -685,7 +686,6 @@
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper029.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper030.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper034.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper035.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper036.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper038.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper040.cs" />

File diff suppressed because it is too large Load Diff

View File

@ -88,11 +88,13 @@ namespace BizHawk.Emulation.Cores.Components.Z80
private RegisterPair RegBC;
private RegisterPair RegDE;
private RegisterPair RegHL;
private RegisterPair RegWZ;
private RegisterPair RegAltAF; // Shadow for A and F
private RegisterPair RegAltBC; // Shadow for B and C
private RegisterPair RegAltDE; // Shadow for D and E
private RegisterPair RegAltHL; // Shadow for H and L
// NOTE: There is no AltWZ register (despite it being shown on various block diagrams)
private byte RegI; // I (interrupt vector)
private byte RegR; // R (memory refresh)
@ -106,7 +108,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80
private void ResetRegisters()
{
// Clear main registers
RegAF = 0; RegBC = 0; RegDE = 0; RegHL = 0;
RegAF = 0; RegBC = 0; RegDE = 0; RegHL = 0; RegWZ = 0;
// Clear alternate registers
RegAltAF = 0; RegAltBC = 0; RegAltDE = 0; RegAltHL = 0;
// Clear special purpose registers
@ -162,6 +164,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80
get { return RegDE.Low; }
set { RegDE.Low = value; }
}
public ushort RegisterDE
{
get { return RegDE.Word; }
@ -179,57 +182,85 @@ namespace BizHawk.Emulation.Cores.Components.Z80
get { return RegHL.Low; }
set { RegHL.Low = value; }
}
public ushort RegisterHL
{
get { return RegHL.Word; }
set { RegHL.Word = value; }
}
public byte RegisterW
{
get { return RegWZ.High; }
set { RegWZ.High = value; }
}
public byte RegisterZ
{
get { return RegWZ.Low; }
set { RegWZ.Low = value; }
}
public ushort RegisterWZ
{
get { return RegWZ.Word; }
set { RegWZ.Word = value; }
}
public ushort RegisterPC
{
get { return RegPC.Word; }
set { RegPC.Word = value; }
}
public ushort RegisterSP
{
get { return RegSP.Word; }
set { RegSP.Word = value; }
}
public ushort RegisterIX
{
get { return RegIX.Word; }
set { RegIX.Word = value; }
}
public ushort RegisterIY
{
get { return RegIY.Word; }
set { RegIY.Word = value; }
}
public byte RegisterI
{
get { return RegI; }
set { RegI = value; }
}
public byte RegisterR
{
get { return RegR; }
set { RegR = value; }
}
public ushort RegisterShadowAF
{
get { return RegAltAF.Word; }
set { RegAltAF.Word = value; }
}
public ushort RegisterShadowBC
{
get { return RegAltBC.Word; }
set { RegAltBC.Word = value; }
}
public ushort RegisterShadowDE
{
get { return RegAltDE.Word; }
set { RegAltDE.Word = value; }
}
public ushort RegisterShadowHL
{
get { return RegAltHL.Word; }

View File

@ -8,6 +8,8 @@ using BizHawk.Emulation.Common;
// This Z80 emulator is a modified version of Ben Ryves 'Brazil' emulator.
// It is MIT licensed.
// for WZ register details, see: http://www.grimware.org/lib/exe/fetch.php/documentations/devices/z80/z80.memptr.eng.txt
namespace BizHawk.Emulation.Cores.Components.Z80
{
public sealed partial class Z80A
@ -113,6 +115,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80
ser.Sync("BC", ref RegBC.Word);
ser.Sync("DE", ref RegDE.Word);
ser.Sync("HL", ref RegHL.Word);
ser.Sync("WZ", ref RegWZ.Word);
ser.Sync("ShadowAF", ref RegAltAF.Word);
ser.Sync("ShadowBC", ref RegAltBC.Word);
ser.Sync("ShadowDE", ref RegAltDE.Word);

View File

@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Definition = new ControllerDefinition
{
Name = "Atari 2600 Controller",
Name = "Atari 2600 Basic Controller",
BoolButtons = Port1.Definition.BoolButtons
.Concat(Port2.Definition.BoolButtons)
.Concat(new[]

View File

@ -1128,7 +1128,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_player0.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67)
if (_hsyncCnt == 67 || _hsyncCnt==0)
{
_player0.HPosCnt = 160 - 3;
}
@ -1136,7 +1136,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
else
{
_player0.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75)
if (_hsyncCnt == 75 || _hsyncCnt == 0)
{
_player0.HPosCnt = 160 - 3;
}
@ -1148,7 +1148,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_player1.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67)
if (_hsyncCnt == 67 || _hsyncCnt == 0)
{
_player1.HPosCnt = 160 - 3;
}
@ -1156,7 +1156,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
else
{
_player1.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75)
if (_hsyncCnt == 75 || _hsyncCnt == 0)
{
_player1.HPosCnt = 160 - 3;
}
@ -1167,7 +1167,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_player0.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67)
if (_hsyncCnt == 67 || _hsyncCnt == 0)
{
_player0.Missile.HPosCnt = 160 - 3;
}
@ -1175,7 +1175,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
else
{
_player0.Missile.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75)
if (_hsyncCnt == 75 || _hsyncCnt == 0)
{
_player0.Missile.HPosCnt = 160 - 3;
}
@ -1186,7 +1186,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_player1.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67)
if (_hsyncCnt == 67 || _hsyncCnt == 0)
{
_player1.Missile.HPosCnt = 160 - 3;
}
@ -1194,7 +1194,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
else
{
_player1.Missile.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75)
if (_hsyncCnt == 75 || _hsyncCnt == 0)
{
_player1.Missile.HPosCnt = 160 - 3;
}
@ -1205,7 +1205,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_ball.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67)
if (_hsyncCnt == 67 || _hsyncCnt == 0)
{
_ball.HPosCnt = 160 - 3;
}
@ -1213,7 +1213,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
else
{
_ball.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75)
if (_hsyncCnt == 75 || _hsyncCnt == 0)
{
_ball.HPosCnt = 160 - 3;
}

View File

@ -21,6 +21,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
"BW", // should be "Color"??
"Left Difficulty", // better not put P# on these as they might not correspond to player numbers
"Right Difficulty",
"Pause",
// ports
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Trigger",
@ -166,9 +167,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
// on the console
"Reset",
"Select",
"Pause",
"BW", // should be "Color"??
"Toggle Left Difficulty", // better not put P# on these as they might not correspond to player numbers
"Toggle Right Difficulty",
"Pause",
// ports
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Trigger", "P1 Trigger 2",

View File

@ -1,10 +1,11 @@
using BizHawk.Common.NumberExtensions;
using BizHawk.Emulation.Common;
using System;
using System.Collections.Generic;
namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
public partial class A7800Hawk : IEmulator
public partial class A7800Hawk : IEmulator, IVideoProvider
{
public IEmulatorServiceProvider ServiceProvider { get; }
@ -13,7 +14,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
//Maria related variables
public int cycle;
public int cpu_cycle;
public int m6532_cycle;
public bool cpu_is_haltable;
public bool cpu_is_halted;
public bool cpu_halt_pending;
@ -33,15 +33,27 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
public bool right_was_pressed;
public bool p1_is_2button;
public bool p2_is_2button;
public bool p1_is_lightgun;
public bool p2_is_lightgun;
public float p1_lightgun_x;
public float p1_lightgun_y;
public float p2_lightgun_x;
public float p2_lightgun_y;
public int lg_1_counting_down;
public int lg_1_counting_down_2;
public int lg_2_counting_down;
public int lg_2_counting_down_2;
public byte lg_1_trigger_hit;
public byte lg_2_trigger_hit;
// there are 4 maria cycles in a CPU cycle (fast access, both NTSC and PAL)
// if the 6532 or TIA are accessed (PC goes to one of those addresses) the next access will be slower by 1/2 a CPU cycle
// i.e. it will take 6 Maria cycles instead of 4
public bool slow_access = false;
public int slow_countdown;
public void FrameAdvance(IController controller, bool render, bool rendersound)
{
Console.WriteLine("-----------------------FRAME-----------------------");
if (_tracer.Enabled)
{
cpu.TraceCallback = s => _tracer.Put(s);
@ -71,12 +83,77 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
_lagcount++;
}
}
public void RunCPUCycle()
{
cpu_cycle++;
if (slow_countdown==0)
{
cpu_cycle++;
}
else
{
slow_countdown--;
}
if (p1_is_lightgun)
{
if (lg_1_counting_down > 0)
{
lg_1_counting_down--;
if (lg_1_counting_down == 0 && lg_1_counting_down_2 > 0)
{
lg_1_trigger_hit = 0;
lg_1_counting_down = 454;
lg_1_counting_down_2--;
}
if (lg_1_counting_down < 424)
{
lg_1_trigger_hit = 0x80;
}
}
if ((maria.scanline - 20) == (p1_lightgun_y - 4))
{
if (maria.cycle == (132 + p1_lightgun_x))
{
// return true 64 cycles into the future
lg_1_counting_down = 64;
lg_1_counting_down_2 = 9;
}
}
}
if (p2_is_lightgun)
{
if (lg_2_counting_down > 0)
{
lg_2_counting_down--;
if (lg_2_counting_down == 0 && lg_2_counting_down_2 > 0)
{
lg_2_trigger_hit = 0;
lg_2_counting_down = 454;
lg_2_counting_down_2--;
}
if (lg_2_counting_down < 424)
{
lg_2_trigger_hit = 0x80;
}
}
if ((maria.scanline - 20) == (p2_lightgun_y - 4))
{
if (maria.cycle == (132 + p2_lightgun_x))
{
// return true 64 cycles into the future
lg_2_counting_down = 64;
lg_2_counting_down_2 = 9;
}
}
}
tia._hsyncCnt++;
tia._hsyncCnt %= 454;
// do the audio sampling
@ -86,11 +163,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
// tick the m6532 timer, which is still active although not recommended to use
m6532_cycle++;
if (m6532_cycle== 4)
// also it runs off of the cpu cycle timer
if (cpu_cycle== 4)
{
m6532.Timer.Tick();
m6532_cycle = 0;
}
if (cpu_cycle <= (2 + (slow_access ? 1 : 0)))
@ -109,6 +185,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
if (!cpu_is_halted)
{
cpu.ExecuteOne();
// we need to stall the next cpu cycle from starting if the current one is a slow access
if (slow_access)
{
slow_access = false;
slow_countdown = 2;
}
}
else
{
@ -131,32 +214,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
cpu_is_halted = false;
}
}
// determine if the next access will be fast or slow
if ((cpu.PC & 0xFCE0) == 0)
{
// return TIA registers or control register if it is still unlocked
if ((A7800_control_register & 0x1) == 0)
{
slow_access = false;
}
else
{
slow_access = true;
}
}
else if ((cpu.PC & 0xFF80) == 0x280)
{
slow_access = true;
}
else if ((cpu.PC & 0xFE80) == 0x480)
{
slow_access = true;
}
else
{
slow_access = false;
}
}
public void GetControllerState(IController controller)
@ -171,13 +228,15 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
p2_fire_2x = _controllerDeck.ReadFire2_2x(controller);
p1_is_2button = _controllerDeck.Is_2_button1(controller);
p2_is_2button = _controllerDeck.Is_2_button2(controller);
p1_is_lightgun = _controllerDeck.Is_LightGun1(controller, out p1_lightgun_x, out p1_lightgun_y);
p2_is_lightgun = _controllerDeck.Is_LightGun2(controller, out p2_lightgun_x, out p2_lightgun_y);
}
public void GetConsoleState(IController controller)
{
byte result = 0;
if (controller.IsPressed("Right Difficulty"))
if (controller.IsPressed("Toggle Right Difficulty"))
{
if (!right_was_pressed)
{
@ -192,7 +251,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
result |= (byte)((right_toggle ? 1 : 0) << 7);
}
if (controller.IsPressed("Left Difficulty"))
if (controller.IsPressed("Toggle Left Difficulty"))
{
if (!left_was_pressed)
{
@ -225,7 +284,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
public int Frame => _frame;
public string SystemId => "A7800";
public string SystemId => "A78";
public bool DeterministicEmulation { get; set; }
@ -244,5 +303,46 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
tia = null;
m6532 = null;
}
#region Video provider
public int _frameHz = 60;
public int _screen_width = 320;
public int _screen_height = 263;
public int _vblanklines = 20;
public int[] _vidbuffer;
public int[] GetVideoBuffer()
{
if (_syncSettings.Filter != "None")
{
apply_filter();
}
return _vidbuffer;
}
public int VirtualWidth => 320;
public int VirtualHeight => _screen_height - _vblanklines;
public int BufferWidth => 320;
public int BufferHeight => _screen_height - _vblanklines;
public int BackgroundColor => unchecked((int)0xff000000);
public int VsyncNumerator => _frameHz;
public int VsyncDenominator => 1;
public void apply_filter()
{
}
public static Dictionary<string, string> ValidFilterTypes = new Dictionary<string, string>
{
{ "None", "None"},
{ "NTSC", "NTSC"},
{ "Pal", "Pal"}
};
#endregion
}
}

View File

@ -44,28 +44,25 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
1),
new MemoryDomainDelegate(
"Ram Block 0",
0xB0,
0xC0,
MemoryDomain.Endian.Little,
addr => RAM[addr+0x840],
(addr, value) => RAM[addr+0x840] = value,
1
),
1),
new MemoryDomainDelegate(
"Ram Block 1",
0xB0,
0xC0,
MemoryDomain.Endian.Little,
addr => RAM[addr+0x940],
(addr, value) => RAM[addr+0x940] = value,
1
),
1),
new MemoryDomainDelegate(
"System Bus",
0X10000,
MemoryDomain.Endian.Little,
addr => PeekSystemBus(addr),
(addr, value) => PokeSystemBus(addr, value),
1
)
1)
};
MemoryDomains = new MemoryDomainList(domains);

View File

@ -1,4 +1,6 @@
using System;
using System.ComponentModel;
using Newtonsoft.Json;
using BizHawk.Common;
@ -32,7 +34,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
private A7800Settings _settings = new A7800Settings();
private A7800SyncSettings _syncSettings = new A7800SyncSettings();
public A7800SyncSettings _syncSettings = new A7800SyncSettings();
public class A7800Settings
{
@ -46,6 +48,17 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
private string _port1 = A7800HawkControllerDeck.DefaultControllerName;
private string _port2 = A7800HawkControllerDeck.DefaultControllerName;
private string _Filter = "None";
[JsonIgnore]
public string Filter
{
get { return _Filter; }
set
{
_Filter = value;
}
}
[JsonIgnore]
public string Port1

View File

@ -70,13 +70,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
ser.Sync("cycle", ref cycle);
ser.Sync("cpu_cycle", ref cpu_cycle);
ser.Sync("m6532_cycle", ref m6532_cycle);
ser.Sync("cpu_is_haltable", ref cpu_is_haltable);
ser.Sync("cpu_is_halted", ref cpu_is_halted);
ser.Sync("cpu_halt_pending", ref cpu_halt_pending);
ser.Sync("cpu_resume_pending", ref cpu_resume_pending);
ser.Sync("slow_access", ref slow_access);
ser.Sync("slow_access", ref slow_countdown);
ser.Sync("small flag", ref small_flag);
ser.Sync("pal kara", ref PAL_Kara);
ser.Sync("Cart RAM", ref cart_RAM);

View File

@ -13,8 +13,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
isPorted: false,
isReleased: true)]
[ServiceNotApplicable(typeof(ISettable<,>), typeof(IDriveLight))]
public partial class A7800Hawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable,
ISettable<A7800Hawk.A7800Settings, A7800Hawk.A7800SyncSettings>
public partial class A7800Hawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable,
IRegionable, IBoardInfo, ISettable<A7800Hawk.A7800Settings, A7800Hawk.A7800SyncSettings>
{
// this register selects between 2600 and 7800 mode in the A7800
// however, we already have a 2600 emulator so this core will only be loading A7800 games
@ -76,7 +76,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
_settings = (A7800Settings)settings ?? new A7800Settings();
_syncSettings = (A7800SyncSettings)syncSettings ?? new A7800SyncSettings();
_controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2);
byte[] highscoreBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS.");
@ -173,7 +172,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
s_mapper = "0";
}
}
else
{
@ -206,18 +204,18 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
// set up palette and frame rate
if (_isPAL)
{
maria._frameHz = 50;
maria._screen_width = 320;
maria._screen_height = 313;
maria._vblanklines = 20;
_frameHz = 50;
_screen_width = 320;
_screen_height = 313;
_vblanklines = 20;
maria._palette = PALPalette;
}
else
{
maria._frameHz = 60;
maria._screen_width = 320;
maria._screen_height = 263;
maria._vblanklines = 20;
_frameHz = 60;
_screen_width = 320;
_screen_height = 263;
_vblanklines = 20;
maria._palette = NTSCPalette;
}
@ -225,7 +223,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
m6532.Core = this;
tia.Core = this;
ser.Register<IVideoProvider>(maria);
ser.Register<IVideoProvider>(this);
ser.Register<ISoundProvider>(tia);
ServiceProvider = ser;
@ -233,9 +231,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
ser.Register<ITraceable>(_tracer);
SetupMemoryDomains();
ser.Register<IDisassemblable>(cpu);
HardReset();
}
public string BoardName => mapper.GetType().Name.Replace("Mapper", "");
public DisplayType Region => _isPAL ? DisplayType.PAL : DisplayType.NTSC;
private readonly A7800HawkControllerDeck _controllerDeck;
@ -255,6 +256,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
RAM = new byte[0x1000];
cpu_cycle = 0;
_vidbuffer = new int[VirtualWidth * VirtualHeight];
}
private void ExecFetch(ushort addr)
@ -284,6 +287,14 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
mapper = new MapperRampage();
}
if (m == "5")
{
mapper = new MapperFractalus();
}
if (m == "6")
{
mapper = new MapperFractalus();
}
mapper.Core = this;
}

View File

@ -27,7 +27,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
Definition = new ControllerDefinition
{
Name = "A7800 Controller",
Name = Port1.Definition.Name,
BoolButtons = Port1.Definition.BoolButtons
.Concat(Port2.Definition.BoolButtons)
.Concat(new[]
@ -35,9 +35,9 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
"Power",
"Reset",
"Select",
"BW",
"Left Difficulty", // better not put P# on these as they might not correspond to player numbers
"Right Difficulty",
"BW",
"Toggle Left Difficulty", // better not put P# on these as they might not correspond to player numbers
"Toggle Right Difficulty",
"Pause"
})
.ToList()
@ -90,6 +90,16 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
return Port2.Is_2_button(c);
}
public bool Is_LightGun1(IController c, out float lightgun_x, out float lightgun_y)
{
return Port1.Is_LightGun(c, out lightgun_x, out lightgun_y);
}
public bool Is_LightGun2(IController c, out float lightgun_x, out float lightgun_y)
{
return Port2.Is_LightGun(c, out lightgun_x, out lightgun_y);
}
public ControllerDefinition Definition { get; }
public void SyncState(Serializer ser)
@ -127,5 +137,4 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
public static string DefaultControllerName => typeof(StandardController).DisplayName();
}
}

View File

@ -21,6 +21,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
bool Is_2_button(IController c);
bool Is_LightGun(IController c, out float x, out float y);
ControllerDefinition Definition { get; }
void SyncState(Serializer ser);
@ -60,6 +62,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
return false;
}
public bool Is_LightGun(IController c, out float x, out float y)
{
x = -1;
y = -1;
return false;
}
public ControllerDefinition Definition { get; }
public void SyncState(Serializer ser)
@ -78,6 +87,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
PortNum = portNum;
Definition = new ControllerDefinition
{
Name = "Atari 2600 Basic Controller",
BoolButtons = BaseDefinition
.Select(b => "P" + PortNum + " " + b)
.ToList()
@ -125,6 +135,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
return false;
}
public bool Is_LightGun(IController c, out float x, out float y)
{
x = -1;
y = -1;
return false;
}
public ControllerDefinition Definition { get; }
public void SyncState(Serializer ser)
@ -134,7 +151,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
private static readonly string[] BaseDefinition =
{
"U", "D", "L", "R", "Fire"
"Up", "Down", "Left", "Right", "Trigger"
};
private static byte[] HandControllerButtons =
@ -154,6 +171,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
PortNum = portNum;
Definition = new ControllerDefinition
{
Name = "Atari 7800 ProLine Joystick Controller",
BoolButtons = BaseDefinition
.Select(b => "P" + PortNum + " " + b)
.ToList()
@ -210,6 +228,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
return true;
}
public bool Is_LightGun(IController c, out float x, out float y)
{
x = -1;
y = -1;
return false;
}
public ControllerDefinition Definition { get; }
public void SyncState(Serializer ser)
@ -219,7 +244,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
private static readonly string[] BaseDefinition =
{
"U", "D", "L", "R", "Fire", "Fire2"
"Up", "Down", "Left", "Right", "Trigger", "Trigger 2"
};
private static byte[] HandControllerButtons =
@ -230,4 +255,75 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
0x0, // Right
};
}
}
[DisplayName("Light Gun Controller")]
public class LightGunController : IPort
{
public LightGunController(int portNum)
{
PortNum = portNum;
Definition = new ControllerDefinition
{
Name = "Light Gun Controller",
BoolButtons = BaseDefinition
.Select(b => "P" + PortNum + " " + b)
.ToList(),
FloatControls = { "P" + PortNum + " X", "P" + PortNum + " Y" },
FloatRanges = { new[] { 1.0f, 160, 320.0f }, new[] { 1.0f, 121, 242.0f } }
};
}
public int PortNum { get; }
public byte Read(IController c)
{
byte result = 0xE;
if (c.IsPressed(Definition.BoolButtons[0]))
{
result |= 0x1;
}
if (PortNum == 1)
{
result = (byte)(result << 4);
}
return result;
}
public byte ReadFire(IController c)
{
return 0x80;
}
public byte ReadFire2x(IController c)
{
return 0; // only applicable for 2 button mode
}
public bool Is_2_button(IController c)
{
return false;
}
public bool Is_LightGun(IController c, out float x, out float y)
{
x = c.GetFloat(Definition.FloatControls[0]);
y = c.GetFloat(Definition.FloatControls[1]);
return true;
}
public ControllerDefinition Definition { get; }
public void SyncState(Serializer ser)
{
// Nothing todo, I think
}
private static readonly string[] BaseDefinition =
{
"Trigger"
};
}
}

View File

@ -6,7 +6,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
// Emulates the M6532 RIOT Chip
public class M6532
{
public A7800Hawk Core { get; set; }
public byte _ddRa = 0x00;

View File

@ -85,7 +85,5 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
WriteMemory(addr, value);
}
}
}

View File

@ -0,0 +1,108 @@
using BizHawk.Common;
using BizHawk.Common.NumberExtensions;
using System;
namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
// Rescue on Fractulus has unique RAM mapping
public class MapperFractalus : MapperBase
{
public byte[] RAM = new byte[0x800];
public override byte ReadMemory(ushort addr)
{
if (addr >=0x1000 && addr < 0x1800)
{
//could be hsbios RAM here
if (Core._hsbios != null)
{
return Core._hsram[addr - 0x1000];
}
return 0xFF;
}
else if (addr < 0x4000)
{
// could be either RAM mirror or ROM
if (addr >= 0x3000 && Core._hsbios != null)
{
return Core._hsbios[addr - 0x3000];
}
else
{
return Core.RAM[0x800 + addr & 0x7FF];
}
}
else
{
// cartridge and other OPSYS
if ((Core._rom.Length >= 0x10000 - addr) && Core.A7800_control_register.Bit(2))
{
return Core._rom[Core._rom.Length - (0x10000 - addr)];
}
else if (addr >= (0x10000-Core._bios.Length) && !Core.A7800_control_register.Bit(2))
{
return Core._bios[addr - (0x10000 - Core._bios.Length)];
}
else if (addr >= 0x4000 && addr <0x5000)
{
int temp_ret_1 = ((addr >> 8) & 0xE) >> 1;
int temp_ret_2 = addr & 0xFF;
return RAM[(temp_ret_1 << 8) + temp_ret_2];
}
else
{
return 0x00;
}
}
}
public override byte PeekMemory(ushort addr)
{
return ReadMemory(addr);
}
public override void WriteMemory(ushort addr, byte value)
{
if (addr >= 0x1000 && addr < 0x1800)
{
//could be hsbios RAM here
if (Core._hsbios != null)
{
Core._hsram[addr - 0x1000] = value;
}
}
else if (addr < 0x4000)
{
// could be either RAM mirror or ROM
if (addr >= 0x3000 && Core._hsbios != null)
{
}
else
{
Core.RAM[0x800 + addr & 0x7FF] = value;
}
}
else
{
if (addr >= 0x4000 && addr < 0x5000)
{
int temp_ret_1 = ((addr >> 8) & 0xE) >> 1;
int temp_ret_2 = addr & 0xFF;
RAM[(temp_ret_1 << 8) + temp_ret_2] = value;
}
}
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMemory(addr, value);
}
public override void SyncState(Serializer ser)
{
ser.Sync("RAM", ref RAM, false);
}
}
}

View File

@ -6,7 +6,7 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
// Emulates the Atari 7800 Maria graphics chip
public class Maria : IVideoProvider
public class Maria
{
public A7800Hawk Core { get; set; }
@ -25,32 +25,15 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
// technically there is no limit on the number of graphics objects, but since dma is automatically killed
// at the end of a scanline, we have an effective limit
GFX_Object[,] GFX_Objects = new GFX_Object[2,128];
GFX_Object[] GFX_Objects = new GFX_Object[128];
public byte[,] line_ram = new byte[2, 320];
byte temp_check = 0;
int GFX_index = 0;
public int _frameHz = 60;
public int _screen_width = 320;
public int _screen_height = 263;
public int _vblanklines = 20;
public int[] _vidbuffer;
public int[] _palette;
public int[] scanline_buffer = new int[320];
public int[] bg_temp = new int[320]; // since BG color can be changed midscanline, we need to account for this here.
public int[] GetVideoBuffer()
{
return _vidbuffer;
}
public int VirtualWidth => 320;
public int VirtualHeight => _screen_height - _vblanklines;
public int BufferWidth => 320;
public int BufferHeight => _screen_height - _vblanklines;
public int BackgroundColor => unchecked((int)0xff000000);
public int VsyncNumerator => _frameHz;
public int VsyncDenominator => 1;
// the Maria chip can directly access memory
public Func<ushort, byte> ReadMemory;
@ -84,13 +67,20 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
public bool current_DLL_H16;
public bool current_DLL_H8;
public bool overrun_dma;
public bool global_write_mode;
public int header_counter;
public int[] header_counter_max = new int [2];
public int header_pointer; // since headers could be 4 or 5 bytes, we need a seperate pointer
// variables for drawing a pixel
int color;
int local_GFX_index;
int temp_palette;
int temp_bit_0;
int temp_bit_1;
int disp_mode;
int pixel;
// each frame contains 263 scanlines
// each scanline consists of 113.5 CPU cycles (fast access) which equates to 454 Maria cycles
// In total there are 29850.5 CPU cycles (fast access) in a frame
@ -115,7 +105,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
Core.tia._hsyncCnt = 0;
Core.cpu.RDY = true;
}
}
// "The end of vblank is made up of a DMA startup plus a long shut down"
@ -165,7 +154,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
// Now proceed with the remaining scanlines
// the first one is a pre-render line, since we didn't actually put any data into the buffer yet
while (scanline < _screen_height)
while (scanline < Core._screen_height)
{
if (cycle == 28 && Core.Maria_regs[0x1C].Bit(6) && !Core.Maria_regs[0x1C].Bit(5))
{
@ -187,20 +176,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
current_DLL_DLI = false;
}
if (overrun_dma && sl_DMA_complete)
{
if (GFX_index == 1)
{
GFX_index = 0;
}
else
{
GFX_index = 1;
}
overrun_dma = false;
}
if (DLI_countdown > 0)
{
DLI_countdown--;
@ -210,15 +185,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
}
if (cycle > 133)
if (cycle == 428 && !sl_DMA_complete && do_dma && (DMA_phase == DMA_GRAPHICS || DMA_phase == DMA_HEADER))
{
bg_temp[cycle - 134] = Core.Maria_regs[0];
}
if (cycle == 453 && !sl_DMA_complete && do_dma && (DMA_phase == DMA_GRAPHICS || DMA_phase == DMA_HEADER))
{
overrun_dma = true;
//Console.WriteLine(scanline);
if (current_DLL_offset == 0)
{
@ -234,31 +202,97 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
Core.RunCPUCycle();
//////////////////////////////////////////////
// Drawing Start
//////////////////////////////////////////////
if (cycle >=133 && cycle < 453 && scanline > 20)
{
pixel = cycle - 133;
local_GFX_index = (GFX_index == 1) ? 0 : 1; // whatever the current index is, we use the opposite
disp_mode = Core.Maria_regs[0x1C] & 0x3;
color = line_ram[local_GFX_index, pixel];
if (disp_mode == 0)
{
// direct read, nothing to do
}
else if (disp_mode == 2) // note: 1 is not used
{
// there is a trick here to be aware of.
// the renderer has no concept of objects, as it only has information on each pixel
// but objects are specified in groups of 8 pixels.
// however, since objects can only be placed in 160 resolution
// we can pick bits based on whether the current pixel is even or odd
temp_palette = color & 0x10;
temp_bit_0 = 0;
temp_bit_1 = 0;
if (pixel % 2 == 0)
{
temp_bit_1 = color & 2;
temp_bit_0 = (color & 8) >> 3;
}
else
{
temp_bit_1 = (color & 1) << 1;
temp_bit_0 = (color & 4) >> 2;
}
color = temp_palette + temp_bit_1 + temp_bit_0;
}
else
{
// same as above, we can use the pixel index to pick the bits out
if (pixel % 2 == 0)
{
color &= 0x1E;
}
else
{
color = (color & 0x1C) + ((color & 1) << 1);
}
}
if ((color & 0x3) != 0)
{
scanline_buffer[pixel] = _palette[Core.Maria_regs[color]];
}
else
{
scanline_buffer[pixel] = _palette[Core.Maria_regs[0x00]];
}
// send buffer to the video buffer
Core._vidbuffer[(scanline - 21) * 320 + pixel] = scanline_buffer[pixel];
// clear the line ram
line_ram[local_GFX_index, pixel] = 0;
}
//////////////////////////////////////////////
// Drawing End
//////////////////////////////////////////////
cycle++;
if (cycle == 454)
{
if (scanline > 20)
{
// add the current graphics to the buffer
draw_scanline(scanline - 21);
}
scanline++;
cycle = 0;
Core.tia._hsyncCnt = 0;
Core.cpu.RDY = true;
// swap sacnline buffers
if (!overrun_dma)
if (GFX_index == 1)
{
if (GFX_index == 1)
{
GFX_index = 0;
}
else
{
GFX_index = 1;
}
GFX_index = 0;
}
else
{
GFX_index = 1;
}
}
}
@ -299,7 +333,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
if (DMA_phase_counter==1)
{
header_counter++;
GFX_Objects[GFX_index, header_counter].addr = ReadMemory((ushort)(current_DLL_addr + header_pointer));
GFX_Objects[header_counter].addr = ReadMemory((ushort)(current_DLL_addr + header_pointer));
header_pointer++;
byte temp = ReadMemory((ushort)(current_DLL_addr + header_pointer));
// if there is no width, then we must have an extended header
@ -324,12 +358,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
else
{
// we are in 5 Byte header mode (i.e. using the character map)
GFX_Objects[GFX_index, header_counter].write_mode = temp.Bit(7);
GFX_Objects[header_counter].write_mode = temp.Bit(7);
global_write_mode = temp.Bit(7);
GFX_Objects[GFX_index, header_counter].ind_mode = temp.Bit(5);
GFX_Objects[header_counter].ind_mode = temp.Bit(5);
header_pointer++;
temp = (byte)(ReadMemory((ushort)(current_DLL_addr + header_pointer)));
GFX_Objects[GFX_index, header_counter].addr |= (ushort)(temp << 8);
GFX_Objects[header_counter].addr |= (ushort)(temp << 8);
header_pointer++;
temp = ReadMemory((ushort)(current_DLL_addr + header_pointer));
int temp_w = (temp & 0x1F); // this is the 2's complement of width (for reasons that escape me)
@ -337,18 +371,18 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
if (temp_w == 0)
{
// important note here. In 5 byte mode, width 0 actually counts as 32
GFX_Objects[GFX_index, header_counter].width = 32;
GFX_Objects[header_counter].width = 32;
}
else
{
temp_w = (temp_w - 1);
temp_w = (0x1F - temp_w);
GFX_Objects[GFX_index, header_counter].width = (byte)(temp_w & 0x1F);
GFX_Objects[header_counter].width = (byte)(temp_w & 0x1F);
}
GFX_Objects[GFX_index, header_counter].palette = (byte)((temp & 0xE0) >> 5);
GFX_Objects[header_counter].palette = (byte)((temp & 0xE0) >> 5);
header_pointer++;
GFX_Objects[GFX_index, header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
GFX_Objects[header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
header_pointer++;
DMA_phase_next = DMA_GRAPHICS;
@ -361,21 +395,21 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
int temp_w = (temp & 0x1F); // this is the 2's complement of width (for reasons that escape me)
temp_w = (temp_w - 1);
temp_w = (0x1F - temp_w);
GFX_Objects[GFX_index, header_counter].width = (byte)(temp_w & 0x1F);
GFX_Objects[header_counter].width = (byte)(temp_w & 0x1F);
GFX_Objects[GFX_index, header_counter].palette = (byte)((temp & 0xE0) >> 5);
GFX_Objects[header_counter].palette = (byte)((temp & 0xE0) >> 5);
header_pointer++;
temp = (byte)(ReadMemory((ushort)(current_DLL_addr + header_pointer)));
GFX_Objects[GFX_index, header_counter].addr |= (ushort)(temp << 8);
GFX_Objects[header_counter].addr |= (ushort)(temp << 8);
header_pointer++;
GFX_Objects[GFX_index, header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
GFX_Objects[header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
header_pointer++;
DMA_phase_next = DMA_GRAPHICS;
GFX_Objects[GFX_index, header_counter].write_mode = global_write_mode;
GFX_Objects[header_counter].write_mode = global_write_mode;
GFX_Objects[GFX_index, header_counter].ind_mode = false;
GFX_Objects[header_counter].ind_mode = false;
header_read_time = 8;
}
@ -396,46 +430,48 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
ushort addr_t = 0;
// in 5 byte mode, we first have to check if we are in direct or indirect mode
if (GFX_Objects[GFX_index, header_counter].ind_mode)
if (GFX_Objects[header_counter].ind_mode)
{
int ch_size = 0;
if (Core.Maria_regs[0x1C].Bit(4))
{
graphics_read_time = 9 * GFX_Objects[GFX_index, header_counter].width;
graphics_read_time = 9 * GFX_Objects[header_counter].width;
ch_size = 2;
GFX_Objects[GFX_index, header_counter].width *= 2;
}
else
{
graphics_read_time = 6 * GFX_Objects[GFX_index, header_counter].width;
graphics_read_time = 6 * GFX_Objects[header_counter].width;
ch_size = 1;
}
// the address here is specified by CHAR_BASE maria registers
// ushort addr = (ushort)(GFX_Objects[header_counter].addr & 0xFF);
for (int i = 0; i < GFX_Objects[GFX_index, header_counter].width; i++)
for (int i = 0; i < GFX_Objects[header_counter].width; i++)
{
addr_t = ReadMemory((ushort)(GFX_Objects[GFX_index, header_counter].addr + i));
addr_t = ReadMemory((ushort)(GFX_Objects[header_counter].addr + i));
addr_t |= (ushort)((Core.Maria_regs[0x14] + current_DLL_offset) << 8);
if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000))
{
if (i * ch_size < 128)
{
GFX_Objects[GFX_index, header_counter].obj[i * ch_size] = 0;
GFX_Objects[header_counter].obj[i * ch_size] = 0;
}
if ((i * ch_size + 1 < 128) && (ch_size == 2))
{
GFX_Objects[GFX_index, header_counter].obj[i * ch_size + 1] = 0;
GFX_Objects[header_counter].obj[i * ch_size + 1] = 0;
}
if (ch_size == 1)
if (i != 0)
{
graphics_read_time -= 6;
}
else
{
graphics_read_time -= 9;
if (ch_size == 1)
{
graphics_read_time -= 6;
}
else
{
graphics_read_time -= 9;
}
}
}
@ -443,31 +479,37 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
if (i * ch_size < 128)
{
GFX_Objects[GFX_index, header_counter].obj[i * ch_size] = ReadMemory(addr_t);
GFX_Objects[header_counter].obj[i * ch_size] = ReadMemory(addr_t);
fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 0, ch_size, GFX_Objects[header_counter].obj[i * ch_size], GFX_Objects[header_counter].write_mode);
}
if (((i * ch_size + 1) < 128) && (ch_size == 2))
{
GFX_Objects[GFX_index, header_counter].obj[i * ch_size + 1] = ReadMemory((ushort)(addr_t + 1));
GFX_Objects[header_counter].obj[i * ch_size + 1] = ReadMemory((ushort)(addr_t + 1));
fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 1, ch_size, GFX_Objects[header_counter].obj[i * ch_size + 1], GFX_Objects[header_counter].write_mode);
}
}
}
}
else
{
graphics_read_time = 3 * GFX_Objects[GFX_index, header_counter].width;
graphics_read_time = 3 * GFX_Objects[header_counter].width;
for (int i = 0; i < GFX_Objects[GFX_index, header_counter].width; i++)
for (int i = 0; i < GFX_Objects[header_counter].width; i++)
{
addr_t = (ushort)(GFX_Objects[GFX_index, header_counter].addr + (current_DLL_offset << 8) + i);
addr_t = (ushort)(GFX_Objects[header_counter].addr + (current_DLL_offset << 8) + i);
if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000))
{
GFX_Objects[GFX_index, header_counter].obj[i] = 0;
graphics_read_time -= 3;
GFX_Objects[header_counter].obj[i] = 0;
if (i != 0)
{
graphics_read_time -= 3;
}
}
else
{
GFX_Objects[GFX_index, header_counter].obj[i] = ReadMemory(addr_t);
GFX_Objects[header_counter].obj[i] = ReadMemory(addr_t);
fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 0, 1, GFX_Objects[header_counter].obj[i], GFX_Objects[header_counter].write_mode);
}
}
}
@ -485,18 +527,20 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
if (DMA_phase == DMA_SHUTDOWN_OTHER)
{
Core.cpu_resume_pending = true;
sl_DMA_complete = true;
current_DLL_offset -= 1; // this is reduced by one for each scanline, which changes where graphics are fetched
header_counter_max[GFX_index] = header_counter;
header_counter = -1;
header_pointer = 0;
if (DMA_phase_counter == 6)
{
Core.cpu_resume_pending = true;
sl_DMA_complete = true;
current_DLL_offset -= 1; // this is reduced by one for each scanline, which changes where graphics are fetched
header_counter = -1;
header_pointer = 0;
}
return;
}
if (DMA_phase == DMA_SHUTDOWN_LAST)
{
if (DMA_phase_counter==6)
if (DMA_phase_counter==12)
{
Core.cpu_resume_pending = true;
sl_DMA_complete = true;
@ -515,7 +559,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
current_DLL_H16 = temp.Bit(6);
current_DLL_H8 = temp.Bit(5);
header_counter_max[GFX_index] = header_counter;
header_counter = -1;
header_pointer = 0;
}
@ -524,298 +567,84 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
}
public void draw_scanline(int scanline)
public void fill_line_ram(int temp_start, int index, int doub_size, int ch_s, byte temp_byte, bool w_m)
{
int local_start;
int local_width;
int local_palette;
int index;
int color;
int local_GFX_index;
local_GFX_index = (GFX_index == 1) ? 0 : 1; // whatever the current index is, we use the opposite
int disp_mode = Core.Maria_regs[0x1C] & 0x3;
for (int i = 0; i < 320; i++)
if (w_m)
{
scanline_buffer[i] = _palette[bg_temp[i]];
}
temp_start = temp_start + index * ch_s * 4 + doub_size * 4;
for (int i = 0; i < header_counter_max[local_GFX_index]; i++)
{
local_start = GFX_Objects[local_GFX_index, i].h_pos;
local_palette = GFX_Objects[local_GFX_index, i].palette;
// the two different rendering paths are basically controlled by write mode
if (GFX_Objects[local_GFX_index, i].write_mode)
for (int z = 0; z < 4; z++)
{
if (disp_mode == 0)
if ((temp_start + z) % 512 < 320)
{
local_width = GFX_Objects[local_GFX_index, i].width;
for (int j = 0; j < local_width; j++)
if (z < 2)
{
for (int k = 3; k >= 0; k--)
{
index = local_start * 2 + j * 4 + (3 - k);
if (index > 511)
{
index -= 512;
}
if (index < 320)
{
color = GFX_Objects[local_GFX_index, i].obj[j];
// this is now the color index (0-3) we choose from the palette
if (k >= 2)
{
color = (((color >> 2) & 0x3) << 2) + ((color >> 6) & 0x3);
}
else
{
color = ((color & 0x3) << 2) + ((color >> 4) & 0x3);
}
if ((color != 0) && (color != 4) && (color != 8) && (color != 12)) // transparent
{
color = ((local_palette & 4) << 2) + color;
color = Core.Maria_regs[color];
scanline_buffer[index] = _palette[color];
}
}
}
temp_check = (byte)((temp_byte & 0xC) + ((temp_byte >> 6) & 0x3));
}
}
else if (disp_mode == 2) // note: 1 is not used
{
local_width = GFX_Objects[local_GFX_index, i].width;
for (int j = 0; j < local_width; j++)
else
{
for (int k = 7; k >= 0; k--)
{
index = local_start * 4 + j * 8 + (7 - k);
if (index > 511)
{
index -= 512;
}
if (index < 320)
{
color = GFX_Objects[local_GFX_index, i].obj[j];
// this is now the color index (0-3) we choose from the palette
if (k >= 6)
{
color = ((color >> 6) & 0x2) + ((color >> 3) & 0x1);
}
else if (k >= 4)
{
color = ((color >> 5) & 0x2) + ((color >> 2) & 0x1);
}
else if (k >= 2)
{
color = ((color >> 4) & 0x2) + ((color >> 1) & 0x1);
}
else
{
color = ((color >> 3) & 0x2) + (color & 0x1);
}
if (color != 0) // transparent
{
color = ((local_palette & 4) << 2) + color;
color = Core.Maria_regs[color];
scanline_buffer[index] = _palette[color];
}
}
}
temp_check = (byte)(((temp_byte & 0x3) << 2) + ((temp_byte >> 4) & 0x3));
}
}
else
{
local_width = GFX_Objects[local_GFX_index, i].width;
for (int j = 0; j < local_width; j++)
if ((temp_check & 3) != 0)
{
for (int k = 3; k >= 0; k--)
{
index = local_start * 2 + j * 4 + (3 - k);
if (index > 511)
{
index -= 512;
}
if (index < 320)
{
color = GFX_Objects[local_GFX_index, i].obj[j];
int temp_color = color;
// this is now the color index (0-3) we choose from the palette
if (k >= 3)
{
color = ((color >> 7) & 0x1);
temp_color = (local_palette & 4) + ((temp_color >> 2) & 3);
}
else if (k >= 2)
{
color = ((color >> 6) & 0x1);
temp_color = (local_palette & 4) + ((temp_color >> 2) & 3);
}
else if (k >= 1)
{
color = ((color >> 5) & 0x1);
temp_color = (local_palette & 4) + (temp_color & 3);
}
else
{
color = ((color >> 4) & 0x1);
temp_color = (local_palette & 4) + (temp_color & 3);
}
if (color != 0) // transparent
{
color = (temp_color << 2) + 2;
color = Core.Maria_regs[color];
scanline_buffer[index] = _palette[color];
}
}
}
line_ram[GFX_index, (temp_start + z) % 512] = temp_check;
line_ram[GFX_index, (temp_start + z) % 512] += (byte)((GFX_Objects[header_counter].palette & 4) << 2);
}
}
}
else
{
if (disp_mode == 0)
{
local_width = GFX_Objects[local_GFX_index, i].width;
for (int j = 0; j < local_width; j++)
else if (Core.Maria_regs[0x1C].Bit(2))
{
for (int k = 7; k >= 0; k--)
{
index = local_start * 2 + j * 8 + (7 - k);
if (index > 511)
{
index -= 512;
}
if (index < 320)
{
color = GFX_Objects[local_GFX_index, i].obj[j];
// this is now the color index (0-3) we choose from the palette
if (k >= 6)
{
color = (color >> 6) & 0x3;
}
else if (k >= 4)
{
color = (color >> 4) & 0x3;
}
else if (k >= 2)
{
color = (color >> 2) & 0x3;
}
else
{
color = color & 0x3;
}
if (color != 0) // transparent
{
color = Core.Maria_regs[local_palette * 4 + color];
scanline_buffer[index] = _palette[color];
}
}
}
}
}
else if (disp_mode == 2) // note: 1 is not used
{
local_width = GFX_Objects[local_GFX_index, i].width;
// here the palette is determined by palette bit 2 only
// hence only palette 0 or 4 is available
local_palette = GFX_Objects[local_GFX_index, i].palette & 0x4;
int temp_c0 = GFX_Objects[local_GFX_index, i].palette & 0x1;
int temp_c1 = GFX_Objects[local_GFX_index, i].palette & 0x2;
for (int j = 0; j < local_width; j++)
{
for (int k = 7; k >= 0; k--)
{
color = (GFX_Objects[local_GFX_index, i].obj[j] >> k) & 1;
color = (color << 1) | ((k % 2 == 0) ? temp_c0 : temp_c1);
index = local_start * 2 + j * 8 + (7 - k);
if (index > 511) index -= 512;
if (index < 320)
{
color = Core.Maria_regs[local_palette + color];
scanline_buffer[index] = _palette[color];
}
}
}
}
else
{
local_width = GFX_Objects[local_GFX_index, i].width;
for (int j = 0; j < local_width; j++)
{
for (int k = 7; k >= 0; k--)
{
color = (GFX_Objects[local_GFX_index, i].obj[j] >> k) & 1;
index = local_start * 2 + j * 8 + (7 - k);
if (index > 511) index -= 512;
if (index < 320 && color == 1)
{
color = Core.Maria_regs[local_palette * 4 + 2]; // automatically use index 2 here
scanline_buffer[index] = _palette[color];
}
}
// kangaroo mode, override transparency with zero
line_ram[GFX_index, (temp_start + z) % 512] = 0;
}
}
}
}
// send buffer to the video buffer
for (int i = 0; i < 320; i ++)
else
{
_vidbuffer[scanline * 320 + i] = scanline_buffer[i];
temp_start = temp_start + index * ch_s * 8 + doub_size * 8;
for (int z = 0; z < 8; z++)
{
if (((temp_start + z) % 512) < 320)
{
if (z < 2)
{
temp_check = (byte)((temp_byte >> 6) & 0x3);
}
else if (z < 4)
{
temp_check = (byte)((temp_byte >> 4) & 0x3);
}
else if (z < 6)
{
temp_check = (byte)((temp_byte >> 2) & 0x3);
}
else
{
temp_check = (byte)(temp_byte & 0x3);
}
if (temp_check != 0)
{
line_ram[GFX_index, (temp_start + z) % 512] = temp_check;
line_ram[GFX_index, (temp_start + z) % 512] += (byte)(GFX_Objects[header_counter].palette << 2);
}
else if (Core.Maria_regs[0x1C].Bit(2))
{
// kangaroo mode, override transparency with zero
line_ram[GFX_index, (temp_start + z) % 512] = 0;
}
}
}
}
}
public void Reset()
{
_vidbuffer = new int[VirtualWidth * VirtualHeight];
for (int j = 0; j < 2; j++)
for (int i = 0; i < 128; i++)
{
for (int i = 0; i < 128; i++)
{
GFX_Objects[j, i].obj = new byte[128];
}
}
GFX_Objects[i].obj = new byte[128];
}
}
// Most of the Maria state is captured in Maria Regs in the core

View File

@ -34,6 +34,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
else
{
slow_access = true;
return tia.ReadMemory((ushort)(addr & 0x1F), false);
}
}
@ -45,16 +46,17 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
else
{
return 0xFF; // TODO: What if Maria is off?
return 0x80; // TODO: What if Maria is off?
}
}
else if ((addr & 0xFF80) == 0x280)
{
//return regs_6532[addr & 0x1F];
slow_access = true;
return m6532.ReadMemory(addr, false);
}
else if ((addr & 0xFE80) == 0x480)
{
slow_access = true;
return RAM_6532[addr & 0x7F];
}
else if ((addr >= 0x1800) && (addr < 0x2800))
@ -105,10 +107,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
// return TIA registers or control register if it is still unlocked
if ((A7800_control_register & 0x1) == 0)
{
A7800_control_register = value;
A7800_control_register = value;
}
else
{
slow_access = true;
tia.WriteMemory((ushort)(addr & 0x1F), value, false);
}
}
@ -140,10 +143,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
else if ((addr & 0xFF80) == 0x280)
{
slow_access = true;
m6532.WriteMemory(addr, value);
}
else if ((addr & 0xFE80) == 0x480)
{
slow_access = true;
RAM_6532[addr & 0x7F] = value;
}
else if ((addr >= 0x1800) && (addr < 0x2800))

View File

@ -1 +1,8 @@
todo:
TODO:
Pokey: used in Ball Blazer and Commando as well as some homebrew
A2600 mode: used in diagnostic cart
Color Artifacting: used in Tower Toppler
Emulation:
Check timer in One on One Basketball
Water Ski tow line glitch, does it happen on console?

View File

@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
_capChargeStart = 0;
_capCharging = false;
AudioClocks = 0;
_spf = (Core.maria._frameHz > 55) ? 740 : 880;
_spf = (Core._frameHz > 55) ? 740 : 880;
_doTicks = false;
}
@ -154,7 +154,14 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
if (!Core.p1_is_2button)
{
return Core.p1_fire;
if (!Core.p1_is_lightgun)
{
return Core.p1_fire;
}
else
{
return Core.lg_1_trigger_hit;
}
}
else if ((Core.m6532._outputB & 0x04) != 0 || (Core.m6532._ddRb & 0x04) != 0x04)
{
@ -169,10 +176,16 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
if (maskedAddr == 0x0D) // INPT5
{
Core._islag = false;
if (!Core.p2_is_2button)
{
return Core.p2_fire;
if (!Core.p2_is_lightgun)
{
return Core.p2_fire;
}
else
{
return Core.lg_2_trigger_hit;
}
}
else if ((Core.m6532._outputB & 0x10) != 0 || (Core.m6532._ddRb & 0x10) != 0x10)
{

View File

@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
"https://sameboy.github.io/", false)]
public class Sameboy : WaterboxCore,
IGameboyCommon, ISaveRam,
ISettable<object, Sameboy.SyncSettings>
ISettable<Sameboy.Settings, Sameboy.SyncSettings>
{
/// <summary>
/// the nominal length of one frame
@ -38,20 +38,20 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
private bool _sgb;
[CoreConstructor("SGB")]
public Sameboy(byte[] rom, CoreComm comm, SyncSettings syncSettings, bool deterministic)
: this(rom, comm, true, syncSettings, deterministic)
public Sameboy(byte[] rom, CoreComm comm, Settings settings, SyncSettings syncSettings, bool deterministic)
: this(rom, comm, true, settings, syncSettings, deterministic)
{ }
[CoreConstructor("GB")]
public Sameboy(CoreComm comm, byte[] rom, SyncSettings syncSettings, bool deterministic)
: this(rom, comm, false, syncSettings, deterministic)
public Sameboy(CoreComm comm, byte[] rom, Settings settings, SyncSettings syncSettings, bool deterministic)
: this(rom, comm, false, settings, syncSettings, deterministic)
{ }
public Sameboy(byte[] rom, CoreComm comm, bool sgb, SyncSettings syncSettings, bool deterministic)
public Sameboy(byte[] rom, CoreComm comm, bool sgb, Settings settings, SyncSettings syncSettings, bool deterministic)
: base(comm, new Configuration
{
DefaultWidth = sgb ? 256 : 160,
DefaultHeight = sgb ? 224 : 144,
DefaultWidth = sgb && (settings == null || settings.ShowSgbBorder) ? 256 : 160,
DefaultHeight = sgb && (settings == null || settings.ShowSgbBorder) ? 224 : 144,
MaxWidth = sgb ? 256 : 160,
MaxHeight = sgb ? 224 : 144,
MaxSamples = 1024,
@ -74,6 +74,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
_sgb = sgb;
Console.WriteLine("Automaticly detected CGB to " + _cgb);
_syncSettings = syncSettings ?? new SyncSettings();
_settings = settings ?? new Settings();
var bios = _syncSettings.UseRealBIOS && !sgb
? comm.CoreFileProvider.GetFirmware(_cgb ? "GBC" : "GB", "World", true)
@ -179,8 +180,31 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
#region ISettable
private Settings _settings;
private SyncSettings _syncSettings;
public class Settings
{
[DisplayName("Show SGB Border")]
[DefaultValue(true)]
public bool ShowSgbBorder { get; set; }
public Settings Clone()
{
return (Settings)MemberwiseClone();
}
public static bool NeedsReboot(Settings x, Settings y)
{
return false;
}
public Settings()
{
SettingsUtil.SetDefaultValues(this);
}
}
public class SyncSettings
{
[DisplayName("Initial Time")]
@ -213,9 +237,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
}
}
public object GetSettings()
public Settings GetSettings()
{
return null;
return _settings.Clone();
}
public SyncSettings GetSyncSettings()
@ -223,9 +247,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
return _syncSettings.Clone();
}
public bool PutSettings(object o)
public bool PutSettings(Settings o)
{
return false;
var ret = Settings.NeedsReboot(_settings, o);
_settings = o;
return ret;
}
public bool PutSyncSettings(SyncSettings o)
@ -246,10 +272,29 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
};
}
protected override void FrameAdvancePost()
protected unsafe override void FrameAdvancePost()
{
if (_scanlineCallback != null && _scanlineCallbackLine == -1)
_scanlineCallback(_core.GetIoReg(0x40));
if (_sgb && !_settings.ShowSgbBorder)
{
fixed(int *buff = _videoBuffer)
{
int* dst = buff;
int* src = buff + (224 - 144) / 2 * 256 + (256 - 160) / 2;
for (int j = 0; j < 144; j++)
{
for (int i = 0; i < 160; i++)
{
*dst++ = *src++;
}
src += 256 - 160;
}
}
BufferWidth = 160;
BufferHeight = 144;
}
}
protected override void LoadStateBinaryInternal(BinaryReader reader)

View File

@ -1,133 +0,0 @@
using BizHawk.Common;
using BizHawk.Common.NumberExtensions;
namespace BizHawk.Emulation.Cores.Nintendo.NES
{
public sealed class Mapper035 : NES.NESBoardBase
{
private ByteBuffer reg = new ByteBuffer(8);
private ByteBuffer chr = new ByteBuffer(8);
private int prg_bank_mask_8k;
private int chr_bank_mask_1k;
private bool IRQa;
private int IRQCount;
public override bool Configure(NES.EDetectionOrigin origin)
{
switch (Cart.board_type)
{
case "MAPPER035":
break;
default:
return false;
}
prg_bank_mask_8k = Cart.prg_size / 8 - 1;
chr_bank_mask_1k = Cart.chr_size / 1 - 1;
SetMirrorType(Cart.pad_h, Cart.pad_v);
return true;
}
public override void Dispose()
{
reg.Dispose();
chr.Dispose();
base.Dispose();
}
public override void SyncState(Serializer ser)
{
ser.Sync("reg", ref reg);
ser.Sync("chr", ref chr);
ser.Sync("IRQa", ref IRQa);
ser.Sync("IRQCount", ref IRQCount);
base.SyncState(ser);
}
public override byte ReadEXP(int addr)
{
if (addr == 0x800)
{
return 0x20;
}
return base.ReadEXP(addr);
}
private void SetMirror()
{
SetMirrorType(reg[3].Bit(0) ? EMirrorType.Horizontal : EMirrorType.Vertical);
}
public override void WritePRG(int addr, byte value)
{
addr += 0x8000;
switch (addr)
{
case 0x8000: reg[0] = value; break;
case 0x8001: reg[1] = value; break;
case 0x8002: reg[2] = value; break;
case 0x9000: chr[0] = value; break;
case 0x9001: chr[1] = value; break;
case 0x9002: chr[2] = value; break;
case 0x9003: chr[3] = value; break;
case 0x9004: chr[4] = value; break;
case 0x9005: chr[5] = value; break;
case 0x9006: chr[6] = value; break;
case 0x9007: chr[7] = value; break;
case 0xC002: IRQa = false; IRQSignal = false; break;
case 0xC005: IRQCount = value; break;
case 0xC003: IRQa = true; break;
case 0xD001: reg[3] = value;
SetMirror(); break;
}
}
public override byte ReadPRG(int addr)
{
int index = addr >> 13;
int bank = reg[index];
if (index == 3) { bank = 0xFF; }
bank &= prg_bank_mask_8k;
return ROM[(bank << 13) + (addr & 0x1FFF)];
}
public override byte ReadPPU(int addr)
{
if (addr < 0x2000)
{
int index = addr >> 10;
int bank = chr[index];
bank &= chr_bank_mask_1k;
return VROM[(bank << 10) + (addr & 0x3FF)];
}
return base.ReadPPU(addr);
}
public override void ClockCPU()
{
IrqHook(1);
}
private void IrqHook(int a)
{
if (IRQa)
{
IRQCount += a;
if (IRQCount > 0x10000)
{
IRQSignal = true;
IRQa = false;
}
}
}
}
}

View File

@ -33,6 +33,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
bool mapper_090 = false;
bool mapper_209 = false;
bool mapper_211 = false;
bool mapper_035 = false;
bool nt_advanced_control = false;
bool nt_ram_disable = false;
@ -67,6 +68,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
switch (Cart.board_type)
{
case "MAPPER035":
mapper_035 = true;
break;
case "MAPPER090":
case "UNIF_UNL-TEK90":
mapper_090 = true;
@ -148,6 +152,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync("sram_prg", ref sram_prg);
ser.Sync("ram_bank", ref ram_bank);
ser.Sync("mapper_035", ref mapper_035);
ser.Sync("mapper_090", ref mapper_090);
ser.Sync("mapper_209", ref mapper_209);
ser.Sync("mapper_211", ref mapper_211);
@ -465,10 +470,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
SetMirrorType(EMirrorType.Horizontal);
break;
case 2:
SetMirrorType(EMirrorType.OneScreenA);
if (mapper_035)
{
SetMirrorType(EMirrorType.OneScreenB);
}
else
{
SetMirrorType(EMirrorType.OneScreenA);
}
break;
case 3:
SetMirrorType(EMirrorType.OneScreenB);
if (mapper_035)
{
SetMirrorType(EMirrorType.OneScreenA);
}
else
{
SetMirrorType(EMirrorType.OneScreenB);
}
break;
}
break;

View File

@ -1,5 +1,6 @@
using BizHawk.Common;
using BizHawk.Common.NumberExtensions;
using System;
namespace BizHawk.Emulation.Cores.Nintendo.NES
{
@ -25,6 +26,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
bool irq_mode;
bool irq_reload_pending;
int separator_counter;
int irq_countdown_2 = 0;
bool clock_scanline_irq;
public override void Dispose()
@ -172,20 +175,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
case 0x4001:
irq_mode = value.Bit(0);
if (irq_mode) irq_countdown = 12;
if (irq_mode) irq_countdown = 4;
irq_reload_pending = true;
break;
case 0x6000:
irq_enable = false;
irq_pending = false;
irq_counter = 0;
SyncIRQ();
break;
case 0x6001:
irq_enable = true;
SyncIRQ();
break;
}
}
@ -224,20 +227,79 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
irq_counter = irq_reload + 1;
irq_reload_pending = false;
if (irq_counter == 0)
{
if (irq_enable)
{
irq_countdown_2 = 9;
}
}
}
else if (irq_counter == 0)
irq_counter--;
if (irq_counter==0)
{
if (irq_enable)
{
irq_countdown_2 = 9;
}
irq_counter = irq_reload + 1;
}
if (irq_counter < 0)
{
irq_counter = irq_reload;
}
/*
else if (irq_counter == 0)
{
irq_counter = irq_reload;
if (irq_counter == 0)
{
if (irq_enable)
{
irq_countdown_2 = 9;
}
}
}
else
{
irq_counter--;
if (irq_counter == 0 && irq_enable)
if (irq_enable)
{
irq_pending = true;
SyncIRQ();
}
if (irq_counter==0)
irq_countdown_2 = 9;
}
}
*/
}
public override void ClockCPU()
{
if (irq_mode == true)
{
irq_countdown--;
if (irq_countdown == 0)
{
ClockIRQ();
irq_countdown = 4;
}
}
else
{
if (clock_scanline_irq)
{
clock_scanline_irq = false;
ClockIRQ();
}
}
}
public override void ClockPPU()
@ -245,14 +307,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (separator_counter > 0)
separator_counter--;
if (irq_countdown > 0)
if (irq_countdown_2 > 0)
{
irq_countdown--;
if (irq_countdown == 0)
irq_countdown_2--;
if (irq_countdown_2==0)
{
ClockIRQ();
if (irq_mode==true)
irq_countdown = 12;
irq_pending = true;
SyncIRQ();
}
}
}
@ -270,7 +331,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
else
{
separator_counter = 15;
irq_countdown = 11;
clock_scanline_irq = true;
}
}

View File

@ -297,6 +297,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ppur.status.cycle++;
is_even_cycle = !is_even_cycle;
if (PPUON && ppur.status.cycle >= 257 && ppur.status.cycle <= 320 && 0 <= ppur.status.sl && ppur.status.sl <= 240)
{
reg_2003 = 0;
}
// Here we execute a CPU instruction if enough PPU cycles have passed
// also do other things that happen at instruction level granularity
cpu_stepcounter++;

View File

@ -40,10 +40,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
show_obj_leftmost = (value >> 2) & 1;
show_bg = (value >> 3) & 1;
show_obj = (value >> 4) & 1;
intense_green = (value >> 5) & 1;
intense_blue = (value >> 6) & 1;
intense_red = (value >> 7) & 1;
intensity_lsl_6 = ((value >> 5) & 7)<<6;
intense_green = (value >> 5) & 1;
intensity_lsl_6 = ((value >> 5) & 7)<<6;
}
}
}
@ -427,10 +427,33 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//OAM DATA (write)
void write_2004(byte value)
{
if ((reg_2003 & 3) == 2) value &= 0xE3; //some of the OAM bits are unwired so we mask them out here
//otherwise we just write this value and move on to the next oam byte
OAM[reg_2003] = value;
reg_2003++;
if ((reg_2003 & 3) == 2)
{
//some of the OAM bits are unwired so we mask them out here
//otherwise we just write this value and move on to the next oam byte
value &= 0xE3;
}
if (0 <= ppur.status.sl && ppur.status.sl <= 240)
{
// don't write to OAM if the screen is on and we are in the active display area
// this impacts sprite evaluation
if (show_bg_new || show_obj_new)
{
// glitchy increment of OAM index
oam_index += 4;
}
else
{
OAM[reg_2003] = value;
reg_2003++;
}
}
else
{
OAM[reg_2003] = value;
reg_2003++;
}
}
byte read_2004()
{

View File

@ -166,7 +166,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//Not sure if this is correct. According to Matt Conte and my own tests, it is. Timing is probably off, though.
//NOTE: Not having this here breaks a Super Donkey Kong game.
if (PPUON) reg_2003 = 0;
//if (PPUON) reg_2003 = 0;
//this was repeatedly finetuned from the fceux days thrugh the old cpu core and into the new one to pass 05-nmi_timing.nes
//note that there is still some leniency. for instance, 4,2 will pass in addition to 3,3
@ -207,13 +207,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
yp = sl - 1;
ppuphase = PPUPHASE.BG;
// "If PPUADDR is not less then 8 when rendering starts, the first 8 bytes in OAM and written to from
// the current location off PPUADDR"
// "If PPUADDR is not less then 8 when rendering starts, the first 8 bytes in OAM are written to from
// the current location of PPUADDR"
if (sl == 0 && PPUON && reg_2003 >= 8 && region==Region.NTSC)
{
for (int i = 0; i < 8; i++)
{
OAM[i] = OAM[reg_2003 & 0xF8 + i];
OAM[i] = OAM[(reg_2003 & 0xF8) + i];
}
}
@ -258,7 +258,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (ppur.status.cycle == 64)
{
soam_index = 0;
oam_index = 0;// reg_2003;
oam_index = reg_2003;
}
// otherwise, scan through OAM and test if sprites are in range
@ -297,7 +297,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (yp >= read_value && yp < read_value + spriteHeight && spr_true_count == 0)
{
//a flag gets set if sprite zero is in range
if (oam_index == 0)//reg_2003)
if (oam_index == reg_2003)
sprite_zero_in_range = true;
spr_true_count++;
@ -769,7 +769,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{ }
else
runppu(1);
} // scanline loop
ppur.status.sl = 241;

View File

@ -297,21 +297,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
return new LibWaterboxCore.FrameInfo();
}
protected override void FrameAdvancePost()
{
_virtualHeight = BufferHeight;
_virtualWidth = BufferWidth;
if (_virtualHeight * 2 < _virtualWidth)
_virtualHeight *= 2;
if (_virtualHeight > 240)
_virtualWidth = 512;
_virtualWidth = (int)Math.Round(_virtualWidth * 1.146);
}
private int _virtualWidth;
private int _virtualHeight;
public override int VirtualWidth => _virtualWidth;
public override int VirtualHeight => _virtualHeight;
public override int VirtualWidth => BufferWidth == 256 && BufferHeight <= 240 ? 293 : 587;
public override int VirtualHeight => BufferHeight <= 240 && BufferWidth == 512 ? BufferHeight * 2 : BufferHeight;
#region IStatable

View File

@ -151,8 +151,8 @@ namespace BizHawk.Emulation.Cores.Libretro
public retro_system_info retro_system_info;
public retro_system_av_info retro_system_av_info;
public uint retro_serialize_size_initial; //size_t :(
public uint retro_serialize_size; //size_t :(
public ulong retro_serialize_size_initial; //size_t :(
public ulong retro_serialize_size; //size_t :(
public uint retro_region;
public uint retro_api_version;

View File

@ -62,7 +62,7 @@ namespace BizHawk.Emulation.Cores.Libretro
{
Message(eMessage.CMD_UpdateSerializeSize);
WaitForCMD();
return comm->env.retro_serialize_size;
return (uint)comm->env.retro_serialize_size;
}
public bool CMD_Serialize(byte[] data)

View File

@ -30,7 +30,7 @@ namespace BizHawk.Emulation.Cores.Libretro
public sbyte* valid_extensions;
public bool need_fullpath;
public bool block_extract;
public short pad;
short _pad;
}
public struct retro_system_timing

View File

@ -375,7 +375,7 @@ namespace BizHawk.Emulation.Cores.Libretro
public void SaveStateBinary(System.IO.BinaryWriter writer)
{
api.CMD_UpdateSerializeSize();
if (savebuff == null || savebuff.Length != api.comm->env.retro_serialize_size)
if (savebuff == null || savebuff.Length != (int)api.comm->env.retro_serialize_size)
{
savebuff = new byte[api.comm->env.retro_serialize_size];
savebuff2 = new byte[savebuff.Length + 13];
@ -406,7 +406,7 @@ namespace BizHawk.Emulation.Cores.Libretro
public byte[] SaveStateBinary()
{
api.CMD_UpdateSerializeSize();
if (savebuff == null || savebuff.Length != api.comm->env.retro_serialize_size)
if (savebuff == null || savebuff.Length != (int)api.comm->env.retro_serialize_size)
{
savebuff = new byte[api.comm->env.retro_serialize_size];
savebuff2 = new byte[savebuff.Length + 13];

View File

@ -507,7 +507,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
long ret = 0;
for (int i = 0; i < iovcnt; i++)
ret += Write(fd, iov[i].Base, iov[i].Length);
{
if (iov[i].Base != IntPtr.Zero)
ret += Write(fd, iov[i].Base, iov[i].Length);
}
return ret;
}

View File

@ -60,8 +60,10 @@ namespace BizHawk.Emulation.DiscSystem
_disc = disc;
_dsr = new DiscSectorReader(disc);
//the first check for mode 0 should be sufficient for blocking attempts to read audio sectors, so dont do this
//dsr.Policy.ThrowExceptions2048 = false;
//the first check for mode 0 should be sufficient for blocking attempts to read audio sectors
//but github #928 had a data track with an audio sector
//so let's be careful here.. we're just trying to ID things, not be robust
_dsr.Policy.ThrowExceptions2048 = false;
}
private readonly Disc _disc;
@ -74,14 +76,13 @@ namespace BizHawk.Emulation.DiscSystem
/// </summary>
public DiscType DetectDiscType()
{
//check track 1's data type. if it's an audio track, further data-track testing is useless
//furthermore, it's probably senseless (no binary data there to read)
//however a sector could mark itself as audio without actually being.. we'll just wait for that one.
// not fully tested yet
if (DetectPCFX())
return DiscType.PCFX;
//check track 1's data type. if it's an audio track, further data-track testing is useless
//furthermore, it's probably senseless (no binary data there to read)
//NOTE: PCE-CD detection goes through here (no good way to detect PCE cd)
if (!_disc.TOC.TOCItems[1].IsData)
return DiscType.AudioDisc;
@ -179,7 +180,9 @@ namespace BizHawk.Emulation.DiscSystem
if (!_sectorCache.TryGetValue(lba, out data))
{
data = new byte[2048];
_dsr.ReadLBA_2048(lba, data, 0);
int read = _dsr.ReadLBA_2048(lba, data, 0);
if (read != 2048)
return null;
_sectorCache[lba] = data;
}
return data;
@ -188,6 +191,7 @@ namespace BizHawk.Emulation.DiscSystem
private bool StringAt(string s, int n, int lba = 0)
{
var data = ReadSectorCached(lba);
if (data == null) return false;
byte[] cmp = System.Text.Encoding.ASCII.GetBytes(s);
byte[] cmp2 = new byte[cmp.Length];
Buffer.BlockCopy(data, n, cmp2, 0, cmp.Length);

View File

@ -35,7 +35,7 @@ rem explicitly list the OK ones here as individual copies. until then....
copy *.dll dll
rem Now, we're about to zip and then unzip. Why, you ask? Because that's just the way this evolved.
..\dist\zip.exe -X -r ..\Dist\%NAME% EmuHawk.exe DiscoHawk.exe defctrl.json dll shaders gamedb Tools NES\Palettes Lua Gameboy\Palettes -x *.pdb -x *.lib -x *.pgd -x *.ipdb -x *.iobj -x *.exp -x dll\libsneshawk-64*.exe -x *.ilk -x dll\gpgx.elf -x dll\miniclient.*
..\dist\zip.exe -X -r ..\Dist\%NAME% EmuHawk.exe EmuHawk.exe.config DiscoHawk.exe DiscoHawk.exe.config defctrl.json dll shaders gamedb Tools NES\Palettes Lua Gameboy\Palettes -x *.pdb -x *.lib -x *.pgd -x *.ipdb -x *.iobj -x *.exp -x dll\libsneshawk-64*.exe -x *.ilk -x dll\gpgx.elf -x dll\miniclient.*
cd ..\Dist
.\unzip.exe %NAME% -d temp

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
This repository contains original work chiefly in c# by the BizHawk team (which is all provided under the MIT License), embedded submodules from other authors with their own licenses clearly provided, other embedded submodules from other authors WITHOUT their own licenses clearly provided, customizations by the BizHawk team to many of those submodules (which is provided under the MIT license), and compiled binary executable modules from other authors without their licenses OR their origins clearly indicated.
Due to the high degree of licensing heterogeneity of this repository and the nature of some of the licenses contained therein, its condition as-is should be considered an illegal combination of several incompatible GPL licenses.
However, if many of the C/C++ emulation cores were removed, the result would be an almost pristine MIT-licensed work. We are therefore providing this repository "under the MIT license" with the expectation that the c# parts of the remaining "frontend" elements authored the BizHawk team is what will be of interest to most people; and besides, those elements constitute the bulk of the original work.
In short, individuals with a keen interest in the licensing details of any portion of this repository should contact us or else assume it is a minefield.
--------------------------
All of the BizHawk team's original work is provided under this license:
--------------------------
MIT License
Copyright (c) BizHawk team
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,3 +1,5 @@
# BizHawk
BizHawk is a multi-system emulator written in C#. BizHawk provides nice features for casual gamers such as fullscreen, rewind, and joypad support in addition to rerecording and debugging tools for all system cores.
[Release Notes](http://tasvideos.org/Bizhawk/ReleaseHistory.html)

Binary file not shown.

View File

@ -132,7 +132,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.15\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.8\include;..\..\..\mupen64plus-win32-deps\libpng-1.6.18\include;..\..\..\mupen64plus-win32-deps\freetype-2.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>DBG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@ -156,13 +156,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<<<<<<< HEAD
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.15\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.8\include;..\..\..\mupen64plus-win32-deps\libpng-1.6.18\include;..\..\..\mupen64plus-win32-deps\freetype-2.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
=======
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>DBG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
>>>>>>> master
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
@ -188,7 +183,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.15\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.8\include;..\..\..\mupen64plus-win32-deps\libpng-1.6.18\include;..\..\..\mupen64plus-win32-deps\freetype-2.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>DBG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>

Binary file not shown.

Binary file not shown.

Binary file not shown.