Merge pull request #1051 from TASVideos/master

Sync Master to GBHawk
This commit is contained in:
alyosha-tas 2017-11-09 08:50:48 -05:00 committed by GitHub
commit b2d453441e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
157 changed files with 10630 additions and 16036 deletions

2
.gitignore vendored
View File

@ -2,7 +2,7 @@
/snes9xgit
svnrev.cs
.vs/**
**/bin/**
**/obj/**
/output/**

View File

@ -743,6 +743,34 @@
"P2 B1": "",
"P2 B2": ""
},
"SMS Paddle Controller": {
"P1 Left": "LeftArrow, J1 POV1L",
"P1 Right": "RightArrow, J1 POV1R",
"P1 B1": "Z, J1 B1, X1 X",
"Reset": "J1 B9, X1 Back",
"Pause": "J1 B10, X1 Start"
},
"SMS Light Phaser Controller": {
"P1 Trigger": "Z, J1 B1, X1 X, WMouse L",
"Reset": "J1 B9, X1 Back",
"Pause": "J1 B10, X1 Start"
},
"SMS Sports Pad Controller": {
"P1 Up": "UpArrow, J1 POV1U",
"P1 Down": "DownArrow, J1 POV1D",
"P1 Left": "LeftArrow, J1 POV1L",
"P1 Right": "RightArrow, J1 POV1R",
"P1 B1": "Z, J1 B1, X1 X",
"P1 B2": "X, J1 B2, X1 A",
"Reset": "J1 B9, X1 Back",
"Pause": "J1 B10, X1 Start",
"P2 Up": "",
"P2 Down": "",
"P2 Left": "",
"P2 Right": "",
"P2 B1": "",
"P2 B2": ""
},
"GG Controller": {
"P1 Up": "UpArrow, J1 POV1U, X1 DpadUp, X1 LStickUp",
"P1 Down": "DownArrow, J1 POV1D, X1 DpadDown, X1 LStickDown",
@ -1567,6 +1595,47 @@
"Mult": 1.0,
"Deadzone": 0.1
}
},
"SMS Paddle Controller": {
"P1 Paddle": {
"Value": "X1 LeftThumbX",
"Mult": 1.0,
"Deadzone": 0.1
}
},
"SMS Light Phaser Controller": {
"P1 X": {
"Value": "WMouse X",
"Mult": 1.0,
"Deadzone": 0.0
},
"P1 Y": {
"Value": "WMouse Y",
"Mult": 1.0,
"Deadzone": 0.0
}
},
"SMS Sports Pad Controller": {
"P1 X": {
"Value": "X1 LeftThumbX",
"Mult": 1.0,
"Deadzone": 0.1
},
"P1 Y": {
"Value": "X1 LeftThumbY",
"Mult": -1.0,
"Deadzone": 0.1
},
"P2 X": {
"Value": "X2 LeftThumbX",
"Mult": 1.0,
"Deadzone": 0.1
},
"P2 Y": {
"Value": "X2 LeftThumbY",
"Mult": -1.0,
"Deadzone": 0.1
}
}
}
}

View File

@ -298,6 +298,8 @@ sha1:CEFEBA536DB507DBDEF8A538F9C332D7A75BF613 You Ling Xing Dong (Ch) NES boar
sha1:DBFCC70CC2DEC7A889429ED542267F0F1BD967BF Ying Xiong Chuan Qi (Ch) NES board=MAPPER224
sha1:FFB4706E49B826C6CDD12E502E8AE94FC9810B7F Monty no Doki Doki Daisassou (FDS Conversion) (Unl) [U][!] NES board=UNIF_UNL-LH32;WRAM=8;VRAM=8;PAD_H=1
sha1:17473C223453D2D80FCB9DCFA317947287DC5C52 Xing He Zhan Shi (China) (Unl) NES board=WAIXINGMAPPER176
sha1:B1C74236FD17FAB4AB9AA6AB28E38864C66D6255 Pocahontus (UNL) NES board=MAPPER182;PRG=256;CHR=256;WRAM=8;PAD_H=1
sha1:5FA23F88432006DCF6874EA36E9E7DA8934427BE Super Donkey Kong (Unl) NES board=MAPPER182;PRG=128;CHR=128;WRAM=8;PAD_H=1
;wrong vram info
sha1:32D71DD6C5A8D78A918FE1B9D6D6C4A570D9652D Oeka Kids Anpanman no Hiragana Daisuki (J) NES board=MAPPER096;VRAM=32

View File

@ -231,7 +231,7 @@ B19256C6716147A9744F5BD528F14450 Magic Knight Rayearth 2 - Making of Magic Knig
846D48D0F4024C8094117599D0E1EEF1 Magic Knight Rayearth (J) GG SRAM=8192 Japan
E496FF2196C372F4D6111538950D25CA Magical Puzzle Popils (W) (En,Ja) GG Puzzle SRAM=8192 World
3AF0C6DDF5F00A493E1F159FCEDC0933 Magical Taruruuto-kun (J) GG Japan
B0C35BC53AB7C184D34E5624F69AAD24 The Majors Pro Baseball (U) GG Sports;Baseball SRAM=128;GGLink USA
B0C35BC53AB7C184D34E5624F69AAD24 The Majors Pro Baseball (U) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA
A15C5219F766D516D1B8D9A09B9A2BB4 Mappy (J) GG Japan
B83F36FD113A8F75F1A29652ACB641FC Marble Madness (UE) GG Arcade USA;Europe
BA846684A66E90372C3C234955EE28BC Marko's Magic Football (E) (En,Fr,De,Es) GG Europe
@ -461,9 +461,9 @@ A23E89266DDAD3C856E7401D04A49C6C Woody Pop (W) (Rev 1) GG World
13F72ACFEA47587F9AA9F655BF98653C World Class Leader Board Golf (UE) GG Sports;Golf USA;Europe
D95D381C6AFFB8345EE5457655E393D1 World Cup USA 94 (UE) (En,Fr,De,Es,It,Nl,Pt,Sv) GG Sports;Soccer USA;Europe
D8939B64458FAF174CDC1241F777CB59 World Derby (J) GG GGLink Japan
E7EABBFC7A1F1339C4720249AEA92A32 World Series Baseball '95 (U) GG Sports;Baseball SRAM=128;GGLink USA
59359FC38865CFF00C90D6EB148DDC2F World Series Baseball (U) GG Sports;Baseball SRAM=128;GGLink USA
05CAC33029F0CAAC27774504C1AA8597 World Series Baseball (U) (Rev 1) GG Sports;Baseball SRAM=128;GGLink USA
E7EABBFC7A1F1339C4720249AEA92A32 World Series Baseball '95 (U) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA
59359FC38865CFF00C90D6EB148DDC2F World Series Baseball (U) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA
05CAC33029F0CAAC27774504C1AA8597 World Series Baseball (U) (Rev 1) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA
D810E851AD60ED5BA50B6246C2CE12F2 WWF Raw (UE) GG Sports;Wrestling USA;Europe
571AC03B80E3075C699CD583BF8651FD X-Men - Gamemaster's Legacy (UE) GG Marvel USA;Europe
CA15F2BA2507EBD836C42D9D10231EB1 X-Men - Mojo World (UE) GG Marvel USA;Europe

View File

@ -106,7 +106,7 @@ F2535DF9BDC3A84221303FA62D61AD6E Back to the Future Part II (E) SMS Europe
3D24A52E98E6C85D7C059386451CE749 Back to the Future Part III (E) SMS PAL Europe
8A94DED3D95AA46DAE8800B92E66D3EE Baku Baku (B) SMS Brazil
7A5D3B9963E316CB7F73BBDC2A7311C6 Bank Panic (E) SMS Europe
26DF4404950CB8DA47235833C0C101C6 Bart vs. the Space Mutants (E) SMS Europe
26DF4404950CB8DA47235833C0C101C6 Bart vs. the Space Mutants (E) SMS PAL Europe
CBA2EC2940619956359801618E7AAB17 Bart vs. the World (E) SMS Europe
0069B1BD9C5B6B88ACE6324D7E61539F Basketball Nightmare (E) SMS Sports;Basketball Europe
215876A62D3CA48D28E98CD8A2C70A15 Batman Returns (E) SMS Europe

View File

@ -470,7 +470,7 @@ namespace BizHawk.Client.Common
System = "PSX"
};
}
else if (ext == ".iso" || ext == ".cue" || ext == ".ccd")
else if (ext == ".iso" || ext == ".cue" || ext == ".ccd" || ext == ".mds")
{
if (file.IsArchive)
{
@ -494,7 +494,7 @@ namespace BizHawk.Client.Common
throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
}
var disc = discMountJob.OUT_Disc;
var disc = discMountJob.OUT_Disc;
// -----------
// TODO - use more sophisticated IDer
@ -514,7 +514,9 @@ namespace BizHawk.Client.Common
// try to use our wizard methods
game = new GameInfo { Name = Path.GetFileNameWithoutExtension(file.Name), Hash = discHash };
switch (new DiscIdentifier(disc).DetectDiscType())
var dt = new DiscIdentifier(disc).DetectDiscType();
switch (dt)
{
case DiscType.SegaSaturn:
game.System = "SAT";
@ -532,9 +534,23 @@ namespace BizHawk.Client.Common
case DiscType.PCFX:
game.System = "PCFX";
break;
case DiscType.TurboCD:
game.System = "PCECD";
break;
case DiscType.Amiga:
case DiscType.CDi:
case DiscType.Dreamcast:
case DiscType.GameCube:
case DiscType.NeoGeoCD:
case DiscType.Panasonic3DO:
case DiscType.Playdia:
case DiscType.Wii:
// no supported emulator core for these (yet)
game.System = dt.ToString();
throw new NoAvailableCoreException(dt.ToString());
case DiscType.AudioDisc:
case DiscType.TurboCD:
case DiscType.UnknownCDFS:
case DiscType.UnknownFormat:
if (PreferredPlatformIsDefined(ext))
@ -543,7 +559,7 @@ namespace BizHawk.Client.Common
}
else
{
game.System = "PCECD";
game.System = "NULL"; // "PCECD";
}
break;
@ -552,6 +568,9 @@ namespace BizHawk.Client.Common
switch (game.System)
{
case "NULL":
nextEmulator = null;
break;
case "GEN":
var genesis = new GPGX(nextComm, null, new[] { disc }, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
nextEmulator = genesis;
@ -1029,7 +1048,14 @@ namespace BizHawk.Client.Common
DoMessageCallback("Failed to load a GB rom in SGB mode. Disabling SGB Mode.");
return LoadRom(path, nextComm, false, recursiveCount + 1);
}
else
// handle exceptions thrown by the new detected systems that bizhawk does not have cores for
else if (ex is NoAvailableCoreException)
{
DoLoadErrorCallback(ex.Message + "\n\n" + ex, system);
}
else
{
DoLoadErrorCallback("A core accepted the rom, but threw an exception while loading it:\n\n" + ex, system);
}

View File

@ -22,6 +22,9 @@ namespace BizHawk.Client.Common
[RequiredService]
private IEmulator Emulator { get; set; }
[OptionalService]
private IMemoryDomains Domains { get; set; }
private readonly LuaFunctionList _luaFunctions = new LuaFunctionList();
public EventLuaLibrary(Lua lua)
@ -210,7 +213,7 @@ namespace BizHawk.Client.Common
}
[LuaMethod("onmemoryexecute", "Fires after the given address is executed by the core")]
public string OnMemoryExecute(LuaFunction luaf, uint address, string name = null)
public string OnMemoryExecute(LuaFunction luaf, uint address, string name = null, string domain = null)
{
try
{
@ -225,8 +228,16 @@ namespace BizHawk.Client.Common
var nlf = new NamedLuaFunction(luaf, "OnMemoryExecute", LogOutputCallback, CurrentThread, name);
_luaFunctions.Add(nlf);
if (string.IsNullOrWhiteSpace(domain))
{
if (Domains != null && Domains.HasSystemBus)
{
domain = Domains.SystemBus.Name;
}
}
DebuggableCore.MemoryCallbacks.Add(
new MemoryCallback(MemoryCallbackType.Execute, "Lua Hook", nlf.Callback, address, null));
new MemoryCallback(domain, MemoryCallbackType.Execute, "Lua Hook", nlf.Callback, address, null));
return nlf.Guid.ToString();
}
}
@ -241,7 +252,7 @@ namespace BizHawk.Client.Common
}
[LuaMethod("onmemoryread", "Fires after the given address is read by the core. If no address is given, it will attach to every memory read")]
public string OnMemoryRead(LuaFunction luaf, uint? address = null, string name = null)
public string OnMemoryRead(LuaFunction luaf, uint? address = null, string name = null, string domain = null)
{
try
{
@ -255,8 +266,16 @@ namespace BizHawk.Client.Common
var nlf = new NamedLuaFunction(luaf, "OnMemoryRead", LogOutputCallback, CurrentThread, name);
_luaFunctions.Add(nlf);
if (string.IsNullOrWhiteSpace(domain))
{
if (Domains != null && Domains.HasSystemBus)
{
domain = Domains.SystemBus.Name;
}
}
DebuggableCore.MemoryCallbacks.Add(
new MemoryCallback(MemoryCallbackType.Read, "Lua Hook", nlf.Callback, address, null));
new MemoryCallback(domain, MemoryCallbackType.Read, "Lua Hook", nlf.Callback, address, null));
return nlf.Guid.ToString();
}
}
@ -271,7 +290,7 @@ namespace BizHawk.Client.Common
}
[LuaMethod("onmemorywrite", "Fires after the given address is written by the core. If no address is given, it will attach to every memory write")]
public string OnMemoryWrite(LuaFunction luaf, uint? address = null, string name = null)
public string OnMemoryWrite(LuaFunction luaf, uint? address = null, string name = null, string domain = null)
{
try
{
@ -285,8 +304,16 @@ namespace BizHawk.Client.Common
var nlf = new NamedLuaFunction(luaf, "OnMemoryWrite", LogOutputCallback, CurrentThread, name);
_luaFunctions.Add(nlf);
if (string.IsNullOrWhiteSpace(domain))
{
if (Domains != null && Domains.HasSystemBus)
{
domain = Domains.SystemBus.Name;
}
}
DebuggableCore.MemoryCallbacks.Add(
new MemoryCallback(MemoryCallbackType.Write, "Lua Hook", nlf.Callback, address, null));
new MemoryCallback(domain, MemoryCallbackType.Write, "Lua Hook", nlf.Callback, address, null));
return nlf.Guid.ToString();
}
}

View File

@ -4,6 +4,7 @@ using System.ComponentModel;
using NLua;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.IEmulatorExtensions;
using BizHawk.Common.BufferExtensions;
namespace BizHawk.Client.Common
{
@ -108,6 +109,37 @@ namespace BizHawk.Client.Common
return false;
}
[LuaMethod("hash_region", "Returns a hash as a string of a region of memory, starting from addr, through count bytes. If the domain is unspecified, it uses the current region.")]
public string HashRegion(int addr, int count, string domain = null)
{
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
// checks
if (addr < 0 || addr >= d.Size)
{
string error = $"Address {addr} is outside the bounds of domain {d.Name}";
Log(error);
throw new ArgumentOutOfRangeException(error);
}
if (addr + count > d.Size)
{
string error = $"Address {addr} + count {count} is outside the bounds of domain {d.Name}";
Log(error);
throw new ArgumentOutOfRangeException(error);
}
byte[] data = new byte[count];
for (int i = 0; i < count; i++)
{
data[i] = d.PeekByte(addr + i);
}
using (var hasher = System.Security.Cryptography.SHA256.Create())
{
return hasher.ComputeHash(data).BytesToHexString();
}
}
#endregion
#region Common Special and Legacy Methods

View File

@ -318,7 +318,7 @@ namespace BizHawk.Client.Common
if (Movie is TasMovie)
{
(Movie as TasMovie).GreenzoneCurrentFrame();
if (Movie.IsPlaying && Global.Emulator.Frame > Movie.InputLogLength)
if (Movie.IsPlaying && Global.Emulator.Frame >= Movie.InputLogLength)
{
HandleFrameLoopForRecordMode();
}

View File

@ -514,14 +514,14 @@ namespace BizHawk.Client.Common
Log?.Dispose();
Log = branch.InputLog.Clone();
////_changes = true;
_lagLog.FromLagLog(branch.LagLog);
// if there are branch states, they will be loaded anyway
// but if there's none, or only *after* divergent point, don't invalidate the entire movie anymore
if (divergentPoint.HasValue)
{
_stateManager.Invalidate(divergentPoint.Value);
_lagLog.FromLagLog(branch.LagLog); // don't truncate LagLog if the branch's one is shorter, but input is the same
}
else
{
@ -530,8 +530,7 @@ namespace BizHawk.Client.Common
_stateManager.LoadBranch(Branches.IndexOf(branch));
_stateManager.SetState(branch.Frame, branch.CoreData);
////ChangeLog = branch.ChangeLog;
if (BindMarkersToInput) // pretty critical not to erase them
{
Markers = branch.Markers;

View File

@ -44,14 +44,16 @@ namespace BizHawk.Client.Common
private readonly TasMovie _movie;
private ulong _expectedStateSize;
private readonly int _minFrequency = VersionInfo.DeveloperBuild ? 2 : 1;
private readonly int _minFrequency = 1;
private const int MaxFrequency = 16;
private int MaxStates => (int)(Settings.Cap / _expectedStateSize) + (int)((ulong)Settings.DiskCapacitymb * 1024 * 1024 / _expectedStateSize);
private int FileStateGap => 1 << Settings.FileStateGap;
private int StateFrequency
{
get
{
int freq = (int)(_expectedStateSize / 65536);
int freq = (int)_expectedStateSize / Settings.MemStateGapDivider / 1024;
if (freq < _minFrequency)
{
@ -66,11 +68,7 @@ namespace BizHawk.Client.Common
return freq;
}
}
private int MaxStates => (int)(Settings.Cap / _expectedStateSize) + (int)((ulong)Settings.DiskCapacitymb * 1024 * 1024 / _expectedStateSize);
private int StateGap => 1 << Settings.StateGap;
public TasStateManager(TasMovie movie)
{
_movie = movie;
@ -585,7 +583,7 @@ namespace BizHawk.Client.Common
for (int i = 1; i < _states.Count; i++)
{
if (_movie.Markers.IsMarker(_states.ElementAt(i).Key + 1)
|| _states.ElementAt(i).Key % StateGap == 0)
|| _states.ElementAt(i).Key % FileStateGap == 0)
{
continue;
}

View File

@ -11,8 +11,9 @@ namespace BizHawk.Client.Common
{
DiskSaveCapacitymb = 512;
Capacitymb = 512;
DiskCapacitymb = 512;
StateGap = 4;
DiskCapacitymb = 1; // not working yet
MemStateGapDivider = 64;
FileStateGap = 4;
BranchStatesInTasproj = false;
EraseBranchStatesFirst = true;
}
@ -22,7 +23,8 @@ namespace BizHawk.Client.Common
DiskSaveCapacitymb = settings.DiskSaveCapacitymb;
Capacitymb = settings.Capacitymb;
DiskCapacitymb = settings.DiskCapacitymb;
StateGap = settings.StateGap;
MemStateGapDivider = settings.MemStateGapDivider;
FileStateGap = settings.FileStateGap;
BranchStatesInTasproj = settings.BranchStatesInTasproj;
EraseBranchStatesFirst = settings.EraseBranchStatesFirst;
}
@ -55,12 +57,19 @@ namespace BizHawk.Client.Common
[Description("The size limit of the state history buffer on the disk. When this limit is reached it will start removing previous savestates")]
public int DiskCapacitymb { get; set; }
/// <summary>
/// Gets or sets the divider that determines memory state gap
/// </summary>
[DisplayName("Divider for memory state interval")]
[Description("The actual state gap in frames is calculated as ExpectedStateSize / div / 1024")]
public int MemStateGapDivider { get; set; }
/// <summary>
/// Gets or sets the amount of states to skip during project saving
/// </summary>
[DisplayName("State interval for .tasproj")]
[Description("The actual state gap in frames is calculated as Nth power on 2")]
public int StateGap { get; set; }
public int FileStateGap { get; set; }
/// <summary>
/// Gets or sets a value indicating whether or not to save branch states into the movie file
@ -99,7 +108,8 @@ namespace BizHawk.Client.Common
sb.AppendLine(DiskCapacitymb.ToString());
sb.AppendLine(BranchStatesInTasproj.ToString());
sb.AppendLine(EraseBranchStatesFirst.ToString());
sb.AppendLine(StateGap.ToString());
sb.AppendLine(FileStateGap.ToString());
sb.AppendLine(MemStateGapDivider.ToString());
return sb.ToString();
}
@ -123,13 +133,13 @@ namespace BizHawk.Client.Common
DiskSaveCapacitymb = refCapacity;
}
DiskCapacitymb = lines.Length > 2 ? int.Parse(lines[2]) : 512;
int i = 2;
BranchStatesInTasproj = lines.Length > 3 && bool.Parse(lines[3]);
EraseBranchStatesFirst = lines.Length <= 4 || bool.Parse(lines[4]);
StateGap = lines.Length > 5 ? int.Parse(lines[5]) : 4;
DiskCapacitymb = lines.Length > i ? int.Parse(lines[i++]) : 1;
BranchStatesInTasproj = lines.Length > i && bool.Parse(lines[i++]);
EraseBranchStatesFirst = lines.Length <= i || bool.Parse(lines[i++]);
FileStateGap = lines.Length > i ? int.Parse(lines[i++]) : 4;
FileStateGap = lines.Length > i ? int.Parse(lines[i++]) : 64;
}
catch (Exception) // TODO: this is bad
{

View File

@ -284,29 +284,61 @@ namespace BizHawk.Client.Common
case WatchSize.Byte:
return (byte?)_val;
case WatchSize.Word:
if (addr == _watch.Address)
if (_watch.BigEndian)
{
if (addr == _watch.Address)
{
return (byte)(_val & 0xFF);
}
return (byte)(_val >> 8);
}
return (byte)(_val & 0xFF);
case WatchSize.DWord:
if (addr == _watch.Address)
else
{
if (addr == _watch.Address)
{
return (byte)(_val >> 8);
}
return (byte)(_val & 0xFF);
}
case WatchSize.DWord:
if (_watch.BigEndian)
{
if (addr == _watch.Address)
{
return (byte)((_val >> 24) & 0xFF);
}
if (addr == _watch.Address + 1)
{
return (byte)((_val >> 16) & 0xFF);
}
if (addr == _watch.Address + 2)
{
return (byte)((_val >> 8) & 0xFF);
}
return (byte)(_val & 0xFF);
}
else
{
if (addr == _watch.Address)
{
return (byte)(_val & 0xFF);
}
if (addr == _watch.Address + 1)
{
return (byte)((_val >> 8) & 0xFF);
}
if (addr == _watch.Address + 2)
{
return (byte)((_val >> 16) & 0xFF);
}
return (byte)((_val >> 24) & 0xFF);
}
if (addr == _watch.Address + 1)
{
return (byte)((_val >> 16) & 0xFF);
}
if (addr == _watch.Address + 2)
{
return (byte)((_val >> 8) & 0xFF);
}
return (byte)(_val & 0xFF);
}
}

View File

@ -111,7 +111,7 @@ namespace BizHawk.Client.DiscoHawk
foreach (string str in files)
{
string ext = Path.GetExtension(str).ToUpper();
if(!ext.In(new string[]{".CUE",".ISO",".CCD"}))
if(!ext.In(new string[]{".CUE",".ISO",".CCD", ".MDS"}))
{
return new List<string>();
}

View File

@ -112,7 +112,7 @@ namespace BizHawk.Client.EmuHawk
}
else
{
cmdRom = arg;
cmdRom = args[i];
}
}
}

View File

@ -35,7 +35,6 @@
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.CoreInfoPanel = new System.Windows.Forms.Panel();
//this.textBox1 = new System.Windows.Forms.TextBox();
this.VersionLabel = new System.Windows.Forms.Label();
this.btnCopyHash = new System.Windows.Forms.Button();
this.linkLabel2 = new System.Windows.Forms.LinkLabel();
@ -146,7 +145,6 @@
//
// linkLabel3
//
this.linkLabel3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.linkLabel3.AutoSize = true;
this.linkLabel3.Location = new System.Drawing.Point(198, 112);
this.linkLabel3.Name = "linkLabel3";
@ -176,7 +174,6 @@
this.Controls.Add(this.linkLabel3);
this.Controls.Add(this.linkLabel2);
this.Controls.Add(this.btnCopyHash);
//this.Controls.Add(this.textBox1);
this.Controls.Add(this.CoreInfoPanel);
this.Controls.Add(this.VersionLabel);
this.Controls.Add(this.label4);

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", ".32X"
".EXE", ".PRG", ".D64", "*G64", ".CRT", ".TAP", ".32X", ".MDS"
};
}
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" };
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", ".MDS" };
}
}

View File

@ -442,7 +442,12 @@
this.ShowMenuContextMenuSeparator = new System.Windows.Forms.ToolStripSeparator();
this.ShowMenuContextMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.timerMouseIdle = new System.Windows.Forms.Timer(this.components);
this.MainformMenu.SuspendLayout();
this.SMSControllerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SMSControllerStandardToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SMSControllerPaddleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SMSControllerLightPhaserToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SMSControllerSportsPadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MainformMenu.SuspendLayout();
this.MainStatusBar.SuspendLayout();
this.MainFormContextMenu.SuspendLayout();
this.SuspendLayout();
@ -2475,7 +2480,8 @@
this.SMSSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.SMSregionToolStripMenuItem,
this.SMSdisplayToolStripMenuItem,
this.SMStoolStripMenuItem2,
this.SMSControllerToolStripMenuItem,
this.SMStoolStripMenuItem2,
this.SMSenableBIOSToolStripMenuItem,
this.SMSEnableFMChipMenuItem,
this.SMSOverclockMenuItem,
@ -2542,9 +2548,44 @@
this.SMSdisplayNtscToolStripMenuItem.Text = "NTSC";
this.SMSdisplayNtscToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayNTSC_Click);
//
// SMSdisplayPalToolStripMenuItem
// SMSControllerToolStripMenuItem
//
this.SMSdisplayPalToolStripMenuItem.Name = "SMSdisplayPalToolStripMenuItem";
this.SMSControllerToolStripMenuItem.Name = "SMSControllerToolStripMenuItem";
this.SMSControllerToolStripMenuItem.Text = "&Controller Type";
this.SMSControllerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.SMSControllerStandardToolStripMenuItem,
this.SMSControllerPaddleToolStripMenuItem,
this.SMSControllerLightPhaserToolStripMenuItem,
this.SMSControllerSportsPadToolStripMenuItem});
//
// SMSControllerStandardToolStripMenuItem
//
this.SMSControllerStandardToolStripMenuItem.Name = "SMSControllerStandardToolStripMenuItem";
this.SMSControllerStandardToolStripMenuItem.Text = "Standard";
this.SMSControllerStandardToolStripMenuItem.Click += new System.EventHandler(this.SMSControllerStandardToolStripMenuItem_Click);
//
// SMSControllerPaddleToolStripMenuItem
//
this.SMSControllerPaddleToolStripMenuItem.Name = "SMSControllerPaddleToolStripMenuItem";
this.SMSControllerPaddleToolStripMenuItem.Text = "Paddle";
this.SMSControllerPaddleToolStripMenuItem.Click += new System.EventHandler(this.SMSControllerPaddleToolStripMenuItem_Click);
//
// SMSControllerLightPhaserToolStripMenuItem
//
this.SMSControllerLightPhaserToolStripMenuItem.Name = "SMSControllerLightPhaserToolStripMenuItem";
this.SMSControllerLightPhaserToolStripMenuItem.Text = "Light Phaser";
this.SMSControllerLightPhaserToolStripMenuItem.Click += new System.EventHandler(this.SMSControllerLightPhaserToolStripMenuItem_Click);
//
// SMSControllerSportsPadToolStripMenuItem
//
this.SMSControllerSportsPadToolStripMenuItem.Name = "SMSControllerSportsPadToolStripMenuItem";
this.SMSControllerSportsPadToolStripMenuItem.Text = "Sports Pad";
this.SMSControllerSportsPadToolStripMenuItem.Click += new System.EventHandler(this.SMSControllerSportsPadToolStripMenuItem_Click);
//
// SMSdisplayPalToolStripMenuItem
//
this.SMSdisplayPalToolStripMenuItem.Name = "SMSdisplayPalToolStripMenuItem";
this.SMSdisplayPalToolStripMenuItem.Size = new System.Drawing.Size(104, 22);
this.SMSdisplayPalToolStripMenuItem.Text = "PAL";
this.SMSdisplayPalToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayPAL_Click);
@ -4368,5 +4409,10 @@
private System.Windows.Forms.ToolStripMenuItem SgbSameBoyMenuItem;
private System.Windows.Forms.ToolStripMenuItem pCFXToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem preferencesToolStripMenuItem3;
private System.Windows.Forms.ToolStripMenuItem SMSControllerToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem SMSControllerStandardToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem SMSControllerPaddleToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem SMSControllerLightPhaserToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem SMSControllerSportsPadToolStripMenuItem;
}
}

View File

@ -1745,6 +1745,10 @@ namespace BizHawk.Client.EmuHawk
SMSdisplayNtscToolStripMenuItem.Checked = ss.DisplayType == "NTSC";
SMSdisplayPalToolStripMenuItem.Checked = ss.DisplayType == "PAL";
SMSdisplayAutoToolStripMenuItem.Checked = ss.DisplayType == "Auto";
SMSControllerStandardToolStripMenuItem.Checked = ss.ControllerType == "Standard";
SMSControllerPaddleToolStripMenuItem.Checked = ss.ControllerType == "Paddle";
SMSControllerLightPhaserToolStripMenuItem.Checked = ss.ControllerType == "Light Phaser";
SMSControllerSportsPadToolStripMenuItem.Checked = ss.ControllerType == "Sports Pad";
SMSenableBIOSToolStripMenuItem.Checked = ss.UseBIOS;
SMSEnableFMChipMenuItem.Checked = ss.EnableFM;
SMSOverclockMenuItem.Checked = ss.AllowOverlock;
@ -1899,6 +1903,34 @@ namespace BizHawk.Client.EmuHawk
GlobalWin.Tools.Load<SmsVDPViewer>();
}
private void SMSControllerStandardToolStripMenuItem_Click(object sender, EventArgs e)
{
var s = ((SMS)Emulator).GetSyncSettings();
s.ControllerType = "Standard";
PutCoreSyncSettings(s);
}
private void SMSControllerPaddleToolStripMenuItem_Click(object sender, EventArgs e)
{
var s = ((SMS)Emulator).GetSyncSettings();
s.ControllerType = "Paddle";
PutCoreSyncSettings(s);
}
private void SMSControllerLightPhaserToolStripMenuItem_Click(object sender, EventArgs e)
{
var s = ((SMS)Emulator).GetSyncSettings();
s.ControllerType = "Light Phaser";
PutCoreSyncSettings(s);
}
private void SMSControllerSportsPadToolStripMenuItem_Click(object sender, EventArgs e)
{
var s = ((SMS)Emulator).GetSyncSettings();
s.ControllerType = "Sports Pad";
PutCoreSyncSettings(s);
}
#endregion
#region TI83

View File

@ -274,7 +274,8 @@ namespace BizHawk.Client.EmuHawk
if (argParse.cmdRom != null)
{
// Commandline should always override auto-load
LoadRom(argParse.cmdRom, new LoadRomArgs { OpenAdvanced = new OpenAdvanced_OpenRom() });
var ioa = OpenAdvancedSerializer.ParseWithLegacy(argParse.cmdRom);
LoadRom(argParse.cmdRom, new LoadRomArgs { OpenAdvanced = ioa });
if (Global.Game == null)
{
MessageBox.Show("Failed to load " + argParse.cmdRom + " specified on commandline");
@ -2076,13 +2077,13 @@ namespace BizHawk.Client.EmuHawk
if (VersionInfo.DeveloperBuild)
{
return FormatFilter(
"Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.32x;*.col;*.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.tap;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;*.vb;*.ngp;*.ngc;*.psf;*.minipsf;*.nsf;%ARCH%",
"Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.mds;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.32x;*.col;*.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.tap;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;*.vb;*.ngp;*.ngc;*.psf;*.minipsf;*.nsf;%ARCH%",
"Music Files", "*.psf;*.minipsf;*.sid;*.nsf",
"Disc Images", "*.cue;*.ccd;*.m3u",
"Disc Images", "*.cue;*.ccd;*.mds;*.m3u",
"NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%",
"Super NES", "*.smc;*.sfc;*.xml;%ARCH%",
"Master System", "*.sms;*.gg;*.sg;%ARCH%",
"PC Engine", "*.pce;*.sgx;*.cue;*.ccd;%ARCH%",
"PC Engine", "*.pce;*.sgx;*.cue;*.ccd;*.mds;%ARCH%",
"TI-83", "*.rom;%ARCH%",
"Archive Files", "%ARCH%",
"Savestate", "*.state",
@ -2094,7 +2095,7 @@ namespace BizHawk.Client.EmuHawk
"Gameboy Advance", "*.gba;%ARCH%",
"Colecovision", "*.col;%ARCH%",
"Intellivision", "*.int;*.bin;*.rom;%ARCH%",
"PlayStation", "*.cue;*.ccd;*.m3u",
"PlayStation", "*.cue;*.ccd;*.mds;*.m3u",
"PSX Executables (experimental)", "*.exe",
"PSF Playstation Sound File", "*.psf;*.minipsf",
"Commodore 64", "*.prg; *.d64, *.g64; *.crt; *.tap;%ARCH%",
@ -2108,17 +2109,17 @@ namespace BizHawk.Client.EmuHawk
}
return FormatFilter(
"Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.gb;*.gbc;*.gba;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.32x;*.smc;*.sfc;*.a26;*.a78;*.lnx;*.col;*.int;*.rom;*.m3u;*.cue;*.ccd;*.sgb;*.z64;*.v64;*.n64;*.ws;*.wsc;*.xml;*.dsk;*.do;*.po;*.psf;*.ngp;*.ngc;*.prg;*.d64;*.g64;*.minipsf;*.nsf;%ARCH%",
"Disc Images", "*.cue;*.ccd;*.m3u",
"Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.gb;*.gbc;*.gba;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.32x;*.smc;*.sfc;*.a26;*.a78;*.lnx;*.col;*.int;*.rom;*.m3u;*.cue;*.ccd;*.mds;*.sgb;*.z64;*.v64;*.n64;*.ws;*.wsc;*.xml;*.dsk;*.do;*.po;*.psf;*.ngp;*.ngc;*.prg;*.d64;*.g64;*.minipsf;*.nsf;%ARCH%",
"Disc Images", "*.cue;*.ccd;*.mds;*.m3u",
"NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%",
"Super NES", "*.smc;*.sfc;*.xml;%ARCH%",
"PlayStation", "*.cue;*.ccd;*.m3u",
"PlayStation", "*.cue;*.ccd;*.mds;*.m3u",
"PSF Playstation Sound File", "*.psf;*.minipsf",
"Nintendo 64", "*.z64;*.v64;*.n64",
"Gameboy", "*.gb;*.gbc;*.sgb;%ARCH%",
"Gameboy Advance", "*.gba;%ARCH%",
"Master System", "*.sms;*.gg;*.sg;%ARCH%",
"PC Engine", "*.pce;*.sgx;*.cue;*.ccd;%ARCH%",
"PC Engine", "*.pce;*.sgx;*.cue;*.ccd;*.mds;%ARCH%",
"Atari 2600", "*.a26;%ARCH%",
"Atari 7800", "*.a78;%ARCH%",
"Atari Lynx", "*.lnx;%ARCH%",
@ -3582,6 +3583,12 @@ namespace BizHawk.Client.EmuHawk
}
}
if (ioa is OpenAdvanced_OpenRom)
{
var ioa_openrom = (OpenAdvanced_OpenRom)ioa;
path = ioa_openrom.Path;
}
CoreFileProvider.SyncCoreCommInputSignals(nextComm);
var result = loader.LoadRom(path, nextComm);

View File

@ -28,220 +28,87 @@
/// </summary>
private void InitializeComponent()
{
this.OK = new System.Windows.Forms.Button();
this.Cancel = new System.Windows.Forms.Button();
this.trackBar1 = new System.Windows.Forms.TrackBar();
this.trackBar2 = new System.Windows.Forms.TrackBar();
this.trackBar3 = new System.Windows.Forms.TrackBar();
this.trackBar4 = new System.Windows.Forms.TrackBar();
this.trackBar5 = new System.Windows.Forms.TrackBar();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.label10 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar4)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar5)).BeginInit();
this.SuspendLayout();
//
// OK
//
this.OK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.OK.Location = new System.Drawing.Point(41, 262);
this.OK.Name = "OK";
this.OK.Size = new System.Drawing.Size(75, 23);
this.OK.TabIndex = 0;
this.OK.Text = "&OK";
this.OK.UseVisualStyleBackColor = true;
this.OK.Click += new System.EventHandler(this.Ok_Click);
//
// Cancel
//
this.Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Cancel.Location = new System.Drawing.Point(122, 262);
this.Cancel.Name = "Cancel";
this.Cancel.Size = new System.Drawing.Size(75, 23);
this.Cancel.TabIndex = 1;
this.Cancel.Text = "&Cancel";
this.Cancel.UseVisualStyleBackColor = true;
this.Cancel.Click += new System.EventHandler(this.Cancel_Click);
//
// trackBar1
//
this.trackBar1.Location = new System.Drawing.Point(12, 12);
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(104, 45);
this.trackBar1.TabIndex = 2;
this.trackBar1.ValueChanged += new System.EventHandler(this.TrackBar1_ValueChanged);
//
// trackBar2
//
this.trackBar2.Location = new System.Drawing.Point(12, 60);
this.trackBar2.Name = "trackBar2";
this.trackBar2.Size = new System.Drawing.Size(104, 45);
this.trackBar2.TabIndex = 3;
this.trackBar2.ValueChanged += new System.EventHandler(this.TrackBar2_ValueChanged);
//
// trackBar3
//
this.trackBar3.Location = new System.Drawing.Point(12, 108);
this.trackBar3.Name = "trackBar3";
this.trackBar3.Size = new System.Drawing.Size(104, 45);
this.trackBar3.TabIndex = 4;
this.trackBar3.ValueChanged += new System.EventHandler(this.TrackBar3_ValueChanged);
//
// trackBar4
//
this.trackBar4.Location = new System.Drawing.Point(12, 156);
this.trackBar4.Name = "trackBar4";
this.trackBar4.Size = new System.Drawing.Size(104, 45);
this.trackBar4.TabIndex = 5;
this.trackBar4.ValueChanged += new System.EventHandler(this.TrackBar4_ValueChanged);
//
// trackBar5
//
this.trackBar5.Location = new System.Drawing.Point(12, 204);
this.trackBar5.Name = "trackBar5";
this.trackBar5.Size = new System.Drawing.Size(104, 45);
this.trackBar5.TabIndex = 6;
this.trackBar5.ValueChanged += new System.EventHandler(this.TrackBar5_ValueChanged);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(122, 12);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(50, 13);
this.label1.TabIndex = 7;
this.label1.Text = "Square 1";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(122, 60);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(50, 13);
this.label2.TabIndex = 8;
this.label2.Text = "Square 2";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(122, 108);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(45, 13);
this.label3.TabIndex = 9;
this.label3.Text = "Triangle";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(122, 156);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(34, 13);
this.label4.TabIndex = 10;
this.label4.Text = "Noise";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(122, 204);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(31, 13);
this.label5.TabIndex = 11;
this.label5.Text = "DMC";
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(122, 25);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(13, 13);
this.label6.TabIndex = 12;
this.label6.Text = "0";
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(122, 73);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(13, 13);
this.label7.TabIndex = 13;
this.label7.Text = "0";
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(122, 121);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(13, 13);
this.label8.TabIndex = 14;
this.label8.Text = "0";
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(122, 169);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(13, 13);
this.label9.TabIndex = 15;
this.label9.Text = "0";
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(122, 217);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(13, 13);
this.label10.TabIndex = 16;
this.label10.Text = "0";
//
// NESSoundConfig
//
this.AcceptButton = this.OK;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.Cancel;
this.ClientSize = new System.Drawing.Size(209, 297);
this.Controls.Add(this.label10);
this.Controls.Add(this.label9);
this.Controls.Add(this.label8);
this.Controls.Add(this.label7);
this.Controls.Add(this.label6);
this.Controls.Add(this.label5);
this.Controls.Add(this.label4);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.trackBar5);
this.Controls.Add(this.trackBar4);
this.Controls.Add(this.trackBar3);
this.Controls.Add(this.trackBar2);
this.Controls.Add(this.trackBar1);
this.Controls.Add(this.Cancel);
this.Controls.Add(this.OK);
this.MaximizeBox = false;
this.Name = "NESSoundConfig";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "NES Sound Channels";
this.Load += new System.EventHandler(this.NESSoundConfig_Load);
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar3)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar4)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar5)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
this.OK = new System.Windows.Forms.Button();
this.Cancel = new System.Windows.Forms.Button();
this.trackBar1 = new System.Windows.Forms.TrackBar();
this.label1 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
this.SuspendLayout();
//
// OK
//
this.OK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.OK.Location = new System.Drawing.Point(41, 117);
this.OK.Name = "OK";
this.OK.Size = new System.Drawing.Size(75, 23);
this.OK.TabIndex = 0;
this.OK.Text = "&OK";
this.OK.UseVisualStyleBackColor = true;
this.OK.Click += new System.EventHandler(this.Ok_Click);
//
// Cancel
//
this.Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Cancel.Location = new System.Drawing.Point(122, 117);
this.Cancel.Name = "Cancel";
this.Cancel.Size = new System.Drawing.Size(75, 23);
this.Cancel.TabIndex = 1;
this.Cancel.Text = "&Cancel";
this.Cancel.UseVisualStyleBackColor = true;
this.Cancel.Click += new System.EventHandler(this.Cancel_Click);
//
// trackBar1
//
this.trackBar1.LargeChange = 1;
this.trackBar1.Location = new System.Drawing.Point(12, 12);
this.trackBar1.Minimum = 1;
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(104, 45);
this.trackBar1.TabIndex = 2;
this.trackBar1.Value = 1;
this.trackBar1.ValueChanged += new System.EventHandler(this.TrackBar1_ValueChanged);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(122, 12);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(67, 13);
this.label1.TabIndex = 7;
this.label1.Text = "APU Volume";
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(122, 25);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(13, 13);
this.label6.TabIndex = 12;
this.label6.Text = "0";
//
// NESSoundConfig
//
this.AcceptButton = this.OK;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.Cancel;
this.ClientSize = new System.Drawing.Size(209, 152);
this.Controls.Add(this.label6);
this.Controls.Add(this.label1);
this.Controls.Add(this.trackBar1);
this.Controls.Add(this.Cancel);
this.Controls.Add(this.OK);
this.MaximizeBox = false;
this.Name = "NESSoundConfig";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "NES Sound Channels";
this.Load += new System.EventHandler(this.NESSoundConfig_Load);
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
@ -250,19 +117,7 @@
private System.Windows.Forms.Button OK;
private System.Windows.Forms.Button Cancel;
private System.Windows.Forms.TrackBar trackBar1;
private System.Windows.Forms.TrackBar trackBar2;
private System.Windows.Forms.TrackBar trackBar3;
private System.Windows.Forms.TrackBar trackBar4;
private System.Windows.Forms.TrackBar trackBar5;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Label label10;
}
}

View File

@ -38,11 +38,7 @@ namespace BizHawk.Client.EmuHawk
// get baseline maxes from a default config object
var d = new NES.NESSettings();
trackBar1.Maximum = d.Square1;
trackBar2.Maximum = d.Square2;
trackBar3.Maximum = d.Triangle;
trackBar4.Maximum = d.Noise;
trackBar5.Maximum = d.DMC;
trackBar1.Minimum = d.APU_vol;
}
private void NESSoundConfig_Load(object sender, EventArgs e)
@ -50,11 +46,7 @@ namespace BizHawk.Client.EmuHawk
_oldSettings = NES.GetSettings();
_settings = _oldSettings.Clone();
trackBar1.Value = _settings.Square1;
trackBar2.Value = _settings.Square2;
trackBar3.Value = _settings.Triangle;
trackBar4.Value = _settings.Noise;
trackBar5.Value = _settings.DMC;
trackBar1.Value = _settings.APU_vol;
}
private void Ok_Click(object sender, EventArgs e)
@ -72,35 +64,7 @@ namespace BizHawk.Client.EmuHawk
private void TrackBar1_ValueChanged(object sender, EventArgs e)
{
label6.Text = trackBar1.Value.ToString();
_settings.Square1 = trackBar1.Value;
NES.PutSettings(_settings);
}
private void TrackBar2_ValueChanged(object sender, EventArgs e)
{
label7.Text = trackBar2.Value.ToString();
_settings.Square2 = trackBar2.Value;
NES.PutSettings(_settings);
}
private void TrackBar3_ValueChanged(object sender, EventArgs e)
{
label8.Text = trackBar3.Value.ToString();
_settings.Triangle = trackBar3.Value;
NES.PutSettings(_settings);
}
private void TrackBar4_ValueChanged(object sender, EventArgs e)
{
label9.Text = trackBar4.Value.ToString();
_settings.Noise = trackBar4.Value;
NES.PutSettings(_settings);
}
private void TrackBar5_ValueChanged(object sender, EventArgs e)
{
label10.Text = trackBar5.Value.ToString();
_settings.DMC = trackBar5.Value;
_settings.APU_vol = trackBar1.Value;
NES.PutSettings(_settings);
}
}

View File

@ -9,9 +9,9 @@ namespace BizHawk.Client.EmuHawk
{
public Action Callback { get; set; }
public void Add(IDebuggable core, uint address, uint mask, MemoryCallbackType type)
public void Add(IDebuggable core, string scope, uint address, uint mask, MemoryCallbackType type)
{
Add(new Breakpoint(core, Callback, address, mask, type));
Add(new Breakpoint(core, scope, Callback, address, mask, type));
}
public new void Clear()
@ -69,8 +69,9 @@ namespace BizHawk.Client.EmuHawk
private bool _active;
private readonly IDebuggable _core;
public Breakpoint(bool readOnly, IDebuggable core, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
public Breakpoint(bool readOnly, IDebuggable core, string scope, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
{
Scope = scope;
_core = core;
Type = type;
Callback = callBack;
@ -82,8 +83,9 @@ namespace BizHawk.Client.EmuHawk
ReadOnly = readOnly;
}
public Breakpoint(IDebuggable core, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
public Breakpoint(IDebuggable core, string scope, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
{
Scope = scope;
_core = core;
Type = type;
Callback = callBack;
@ -94,8 +96,9 @@ namespace BizHawk.Client.EmuHawk
Active = enabled;
}
public Breakpoint(string name, bool readOnly, IDebuggable core, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
public Breakpoint(string name, bool readOnly, IDebuggable core, string scope, Action callBack, uint address, uint mask, MemoryCallbackType type, bool enabled = true)
{
Scope = scope;
_core = core;
Type = type;
Callback = callBack;
@ -107,6 +110,7 @@ namespace BizHawk.Client.EmuHawk
ReadOnly = readOnly;
}
public string Scope { get; }
public Action Callback { get; }
public uint? Address { get; set; }
public uint? AddressMask { get; set; }
@ -159,7 +163,7 @@ namespace BizHawk.Client.EmuHawk
private void AddCallback()
{
_core.MemoryCallbacks.Add(new MemoryCallback(Type, Name, Callback, Address, AddressMask));
_core.MemoryCallbacks.Add(new MemoryCallback(Scope, Type, Name, Callback, Address, AddressMask));
}
private void RemoveCallback()

View File

@ -144,7 +144,7 @@ namespace BizHawk.Client.EmuHawk
public void AddBreakpoint(uint address, uint mask, MemoryCallbackType type)
{
_breakpoints.Add(Core, address, mask, type);
_breakpoints.Add(Core, MemoryDomains.SystemBus.Name, address, mask, type);
BreakpointView.ItemCount = _breakpoints.Count;
UpdateBreakpointRemoveButton();
@ -157,7 +157,7 @@ namespace BizHawk.Client.EmuHawk
if (b.ShowHawkDialog() == DialogResult.OK)
{
_breakpoints.Add(Core, b.Address, b.AddressMask, b.BreakType);
_breakpoints.Add(Core, MemoryDomains.SystemBus.Name, b.Address, b.AddressMask, b.BreakType);
}
BreakpointView.ItemCount = _breakpoints.Count;
@ -170,7 +170,7 @@ namespace BizHawk.Client.EmuHawk
public void AddSeekBreakpoint(uint pcVal, int pcBitSize)
{
var name = SeekName + pcVal.ToHexString(pcBitSize / 4);
_breakpoints.Add(new Breakpoint(name, true, Core, SeekCallback, pcVal, 0xFFFFFFFF, MemoryCallbackType.Execute));
_breakpoints.Add(new Breakpoint(name, true, Core, MemoryDomains.SystemBus.Name, SeekCallback, pcVal, 0xFFFFFFFF, MemoryCallbackType.Execute));
}
public void RemoveCurrentSeek()
@ -284,7 +284,7 @@ namespace BizHawk.Client.EmuHawk
if (b.ShowHawkDialog() == DialogResult.OK)
{
_breakpoints.Add(new Breakpoint(Core, breakpoint.Callback, b.Address, b.AddressMask, b.BreakType, breakpoint.Active));
_breakpoints.Add(new Breakpoint(Core, MemoryDomains.SystemBus.Name, breakpoint.Callback, b.Address, b.AddressMask, b.BreakType, breakpoint.Active));
}
}

View File

@ -15,7 +15,7 @@ namespace BizHawk.Client.EmuHawk
[OptionalService]
private IDisassemblable Disassembler { get; set; }
[OptionalService]
[RequiredService]
private IMemoryDomains MemoryDomains { get; set; }
private IMemoryCallbackSystem MemoryCallbacks { get { return Debuggable.MemoryCallbacks; } }

View File

@ -92,6 +92,7 @@
this.AddressLabel = new System.Windows.Forms.Label();
this.AddressesLabel = new System.Windows.Forms.Label();
this.Header = new System.Windows.Forms.Label();
this.swapBytesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.HexMenuStrip.SuspendLayout();
this.ViewerContextMenuStrip.SuspendLayout();
this.MemoryViewerBox.SuspendLayout();
@ -126,7 +127,7 @@
this.toolStripSeparator1,
this.ExitMenuItem});
this.FileSubMenu.Name = "FileSubMenu";
this.FileSubMenu.Size = new System.Drawing.Size(35, 20);
this.FileSubMenu.Size = new System.Drawing.Size(37, 20);
this.FileSubMenu.Text = "&File";
this.FileSubMenu.DropDownOpened += new System.EventHandler(this.FileSubMenu_DropDownOpened);
//
@ -135,7 +136,7 @@
this.SaveMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs;
this.SaveMenuItem.Name = "SaveMenuItem";
this.SaveMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));
this.SaveMenuItem.Size = new System.Drawing.Size(225, 22);
this.SaveMenuItem.Size = new System.Drawing.Size(229, 22);
this.SaveMenuItem.Text = "Save";
this.SaveMenuItem.Click += new System.EventHandler(this.SaveMenuItem_Click);
//
@ -144,14 +145,14 @@
this.SaveAsBinaryMenuItem.Name = "SaveAsBinaryMenuItem";
this.SaveAsBinaryMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
| System.Windows.Forms.Keys.S)));
this.SaveAsBinaryMenuItem.Size = new System.Drawing.Size(225, 22);
this.SaveAsBinaryMenuItem.Size = new System.Drawing.Size(229, 22);
this.SaveAsBinaryMenuItem.Text = "Save as binary...";
this.SaveAsBinaryMenuItem.Click += new System.EventHandler(this.SaveAsBinaryMenuItem_Click);
//
// SaveAsTextMenuItem
//
this.SaveAsTextMenuItem.Name = "SaveAsTextMenuItem";
this.SaveAsTextMenuItem.Size = new System.Drawing.Size(225, 22);
this.SaveAsTextMenuItem.Size = new System.Drawing.Size(229, 22);
this.SaveAsTextMenuItem.Text = "Save as text...";
this.SaveAsTextMenuItem.Click += new System.EventHandler(this.SaveAsTextMenuItem_Click);
//
@ -159,26 +160,26 @@
//
this.importAsBinaryToolStripMenuItem.Name = "importAsBinaryToolStripMenuItem";
this.importAsBinaryToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.I)));
this.importAsBinaryToolStripMenuItem.Size = new System.Drawing.Size(225, 22);
this.importAsBinaryToolStripMenuItem.Size = new System.Drawing.Size(229, 22);
this.importAsBinaryToolStripMenuItem.Text = "Import as binary...";
this.importAsBinaryToolStripMenuItem.Click += new System.EventHandler(this.importAsBinaryToolStripMenuItem_Click);
//
// toolStripSeparator4
//
this.toolStripSeparator4.Name = "toolStripSeparator4";
this.toolStripSeparator4.Size = new System.Drawing.Size(222, 6);
this.toolStripSeparator4.Size = new System.Drawing.Size(226, 6);
//
// LoadTableFileMenuItem
//
this.LoadTableFileMenuItem.Name = "LoadTableFileMenuItem";
this.LoadTableFileMenuItem.Size = new System.Drawing.Size(225, 22);
this.LoadTableFileMenuItem.Size = new System.Drawing.Size(229, 22);
this.LoadTableFileMenuItem.Text = "&Load .tbl file";
this.LoadTableFileMenuItem.Click += new System.EventHandler(this.LoadTableFileMenuItem_Click);
//
// CloseTableFileMenuItem
//
this.CloseTableFileMenuItem.Name = "CloseTableFileMenuItem";
this.CloseTableFileMenuItem.Size = new System.Drawing.Size(225, 22);
this.CloseTableFileMenuItem.Size = new System.Drawing.Size(229, 22);
this.CloseTableFileMenuItem.Text = "Close .tbl file";
this.CloseTableFileMenuItem.Click += new System.EventHandler(this.CloseTableFileMenuItem_Click);
//
@ -187,26 +188,26 @@
this.RecentTablesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.noneToolStripMenuItem});
this.RecentTablesSubMenu.Name = "RecentTablesSubMenu";
this.RecentTablesSubMenu.Size = new System.Drawing.Size(225, 22);
this.RecentTablesSubMenu.Size = new System.Drawing.Size(229, 22);
this.RecentTablesSubMenu.Text = "Recent";
this.RecentTablesSubMenu.DropDownOpened += new System.EventHandler(this.RecentTablesSubMenu_DropDownOpened);
//
// noneToolStripMenuItem
//
this.noneToolStripMenuItem.Name = "noneToolStripMenuItem";
this.noneToolStripMenuItem.Size = new System.Drawing.Size(99, 22);
this.noneToolStripMenuItem.Size = new System.Drawing.Size(103, 22);
this.noneToolStripMenuItem.Text = "None";
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(222, 6);
this.toolStripSeparator1.Size = new System.Drawing.Size(226, 6);
//
// ExitMenuItem
//
this.ExitMenuItem.Name = "ExitMenuItem";
this.ExitMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
this.ExitMenuItem.Size = new System.Drawing.Size(225, 22);
this.ExitMenuItem.Size = new System.Drawing.Size(229, 22);
this.ExitMenuItem.Text = "E&xit";
this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click);
//
@ -221,7 +222,7 @@
this.FindNextMenuItem,
this.FindPrevMenuItem});
this.EditMenuItem.Name = "EditMenuItem";
this.EditMenuItem.Size = new System.Drawing.Size(37, 20);
this.EditMenuItem.Size = new System.Drawing.Size(39, 20);
this.EditMenuItem.Text = "&Edit";
this.EditMenuItem.DropDownOpened += new System.EventHandler(this.EditMenuItem_DropDownOpened);
//
@ -230,7 +231,7 @@
this.CopyMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Duplicate;
this.CopyMenuItem.Name = "CopyMenuItem";
this.CopyMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
this.CopyMenuItem.Size = new System.Drawing.Size(144, 22);
this.CopyMenuItem.Size = new System.Drawing.Size(147, 22);
this.CopyMenuItem.Text = "&Copy";
this.CopyMenuItem.Click += new System.EventHandler(this.CopyMenuItem_Click);
//
@ -238,7 +239,7 @@
//
this.ExportMenuItem.Name = "ExportMenuItem";
this.ExportMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E)));
this.ExportMenuItem.Size = new System.Drawing.Size(144, 22);
this.ExportMenuItem.Size = new System.Drawing.Size(147, 22);
this.ExportMenuItem.Text = "&Export";
this.ExportMenuItem.Click += new System.EventHandler(this.ExportMenuItem_Click);
//
@ -247,20 +248,20 @@
this.PasteMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Paste;
this.PasteMenuItem.Name = "PasteMenuItem";
this.PasteMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
this.PasteMenuItem.Size = new System.Drawing.Size(144, 22);
this.PasteMenuItem.Size = new System.Drawing.Size(147, 22);
this.PasteMenuItem.Text = "&Paste";
this.PasteMenuItem.Click += new System.EventHandler(this.PasteMenuItem_Click);
//
// toolStripSeparator6
//
this.toolStripSeparator6.Name = "toolStripSeparator6";
this.toolStripSeparator6.Size = new System.Drawing.Size(141, 6);
this.toolStripSeparator6.Size = new System.Drawing.Size(144, 6);
//
// FindMenuItem
//
this.FindMenuItem.Name = "FindMenuItem";
this.FindMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F)));
this.FindMenuItem.Size = new System.Drawing.Size(144, 22);
this.FindMenuItem.Size = new System.Drawing.Size(147, 22);
this.FindMenuItem.Text = "&Find...";
this.FindMenuItem.Click += new System.EventHandler(this.FindMenuItem_Click);
//
@ -268,7 +269,7 @@
//
this.FindNextMenuItem.Name = "FindNextMenuItem";
this.FindNextMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F3;
this.FindNextMenuItem.Size = new System.Drawing.Size(144, 22);
this.FindNextMenuItem.Size = new System.Drawing.Size(147, 22);
this.FindNextMenuItem.Text = "Find Next";
this.FindNextMenuItem.Click += new System.EventHandler(this.FindNextMenuItem_Click);
//
@ -276,7 +277,7 @@
//
this.FindPrevMenuItem.Name = "FindPrevMenuItem";
this.FindPrevMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F2;
this.FindPrevMenuItem.Size = new System.Drawing.Size(144, 22);
this.FindPrevMenuItem.Size = new System.Drawing.Size(147, 22);
this.FindPrevMenuItem.Text = "Find Prev";
this.FindPrevMenuItem.Click += new System.EventHandler(this.FindPrevMenuItem_Click);
//
@ -285,6 +286,7 @@
this.OptionsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.MemoryDomainsMenuItem,
this.DataSizeSubMenu,
this.swapBytesToolStripMenuItem,
this.BigEndianMenuItem,
this.toolStripSeparator2,
this.GoToAddressMenuItem,
@ -293,7 +295,7 @@
this.UnfreezeAllMenuItem,
this.PokeAddressMenuItem});
this.OptionsSubMenu.Name = "OptionsSubMenu";
this.OptionsSubMenu.Size = new System.Drawing.Size(56, 20);
this.OptionsSubMenu.Size = new System.Drawing.Size(61, 20);
this.OptionsSubMenu.Text = "&Options";
this.OptionsSubMenu.DropDownOpened += new System.EventHandler(this.OptionsSubMenu_DropDownOpened);
//
@ -302,7 +304,7 @@
this.MemoryDomainsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripSeparator3});
this.MemoryDomainsMenuItem.Name = "MemoryDomainsMenuItem";
this.MemoryDomainsMenuItem.Size = new System.Drawing.Size(207, 22);
this.MemoryDomainsMenuItem.Size = new System.Drawing.Size(221, 22);
this.MemoryDomainsMenuItem.Text = "&Memory Domains";
this.MemoryDomainsMenuItem.DropDownOpened += new System.EventHandler(this.MemoryDomainsMenuItem_DropDownOpened);
//
@ -318,47 +320,47 @@
this.DataSizeWordMenuItem,
this.DataSizeDWordMenuItem});
this.DataSizeSubMenu.Name = "DataSizeSubMenu";
this.DataSizeSubMenu.Size = new System.Drawing.Size(207, 22);
this.DataSizeSubMenu.Size = new System.Drawing.Size(221, 22);
this.DataSizeSubMenu.Text = "Data Size";
//
// DataSizeByteMenuItem
//
this.DataSizeByteMenuItem.Name = "DataSizeByteMenuItem";
this.DataSizeByteMenuItem.Size = new System.Drawing.Size(105, 22);
this.DataSizeByteMenuItem.Size = new System.Drawing.Size(106, 22);
this.DataSizeByteMenuItem.Text = "1 Byte";
this.DataSizeByteMenuItem.Click += new System.EventHandler(this.DataSizeByteMenuItem_Click);
//
// DataSizeWordMenuItem
//
this.DataSizeWordMenuItem.Name = "DataSizeWordMenuItem";
this.DataSizeWordMenuItem.Size = new System.Drawing.Size(105, 22);
this.DataSizeWordMenuItem.Size = new System.Drawing.Size(106, 22);
this.DataSizeWordMenuItem.Text = "2 Byte";
this.DataSizeWordMenuItem.Click += new System.EventHandler(this.DataSizeWordMenuItem_Click);
//
// DataSizeDWordMenuItem
//
this.DataSizeDWordMenuItem.Name = "DataSizeDWordMenuItem";
this.DataSizeDWordMenuItem.Size = new System.Drawing.Size(105, 22);
this.DataSizeDWordMenuItem.Size = new System.Drawing.Size(106, 22);
this.DataSizeDWordMenuItem.Text = "4 Byte";
this.DataSizeDWordMenuItem.Click += new System.EventHandler(this.DataSizeDWordMenuItem_Click);
//
// BigEndianMenuItem
//
this.BigEndianMenuItem.Name = "BigEndianMenuItem";
this.BigEndianMenuItem.Size = new System.Drawing.Size(207, 22);
this.BigEndianMenuItem.Size = new System.Drawing.Size(221, 22);
this.BigEndianMenuItem.Text = "Big Endian";
this.BigEndianMenuItem.Click += new System.EventHandler(this.BigEndianMenuItem_Click);
//
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(204, 6);
this.toolStripSeparator2.Size = new System.Drawing.Size(218, 6);
//
// GoToAddressMenuItem
//
this.GoToAddressMenuItem.Name = "GoToAddressMenuItem";
this.GoToAddressMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.G)));
this.GoToAddressMenuItem.Size = new System.Drawing.Size(207, 22);
this.GoToAddressMenuItem.Size = new System.Drawing.Size(221, 22);
this.GoToAddressMenuItem.Text = "&Go to Address...";
this.GoToAddressMenuItem.Click += new System.EventHandler(this.GoToAddressMenuItem_Click);
//
@ -367,7 +369,7 @@
this.AddToRamWatchMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.FindHS;
this.AddToRamWatchMenuItem.Name = "AddToRamWatchMenuItem";
this.AddToRamWatchMenuItem.ShortcutKeyDisplayString = "Ctrl+W";
this.AddToRamWatchMenuItem.Size = new System.Drawing.Size(207, 22);
this.AddToRamWatchMenuItem.Size = new System.Drawing.Size(221, 22);
this.AddToRamWatchMenuItem.Text = "Add to RAM Watch";
this.AddToRamWatchMenuItem.Click += new System.EventHandler(this.AddToRamWatchMenuItem_Click);
//
@ -376,7 +378,7 @@
this.FreezeAddressMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Freeze;
this.FreezeAddressMenuItem.Name = "FreezeAddressMenuItem";
this.FreezeAddressMenuItem.ShortcutKeyDisplayString = "Space";
this.FreezeAddressMenuItem.Size = new System.Drawing.Size(207, 22);
this.FreezeAddressMenuItem.Size = new System.Drawing.Size(221, 22);
this.FreezeAddressMenuItem.Text = "&Freeze Address";
this.FreezeAddressMenuItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click);
//
@ -385,7 +387,7 @@
this.UnfreezeAllMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Unfreeze;
this.UnfreezeAllMenuItem.Name = "UnfreezeAllMenuItem";
this.UnfreezeAllMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Delete)));
this.UnfreezeAllMenuItem.Size = new System.Drawing.Size(207, 22);
this.UnfreezeAllMenuItem.Size = new System.Drawing.Size(221, 22);
this.UnfreezeAllMenuItem.Text = "Unfreeze All";
this.UnfreezeAllMenuItem.Click += new System.EventHandler(this.UnfreezeAllMenuItem_Click);
//
@ -394,7 +396,7 @@
this.PokeAddressMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.poke;
this.PokeAddressMenuItem.Name = "PokeAddressMenuItem";
this.PokeAddressMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P)));
this.PokeAddressMenuItem.Size = new System.Drawing.Size(207, 22);
this.PokeAddressMenuItem.Size = new System.Drawing.Size(221, 22);
this.PokeAddressMenuItem.Text = "&Poke Address";
this.PokeAddressMenuItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click);
//
@ -403,7 +405,7 @@
this.SettingsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.CustomColorsSubMenu});
this.SettingsSubMenu.Name = "SettingsSubMenu";
this.SettingsSubMenu.Size = new System.Drawing.Size(58, 20);
this.SettingsSubMenu.Size = new System.Drawing.Size(61, 20);
this.SettingsSubMenu.Text = "&Settings";
//
// CustomColorsSubMenu
@ -413,25 +415,25 @@
this.toolStripSeparator8,
this.ResetColorsToDefaultMenuItem});
this.CustomColorsSubMenu.Name = "CustomColorsSubMenu";
this.CustomColorsSubMenu.Size = new System.Drawing.Size(143, 22);
this.CustomColorsSubMenu.Size = new System.Drawing.Size(153, 22);
this.CustomColorsSubMenu.Text = "Custom Colors";
//
// SetColorsMenuItem
//
this.SetColorsMenuItem.Name = "SetColorsMenuItem";
this.SetColorsMenuItem.Size = new System.Drawing.Size(153, 22);
this.SetColorsMenuItem.Size = new System.Drawing.Size(157, 22);
this.SetColorsMenuItem.Text = "Set Colors";
this.SetColorsMenuItem.Click += new System.EventHandler(this.SetColorsMenuItem_Click);
//
// toolStripSeparator8
//
this.toolStripSeparator8.Name = "toolStripSeparator8";
this.toolStripSeparator8.Size = new System.Drawing.Size(150, 6);
this.toolStripSeparator8.Size = new System.Drawing.Size(154, 6);
//
// ResetColorsToDefaultMenuItem
//
this.ResetColorsToDefaultMenuItem.Name = "ResetColorsToDefaultMenuItem";
this.ResetColorsToDefaultMenuItem.Size = new System.Drawing.Size(153, 22);
this.ResetColorsToDefaultMenuItem.Size = new System.Drawing.Size(157, 22);
this.ResetColorsToDefaultMenuItem.Text = "Reset to Default";
this.ResetColorsToDefaultMenuItem.Click += new System.EventHandler(this.ResetColorsToDefaultMenuItem_Click);
//
@ -464,7 +466,7 @@
this.toolStripMenuItem1,
this.viewN64MatrixToolStripMenuItem});
this.ViewerContextMenuStrip.Name = "ViewerContextMenuStrip";
this.ViewerContextMenuStrip.Size = new System.Drawing.Size(208, 264);
this.ViewerContextMenuStrip.Size = new System.Drawing.Size(222, 264);
this.ViewerContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.ViewerContextMenuStrip_Opening);
//
// CopyContextItem
@ -472,7 +474,7 @@
this.CopyContextItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Duplicate;
this.CopyContextItem.Name = "CopyContextItem";
this.CopyContextItem.ShortcutKeyDisplayString = "Ctrl+C";
this.CopyContextItem.Size = new System.Drawing.Size(207, 22);
this.CopyContextItem.Size = new System.Drawing.Size(221, 22);
this.CopyContextItem.Text = "&Copy";
this.CopyContextItem.Click += new System.EventHandler(this.CopyMenuItem_Click);
//
@ -480,7 +482,7 @@
//
this.ExportContextItem.Name = "ExportContextItem";
this.ExportContextItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E)));
this.ExportContextItem.Size = new System.Drawing.Size(207, 22);
this.ExportContextItem.Size = new System.Drawing.Size(221, 22);
this.ExportContextItem.Text = "&Export";
//
// PasteContextItem
@ -488,7 +490,7 @@
this.PasteContextItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Paste;
this.PasteContextItem.Name = "PasteContextItem";
this.PasteContextItem.ShortcutKeyDisplayString = "Ctrl+V";
this.PasteContextItem.Size = new System.Drawing.Size(207, 22);
this.PasteContextItem.Size = new System.Drawing.Size(221, 22);
this.PasteContextItem.Text = "&Paste";
this.PasteContextItem.Click += new System.EventHandler(this.PasteMenuItem_Click);
//
@ -497,7 +499,7 @@
this.FreezeContextItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Freeze;
this.FreezeContextItem.Name = "FreezeContextItem";
this.FreezeContextItem.ShortcutKeyDisplayString = "Space";
this.FreezeContextItem.Size = new System.Drawing.Size(207, 22);
this.FreezeContextItem.Size = new System.Drawing.Size(221, 22);
this.FreezeContextItem.Text = "&Freeze";
this.FreezeContextItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click);
//
@ -506,7 +508,7 @@
this.AddToRamWatchContextItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.FindHS;
this.AddToRamWatchContextItem.Name = "AddToRamWatchContextItem";
this.AddToRamWatchContextItem.ShortcutKeyDisplayString = "Ctrl+W";
this.AddToRamWatchContextItem.Size = new System.Drawing.Size(207, 22);
this.AddToRamWatchContextItem.Size = new System.Drawing.Size(221, 22);
this.AddToRamWatchContextItem.Text = "&Add to RAM Watch";
this.AddToRamWatchContextItem.Click += new System.EventHandler(this.AddToRamWatchMenuItem_Click);
//
@ -515,7 +517,7 @@
this.UnfreezeAllContextItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Unfreeze;
this.UnfreezeAllContextItem.Name = "UnfreezeAllContextItem";
this.UnfreezeAllContextItem.ShortcutKeyDisplayString = "Shift+Del";
this.UnfreezeAllContextItem.Size = new System.Drawing.Size(207, 22);
this.UnfreezeAllContextItem.Size = new System.Drawing.Size(221, 22);
this.UnfreezeAllContextItem.Text = "&Unfreeze All";
this.UnfreezeAllContextItem.Click += new System.EventHandler(this.UnfreezeAllMenuItem_Click);
//
@ -524,20 +526,20 @@
this.PokeContextItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.poke;
this.PokeContextItem.Name = "PokeContextItem";
this.PokeContextItem.ShortcutKeyDisplayString = "Ctrl+P";
this.PokeContextItem.Size = new System.Drawing.Size(207, 22);
this.PokeContextItem.Size = new System.Drawing.Size(221, 22);
this.PokeContextItem.Text = "&Poke Address";
this.PokeContextItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click);
//
// ContextSeparator1
//
this.ContextSeparator1.Name = "ContextSeparator1";
this.ContextSeparator1.Size = new System.Drawing.Size(204, 6);
this.ContextSeparator1.Size = new System.Drawing.Size(218, 6);
//
// IncrementContextItem
//
this.IncrementContextItem.Name = "IncrementContextItem";
this.IncrementContextItem.ShortcutKeyDisplayString = "+";
this.IncrementContextItem.Size = new System.Drawing.Size(207, 22);
this.IncrementContextItem.Size = new System.Drawing.Size(221, 22);
this.IncrementContextItem.Text = "&Increment";
this.IncrementContextItem.Click += new System.EventHandler(this.IncrementContextItem_Click);
//
@ -545,32 +547,32 @@
//
this.DecrementContextItem.Name = "DecrementContextItem";
this.DecrementContextItem.ShortcutKeyDisplayString = "-";
this.DecrementContextItem.Size = new System.Drawing.Size(207, 22);
this.DecrementContextItem.Size = new System.Drawing.Size(221, 22);
this.DecrementContextItem.Text = "&Decrement";
this.DecrementContextItem.Click += new System.EventHandler(this.DecrementContextItem_Click);
//
// ContextSeparator2
//
this.ContextSeparator2.Name = "ContextSeparator2";
this.ContextSeparator2.Size = new System.Drawing.Size(204, 6);
this.ContextSeparator2.Size = new System.Drawing.Size(218, 6);
//
// GoToContextItem
//
this.GoToContextItem.Name = "GoToContextItem";
this.GoToContextItem.ShortcutKeyDisplayString = "Ctrl+G";
this.GoToContextItem.Size = new System.Drawing.Size(207, 22);
this.GoToContextItem.Size = new System.Drawing.Size(221, 22);
this.GoToContextItem.Text = "&Go to Address...";
this.GoToContextItem.Click += new System.EventHandler(this.GoToAddressMenuItem_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(204, 6);
this.toolStripMenuItem1.Size = new System.Drawing.Size(218, 6);
//
// viewN64MatrixToolStripMenuItem
//
this.viewN64MatrixToolStripMenuItem.Name = "viewN64MatrixToolStripMenuItem";
this.viewN64MatrixToolStripMenuItem.Size = new System.Drawing.Size(207, 22);
this.viewN64MatrixToolStripMenuItem.Size = new System.Drawing.Size(221, 22);
this.viewN64MatrixToolStripMenuItem.Text = "View N64 Matrix";
this.viewN64MatrixToolStripMenuItem.Click += new System.EventHandler(this.viewN64MatrixToolStripMenuItem_Click);
//
@ -638,6 +640,14 @@
this.Header.TabIndex = 2;
this.Header.Text = "label1";
//
// swapBytesToolStripMenuItem
//
this.swapBytesToolStripMenuItem.CheckOnClick = true;
this.swapBytesToolStripMenuItem.Name = "swapBytesToolStripMenuItem";
this.swapBytesToolStripMenuItem.Size = new System.Drawing.Size(221, 22);
this.swapBytesToolStripMenuItem.Text = "Swap Bytes";
this.swapBytesToolStripMenuItem.Click += new System.EventHandler(this.SwapBytesMenuItem_Click);
//
// HexEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -732,5 +742,6 @@
private System.Windows.Forms.ToolStripMenuItem ExportContextItem;
private System.Windows.Forms.ToolStripMenuItem ExportMenuItem;
private System.Windows.Forms.ToolStripMenuItem importAsBinaryToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem swapBytesToolStripMenuItem;
}
}

View File

@ -79,6 +79,9 @@ namespace BizHawk.Client.EmuHawk
private MemoryDomain _romDomain;
private HexFind _hexFind = new HexFind();
[ConfigPersist]
private bool SwapBytes { get; set; }
[ConfigPersist]
private bool BigEndian { get; set; }
@ -179,7 +182,9 @@ namespace BizHawk.Client.EmuHawk
_domain = MemoryDomains.MainMemory;
}
SwapBytes = false;
BigEndian = _domain.EndianType == MemoryDomain.Endian.Big;
_maxRow = _domain.Size / 2;
// Don't reset scroll bar if restarting the same rom
@ -526,7 +531,24 @@ namespace BizHawk.Client.EmuHawk
{
if (_addr + j + DataSize <= _domain.Size)
{
rowStr.AppendFormat(_digitFormatString, MakeValue(_addr + j));
int t_val = 0;
int t_next = 0;
bool is_cht;
for (int k = 0; k < DataSize; k++)
{
t_next = MakeValue(1, _addr + j + k, out is_cht);
if (SwapBytes)
{
t_val += (t_next << (k * 8));
}
else
{
t_val += (t_next << ((DataSize - k - 1) * 8));
}
}
rowStr.AppendFormat(_digitFormatString, t_val);
}
else
{
@ -565,28 +587,31 @@ namespace BizHawk.Client.EmuHawk
: _domain.PeekByte(address);
}
private int MakeValue(int dataSize, long address)
private int MakeValue(int dataSize, long address, out bool is_cheat)
{
if (Global.CheatList.IsActive(_domain, address))
{
return Global.CheatList.GetCheatValue(_domain, address, (WatchSize)DataSize ).Value;
is_cheat = true;
return Global.CheatList.GetCheatValue(_domain, address, (WatchSize)dataSize ).Value;
}
is_cheat = false;
switch (dataSize)
{
default:
case 1:
return _domain.PeekByte(address);
case 2:
return _domain.PeekUshort(address, BigEndian);
return _domain.PeekUshort(address, SwapBytes);
case 4:
return (int)_domain.PeekUint(address, BigEndian);
return (int)_domain.PeekUint(address, SwapBytes);
}
}
private int MakeValue(long address)
{
return MakeValue(DataSize, address);
bool temp;
return MakeValue(DataSize, address, out temp);
}
private void SetMemoryDomain(string name)
@ -600,6 +625,7 @@ namespace BizHawk.Client.EmuHawk
_domain = MemoryDomains[name];
}
SwapBytes = false;
BigEndian = _domain.EndianType == MemoryDomain.Endian.Big;
_maxRow = _domain.Size / 2;
SetUpScrollBar();
@ -1444,8 +1470,9 @@ namespace BizHawk.Client.EmuHawk
{
long start = addresses[i];
long end = addresses[i] + DataSize -1 ;
bool temp;
for(long a = start;a<=end;a++)
sb.AppendFormat("{0:X2}", MakeValue(1,a));
sb.AppendFormat("{0:X2}", MakeValue(1,a, out temp));
}
}
@ -1598,7 +1625,13 @@ namespace BizHawk.Client.EmuHawk
private void BigEndianMenuItem_Click(object sender, EventArgs e)
{
BigEndian ^= true;
//BigEndian ^= true;
//UpdateValues();
}
private void SwapBytesMenuItem_Click(object sender, EventArgs e)
{
SwapBytes ^= true;
UpdateValues();
}

View File

@ -610,9 +610,9 @@ namespace BizHawk.Client.EmuHawk
{
TasBranch branch = GetBranch(BranchView.CurrentCell.RowIndex.Value);
Point location = Location;
location.Offset(-Screenshot.Width, 0);
int width = Tastudio.VideoProvider.BufferWidth;
int height = Tastudio.VideoProvider.BufferHeight;
int width = branch.OSDFrameBuffer.Width;
int height = branch.OSDFrameBuffer.Height;
location.Offset(-width, 0);
Screenshot.UpdateValues(branch, PointToScreen(location), width, height,
(int)Graphics.FromHwnd(this.Handle).MeasureString(

View File

@ -48,28 +48,38 @@ namespace BizHawk.Client.EmuHawk
this.DiskCapacityNumeric = new System.Windows.Forms.NumericUpDown();
this.label5 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.SaveCapacityNumeric = new System.Windows.Forms.NumericUpDown();
this.FileCapacityNumeric = new System.Windows.Forms.NumericUpDown();
this.label7 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.NumSaveStatesLabel = new System.Windows.Forms.Label();
this.BranchStatesInTasproj = new System.Windows.Forms.CheckBox();
this.EraseBranchStatesFirst = new System.Windows.Forms.CheckBox();
this.StateGap = new System.Windows.Forms.NumericUpDown();
this.FileStateGapNumeric = new System.Windows.Forms.NumericUpDown();
this.label10 = new System.Windows.Forms.Label();
this.label11 = new System.Windows.Forms.Label();
this.NumFramesLabel = new System.Windows.Forms.Label();
this.FileNumFramesLabel = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.label14 = new System.Windows.Forms.Label();
this.MemFramesLabel = new System.Windows.Forms.Label();
this.label13 = new System.Windows.Forms.Label();
this.MemStateGapDividerNumeric = new System.Windows.Forms.NumericUpDown();
this.label12 = new System.Windows.Forms.Label();
this.groupBox2 = new System.Windows.Forms.GroupBox();
((System.ComponentModel.ISupportInitialize)(this.MemCapacityNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.DiskCapacityNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.SaveCapacityNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.StateGap)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.FileCapacityNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.FileStateGapNumeric)).BeginInit();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.MemStateGapDividerNumeric)).BeginInit();
this.groupBox2.SuspendLayout();
this.SuspendLayout();
//
// 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(217, 220);
this.CancelBtn.Location = new System.Drawing.Point(242, 259);
this.CancelBtn.Name = "CancelBtn";
this.CancelBtn.Size = new System.Drawing.Size(60, 23);
this.CancelBtn.TabIndex = 0;
@ -80,7 +90,7 @@ namespace BizHawk.Client.EmuHawk
// 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(151, 220);
this.OkBtn.Location = new System.Drawing.Point(176, 259);
this.OkBtn.Name = "OkBtn";
this.OkBtn.Size = new System.Drawing.Size(60, 23);
this.OkBtn.TabIndex = 1;
@ -90,7 +100,7 @@ namespace BizHawk.Client.EmuHawk
//
// MemCapacityNumeric
//
this.MemCapacityNumeric.Location = new System.Drawing.Point(15, 49);
this.MemCapacityNumeric.Location = new System.Drawing.Point(12, 36);
this.MemCapacityNumeric.Maximum = new decimal(new int[] {
1024,
0,
@ -114,20 +124,20 @@ namespace BizHawk.Client.EmuHawk
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(70, 52);
this.label1.Location = new System.Drawing.Point(73, 39);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(21, 13);
this.label1.Size = new System.Drawing.Size(23, 13);
this.label1.TabIndex = 4;
this.label1.Text = "mb";
this.label1.Text = "MB";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 32);
this.label2.Location = new System.Drawing.Point(9, 19);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(88, 13);
this.label2.Size = new System.Drawing.Size(48, 13);
this.label2.TabIndex = 5;
this.label2.Text = "Memory Capacity";
this.label2.Text = "Capacity";
//
// label3
//
@ -150,7 +160,7 @@ namespace BizHawk.Client.EmuHawk
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(12, 136);
this.label4.Location = new System.Drawing.Point(160, 9);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(84, 13);
this.label4.TabIndex = 8;
@ -159,17 +169,18 @@ namespace BizHawk.Client.EmuHawk
// NumStatesLabel
//
this.NumStatesLabel.AutoSize = true;
this.NumStatesLabel.Location = new System.Drawing.Point(99, 136);
this.NumStatesLabel.Location = new System.Drawing.Point(250, 9);
this.NumStatesLabel.Name = "NumStatesLabel";
this.NumStatesLabel.Size = new System.Drawing.Size(25, 13);
this.NumStatesLabel.Size = new System.Drawing.Size(13, 13);
this.NumStatesLabel.TabIndex = 9;
this.NumStatesLabel.Text = "1kb";
this.NumStatesLabel.Text = "1";
//
// DiskCapacityNumeric
//
this.DiskCapacityNumeric.Location = new System.Drawing.Point(15, 113);
this.DiskCapacityNumeric.Enabled = false;
this.DiskCapacityNumeric.Location = new System.Drawing.Point(24, 241);
this.DiskCapacityNumeric.Maximum = new decimal(new int[] {
65536,
1,
0,
0,
0});
@ -182,7 +193,7 @@ namespace BizHawk.Client.EmuHawk
this.DiskCapacityNumeric.Size = new System.Drawing.Size(55, 20);
this.DiskCapacityNumeric.TabIndex = 3;
this.DiskCapacityNumeric.Value = new decimal(new int[] {
512,
1,
0,
0,
0});
@ -191,61 +202,63 @@ namespace BizHawk.Client.EmuHawk
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(70, 116);
this.label5.Enabled = false;
this.label5.Location = new System.Drawing.Point(79, 244);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(21, 13);
this.label5.Size = new System.Drawing.Size(23, 13);
this.label5.TabIndex = 4;
this.label5.Text = "mb";
this.label5.Text = "MB";
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(12, 96);
this.label6.Enabled = false;
this.label6.Location = new System.Drawing.Point(21, 224);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(72, 13);
this.label6.TabIndex = 5;
this.label6.Text = "Disk Capacity";
//
// SaveCapacityNumeric
// FileCapacityNumeric
//
this.SaveCapacityNumeric.Location = new System.Drawing.Point(150, 49);
this.SaveCapacityNumeric.Maximum = new decimal(new int[] {
this.FileCapacityNumeric.Location = new System.Drawing.Point(12, 36);
this.FileCapacityNumeric.Maximum = new decimal(new int[] {
65536,
0,
0,
0});
this.SaveCapacityNumeric.Name = "SaveCapacityNumeric";
this.SaveCapacityNumeric.Size = new System.Drawing.Size(55, 20);
this.SaveCapacityNumeric.TabIndex = 3;
this.SaveCapacityNumeric.Value = new decimal(new int[] {
this.FileCapacityNumeric.Name = "FileCapacityNumeric";
this.FileCapacityNumeric.Size = new System.Drawing.Size(55, 20);
this.FileCapacityNumeric.TabIndex = 3;
this.FileCapacityNumeric.Value = new decimal(new int[] {
512,
0,
0,
0});
this.SaveCapacityNumeric.ValueChanged += new System.EventHandler(this.SaveCapacityNumeric_ValueChanged);
this.FileCapacityNumeric.ValueChanged += new System.EventHandler(this.SaveCapacityNumeric_ValueChanged);
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(205, 52);
this.label7.Location = new System.Drawing.Point(73, 39);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(21, 13);
this.label7.Size = new System.Drawing.Size(23, 13);
this.label7.TabIndex = 4;
this.label7.Text = "mb";
this.label7.Text = "MB";
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(147, 32);
this.label8.Location = new System.Drawing.Point(9, 19);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(112, 13);
this.label8.Size = new System.Drawing.Size(48, 13);
this.label8.TabIndex = 5;
this.label8.Text = "Project Save Capacity";
this.label8.Text = "Capacity";
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(147, 72);
this.label9.Location = new System.Drawing.Point(9, 59);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(84, 13);
this.label9.TabIndex = 8;
@ -254,21 +267,21 @@ namespace BizHawk.Client.EmuHawk
// NumSaveStatesLabel
//
this.NumSaveStatesLabel.AutoSize = true;
this.NumSaveStatesLabel.Location = new System.Drawing.Point(234, 72);
this.NumSaveStatesLabel.Location = new System.Drawing.Point(96, 59);
this.NumSaveStatesLabel.Name = "NumSaveStatesLabel";
this.NumSaveStatesLabel.Size = new System.Drawing.Size(25, 13);
this.NumSaveStatesLabel.Size = new System.Drawing.Size(13, 13);
this.NumSaveStatesLabel.TabIndex = 9;
this.NumSaveStatesLabel.Text = "1kb";
this.NumSaveStatesLabel.Text = "1";
//
// BranchStatesInTasproj
//
this.BranchStatesInTasproj.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.BranchStatesInTasproj.AutoSize = true;
this.BranchStatesInTasproj.Location = new System.Drawing.Point(15, 165);
this.BranchStatesInTasproj.Location = new System.Drawing.Point(12, 153);
this.BranchStatesInTasproj.Name = "BranchStatesInTasproj";
this.BranchStatesInTasproj.Size = new System.Drawing.Size(158, 17);
this.BranchStatesInTasproj.Size = new System.Drawing.Size(118, 17);
this.BranchStatesInTasproj.TabIndex = 10;
this.BranchStatesInTasproj.Text = "Put branch states to .tasproj";
this.BranchStatesInTasproj.Text = "Save branch states";
this.BranchStatesInTasproj.UseVisualStyleBackColor = true;
this.BranchStatesInTasproj.CheckedChanged += new System.EventHandler(this.BranchStatesInTasproj_CheckedChanged);
//
@ -278,7 +291,7 @@ namespace BizHawk.Client.EmuHawk
this.EraseBranchStatesFirst.AutoSize = true;
this.EraseBranchStatesFirst.Checked = true;
this.EraseBranchStatesFirst.CheckState = System.Windows.Forms.CheckState.Checked;
this.EraseBranchStatesFirst.Location = new System.Drawing.Point(15, 190);
this.EraseBranchStatesFirst.Location = new System.Drawing.Point(6, 153);
this.EraseBranchStatesFirst.Name = "EraseBranchStatesFirst";
this.EraseBranchStatesFirst.Size = new System.Drawing.Size(139, 17);
this.EraseBranchStatesFirst.TabIndex = 11;
@ -286,50 +299,146 @@ namespace BizHawk.Client.EmuHawk
this.EraseBranchStatesFirst.UseVisualStyleBackColor = true;
this.EraseBranchStatesFirst.CheckedChanged += new System.EventHandler(this.EraseBranchStatesFIrst_CheckedChanged);
//
// StateGap
// FileStateGapNumeric
//
this.StateGap.Location = new System.Drawing.Point(151, 112);
this.StateGap.Maximum = new decimal(new int[] {
this.FileStateGapNumeric.Location = new System.Drawing.Point(12, 100);
this.FileStateGapNumeric.Maximum = new decimal(new int[] {
8,
0,
0,
0});
this.StateGap.Name = "StateGap";
this.StateGap.Size = new System.Drawing.Size(55, 20);
this.StateGap.TabIndex = 12;
this.StateGap.Value = new decimal(new int[] {
this.FileStateGapNumeric.Name = "FileStateGapNumeric";
this.FileStateGapNumeric.Size = new System.Drawing.Size(55, 20);
this.FileStateGapNumeric.TabIndex = 12;
this.FileStateGapNumeric.Value = new decimal(new int[] {
1,
0,
0,
0});
this.StateGap.ValueChanged += new System.EventHandler(this.StateGap_ValueChanged);
this.FileStateGapNumeric.ValueChanged += new System.EventHandler(this.FileStateGap_ValueChanged);
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(148, 96);
this.label10.Location = new System.Drawing.Point(9, 84);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(91, 13);
this.label10.Size = new System.Drawing.Size(55, 13);
this.label10.TabIndex = 13;
this.label10.Text = "Project State Gap";
this.label10.Text = "State Gap";
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(147, 135);
this.label11.Location = new System.Drawing.Point(8, 123);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(61, 13);
this.label11.TabIndex = 14;
this.label11.Text = "State every";
//
// NumFramesLabel
// FileNumFramesLabel
//
this.NumFramesLabel.AutoSize = true;
this.NumFramesLabel.Location = new System.Drawing.Point(204, 135);
this.NumFramesLabel.Name = "NumFramesLabel";
this.NumFramesLabel.Size = new System.Drawing.Size(47, 13);
this.NumFramesLabel.TabIndex = 15;
this.NumFramesLabel.Text = "0 frames";
this.FileNumFramesLabel.AutoSize = true;
this.FileNumFramesLabel.Location = new System.Drawing.Point(65, 123);
this.FileNumFramesLabel.Name = "FileNumFramesLabel";
this.FileNumFramesLabel.Size = new System.Drawing.Size(47, 13);
this.FileNumFramesLabel.TabIndex = 15;
this.FileNumFramesLabel.Text = "0 frames";
//
// groupBox1
//
this.groupBox1.Controls.Add(this.label14);
this.groupBox1.Controls.Add(this.MemFramesLabel);
this.groupBox1.Controls.Add(this.label13);
this.groupBox1.Controls.Add(this.MemStateGapDividerNumeric);
this.groupBox1.Controls.Add(this.label12);
this.groupBox1.Controls.Add(this.EraseBranchStatesFirst);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.MemCapacityNumeric);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Location = new System.Drawing.Point(12, 34);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(143, 176);
this.groupBox1.TabIndex = 16;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Memory Usage";
//
// label14
//
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(73, 102);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(21, 13);
this.label14.TabIndex = 17;
this.label14.Text = "KB";
//
// MemFramesLabel
//
this.MemFramesLabel.AutoSize = true;
this.MemFramesLabel.Location = new System.Drawing.Point(66, 123);
this.MemFramesLabel.Name = "MemFramesLabel";
this.MemFramesLabel.Size = new System.Drawing.Size(47, 13);
this.MemFramesLabel.TabIndex = 16;
this.MemFramesLabel.Text = "0 frames";
//
// label13
//
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(9, 123);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(61, 13);
this.label13.TabIndex = 15;
this.label13.Text = "State every";
//
// MemStateGapDividerNumeric
//
this.MemStateGapDividerNumeric.Location = new System.Drawing.Point(12, 100);
this.MemStateGapDividerNumeric.Maximum = new decimal(new int[] {
1024,
0,
0,
0});
this.MemStateGapDividerNumeric.Minimum = new decimal(new int[] {
64,
0,
0,
0});
this.MemStateGapDividerNumeric.Name = "MemStateGapDividerNumeric";
this.MemStateGapDividerNumeric.Size = new System.Drawing.Size(55, 20);
this.MemStateGapDividerNumeric.TabIndex = 7;
this.MemStateGapDividerNumeric.Value = new decimal(new int[] {
65,
0,
0,
0});
this.MemStateGapDividerNumeric.ValueChanged += new System.EventHandler(this.MemStateGapDivider_ValueChanged);
//
// label12
//
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(9, 84);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(91, 13);
this.label12.TabIndex = 6;
this.label12.Text = "State Gap Divider";
//
// groupBox2
//
this.groupBox2.Controls.Add(this.label8);
this.groupBox2.Controls.Add(this.FileCapacityNumeric);
this.groupBox2.Controls.Add(this.FileNumFramesLabel);
this.groupBox2.Controls.Add(this.label7);
this.groupBox2.Controls.Add(this.BranchStatesInTasproj);
this.groupBox2.Controls.Add(this.label11);
this.groupBox2.Controls.Add(this.label9);
this.groupBox2.Controls.Add(this.label10);
this.groupBox2.Controls.Add(this.NumSaveStatesLabel);
this.groupBox2.Controls.Add(this.FileStateGapNumeric);
this.groupBox2.Location = new System.Drawing.Point(163, 34);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(138, 176);
this.groupBox2.TabIndex = 17;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Project File";
//
// StateHistorySettingsForm
//
@ -337,28 +446,16 @@ namespace BizHawk.Client.EmuHawk
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(289, 255);
this.Controls.Add(this.NumFramesLabel);
this.Controls.Add(this.label11);
this.Controls.Add(this.label10);
this.Controls.Add(this.StateGap);
this.Controls.Add(this.EraseBranchStatesFirst);
this.Controls.Add(this.BranchStatesInTasproj);
this.Controls.Add(this.NumSaveStatesLabel);
this.Controls.Add(this.NumStatesLabel);
this.Controls.Add(this.label9);
this.Controls.Add(this.label4);
this.Controls.Add(this.SavestateSizeLabel);
this.Controls.Add(this.label3);
this.Controls.Add(this.label8);
this.Controls.Add(this.label7);
this.Controls.Add(this.label6);
this.Controls.Add(this.label5);
this.Controls.Add(this.SaveCapacityNumeric);
this.Controls.Add(this.label2);
this.ClientSize = new System.Drawing.Size(315, 294);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.DiskCapacityNumeric);
this.Controls.Add(this.label1);
this.Controls.Add(this.MemCapacityNumeric);
this.Controls.Add(this.label5);
this.Controls.Add(this.SavestateSizeLabel);
this.Controls.Add(this.label6);
this.Controls.Add(this.label4);
this.Controls.Add(this.label3);
this.Controls.Add(this.NumStatesLabel);
this.Controls.Add(this.OkBtn);
this.Controls.Add(this.CancelBtn);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
@ -369,8 +466,13 @@ namespace BizHawk.Client.EmuHawk
this.Load += new System.EventHandler(this.StateHistorySettings_Load);
((System.ComponentModel.ISupportInitialize)(this.MemCapacityNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.DiskCapacityNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.SaveCapacityNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.StateGap)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.FileCapacityNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.FileStateGapNumeric)).EndInit();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.MemStateGapDividerNumeric)).EndInit();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -388,16 +490,23 @@ namespace BizHawk.Client.EmuHawk
private NumericUpDown DiskCapacityNumeric;
private Label label5;
private Label label6;
private NumericUpDown SaveCapacityNumeric;
private NumericUpDown FileCapacityNumeric;
private Label label7;
private Label label8;
private Label label9;
private Label NumSaveStatesLabel;
private CheckBox BranchStatesInTasproj;
private CheckBox EraseBranchStatesFirst;
private NumericUpDown StateGap;
private NumericUpDown FileStateGapNumeric;
private Label label10;
private Label label11;
private Label NumFramesLabel;
private Label FileNumFramesLabel;
private GroupBox groupBox1;
private NumericUpDown MemStateGapDividerNumeric;
private Label label12;
private GroupBox groupBox2;
private Label MemFramesLabel;
private Label label13;
private Label label14;
}
}

View File

@ -29,11 +29,16 @@ namespace BizHawk.Client.EmuHawk
_settings.Capacitymb : MemCapacityNumeric.Maximum;
DiskCapacityNumeric.Value = _settings.DiskCapacitymb < MemCapacityNumeric.Maximum ?
_settings.DiskCapacitymb : MemCapacityNumeric.Maximum;
SaveCapacityNumeric.Value = _settings.DiskSaveCapacitymb < MemCapacityNumeric.Maximum ?
FileCapacityNumeric.Value = _settings.DiskSaveCapacitymb < MemCapacityNumeric.Maximum ?
_settings.DiskSaveCapacitymb : MemCapacityNumeric.Maximum;
StateGap.Value = _settings.StateGap;
SavestateSizeLabel.Text = Math.Round(_stateSizeMb, 2).ToString() + " mb";
MemStateGapDividerNumeric.Maximum = Statable.SaveStateBinary().Length / 1024 / 2 + 1;
MemStateGapDividerNumeric.Minimum = Statable.SaveStateBinary().Length / 1024 / 16;
MemStateGapDividerNumeric.Value = _settings.MemStateGapDivider < MemStateGapDividerNumeric.Minimum ?
MemStateGapDividerNumeric.Minimum : _settings.MemStateGapDivider;
FileStateGapNumeric.Value = _settings.FileStateGap;
SavestateSizeLabel.Text = Math.Round(_stateSizeMb, 2).ToString() + " MB";
CapacityNumeric_ValueChanged(null, null);
SaveCapacityNumeric_ValueChanged(null, null);
BranchStatesInTasproj.Checked = _settings.BranchStatesInTasproj;
@ -47,8 +52,9 @@ namespace BizHawk.Client.EmuHawk
{
_settings.Capacitymb = (int)MemCapacityNumeric.Value;
_settings.DiskCapacitymb = (int)DiskCapacityNumeric.Value;
_settings.DiskSaveCapacitymb = (int)SaveCapacityNumeric.Value;
_settings.StateGap = (int)StateGap.Value;
_settings.DiskSaveCapacitymb = (int)FileCapacityNumeric.Value;
_settings.MemStateGapDivider = (int)MemStateGapDividerNumeric.Value;
_settings.FileStateGap = (int)FileStateGapNumeric.Value;
DialogResult = DialogResult.OK;
Close();
}
@ -68,7 +74,7 @@ namespace BizHawk.Client.EmuHawk
private void SaveCapacityNumeric_ValueChanged(object sender, EventArgs e)
{
NumSaveStatesLabel.Text = ((int)Math.Floor(SaveCapacityNumeric.Value / _stateSizeMb)).ToString();
NumSaveStatesLabel.Text = ((int)Math.Floor(FileCapacityNumeric.Value / _stateSizeMb)).ToString();
}
private void BranchStatesInTasproj_CheckedChanged(object sender, EventArgs e)
@ -81,11 +87,23 @@ namespace BizHawk.Client.EmuHawk
_settings.EraseBranchStatesFirst = EraseBranchStatesFirst.Checked;
}
private void StateGap_ValueChanged(object sender, EventArgs e)
private void FileStateGap_ValueChanged(object sender, EventArgs e)
{
NumFramesLabel.Text = StateGap.Value == 0
FileNumFramesLabel.Text = FileStateGapNumeric.Value == 0
? "frame"
: $"{1 << (int)StateGap.Value} frames";
: $"{1 << (int)FileStateGapNumeric.Value} frames";
}
private void MemStateGapDivider_ValueChanged(object sender, EventArgs e)
{
int val = (int)(Statable.SaveStateBinary().Length / MemStateGapDividerNumeric.Value / 1024);
if (val <= 1)
MemStateGapDividerNumeric.Maximum = MemStateGapDividerNumeric.Value;
MemFramesLabel.Text = val <= 1
? "frame"
: $"{val} frames";
}
}
}

View File

@ -11,11 +11,8 @@ namespace BizHawk.Client.EmuHawk
{
public partial class ScreenshotForm : Form
{
// but still appear topmost
private const int WS_EX_TOPMOST = 0x00000008;
private const int WidthCap = 320;
private const int HeightCap = 240;
private const int Interval = 40;
private const double AlphaStep = 0.125;
@ -32,9 +29,7 @@ namespace BizHawk.Client.EmuHawk
public ScreenshotForm()
{
InitializeComponent();
Width = WidthCap;
Height = HeightCap;
var fontSize = 10;
var fontStyle = FontStyle.Regular;
Font = new Font(FontFamily.GenericMonospace, fontSize, fontStyle);
@ -71,15 +66,6 @@ namespace BizHawk.Client.EmuHawk
Text = _branch.UserText;
Location = location;
// Set the screenshot to "1x" resolution of the core
// cores like n64 and psx are going to still have sizes too big for the control, so cap them
if (Width > WidthCap)
{
double ratio = WidthCap / (double)Width;
Width = WidthCap;
_drawingHeight = (int)((double)(_drawingHeight) * ratio);
}
if (Padding > 0)
{
Padding += 2;

View File

@ -55,7 +55,7 @@ namespace BizHawk.Client.EmuHawk
private bool _triggerAutoRestore; // If true, autorestore will be called on mouse up
private bool? _autoRestorePaused = null;
private int? _seekStartFrame = null;
private bool _shouldUnpauseFromRewind = false;
private bool _unpauseAfterSeeking = false;
private ControllerDefinition ControllerType => Global.MovieSession.MovieControllerAdapter.Definition;
@ -111,10 +111,10 @@ namespace BizHawk.Client.EmuHawk
}
Mainform.PauseOnFrame = null;
if (_shouldUnpauseFromRewind)
if (_unpauseAfterSeeking)
{
Mainform.UnpauseEmulator();
_shouldUnpauseFromRewind = false;
_unpauseAfterSeeking = false;
}
if (CurrentTasMovie != null)
@ -762,7 +762,8 @@ namespace BizHawk.Client.EmuHawk
private void TasView_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && !TasView.IsPointingAtColumnHeader && !_supressContextMenu && TasView.SelectedRows.Any())
if (e.Button == MouseButtons.Right && !TasView.IsPointingAtColumnHeader &&
!_supressContextMenu && TasView.SelectedRows.Any() && !_leftButtonHeld)
{
if (Global.MovieSession.Movie.FrameCount < TasView.SelectedRows.Max())
{

View File

@ -72,11 +72,10 @@ namespace BizHawk.Client.EmuHawk
}
else if (ofd.FileName.EndsWith(".bkm") || ofd.FileName.EndsWith(".bk2")) // todo: proper extention iteration
{
Mainform.StartNewMovie(MovieService.Get(ofd.FileName), false);
var result1 = MessageBox.Show("This is a regular movie, a new project must be created from it, in order to use in TAStudio\nProceed?", "Convert movie", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (result1 == DialogResult.OK)
{
Mainform.StartNewMovie(MovieService.Get(ofd.FileName), false);
ConvertCurrentMovieToTasproj();
StartNewMovieWrapper(false);
SetUpColumns();

View File

@ -829,7 +829,7 @@ namespace BizHawk.Client.EmuHawk
if (frame == Emulator.Frame)
return;
_shouldUnpauseFromRewind = fromRewinding && !Mainform.EmulatorPaused;
_unpauseAfterSeeking = (fromRewinding || WasRecording) && !Mainform.EmulatorPaused;
TastudioPlayMode();
KeyValuePair<int, byte[]> closestState = CurrentTasMovie.TasStateManager.GetStateClosestToFrame(frame);
if (closestState.Value != null && (frame < Emulator.Frame || closestState.Key > Emulator.Frame))
@ -871,7 +871,8 @@ namespace BizHawk.Client.EmuHawk
// frame == Emulator.Frame when frame == 0
if (frame > Emulator.Frame)
{
if (Mainform.EmulatorPaused || Mainform.IsSeeking || fromRewinding) // make seek frame keep up with emulation on fast scrolls
// make seek frame keep up with emulation on fast scrolls
if (Mainform.EmulatorPaused || Mainform.IsSeeking || fromRewinding || WasRecording)
{
StartSeeking(frame);
}

View File

@ -94,6 +94,8 @@ namespace BizHawk.Emulation.Common
public uint? Address => null;
public uint? AddressMask => null;
public string Scope => ""; // This will be relevant if/when the trace logger can trace anything other than the system bus
}
}
}

View File

@ -14,8 +14,14 @@ namespace BizHawk.Emulation.Common
/// <seealso cref="IMemoryCallbackSystem" />
public class MemoryCallbackSystem : IMemoryCallbackSystem
{
public MemoryCallbackSystem()
public MemoryCallbackSystem(string[] availableScopes)
{
if (availableScopes == null)
{
availableScopes = new[] { "System Bus" };
}
AvailableScopes = availableScopes;
ExecuteCallbacksAvailable = true;
_reads.CollectionChanged += OnCollectionChanged;
@ -35,8 +41,15 @@ namespace BizHawk.Emulation.Common
public bool ExecuteCallbacksAvailable { get; }
public string[] AvailableScopes { get; }
public void Add(IMemoryCallback callback)
{
if (!AvailableScopes.Contains(callback.Scope))
{
throw new InvalidOperationException($"{callback.Scope} is not currently supported for callbacks");
}
switch (callback.Type)
{
case MemoryCallbackType.Execute:
@ -61,38 +74,38 @@ namespace BizHawk.Emulation.Common
_empty = false;
}
private static void Call(ObservableCollection<IMemoryCallback> cbs, uint addr)
private static void Call(ObservableCollection<IMemoryCallback> cbs, uint addr, string scope)
{
for (int i = 0; i < cbs.Count; i++)
{
if (!cbs[i].Address.HasValue || cbs[i].Address == (addr & cbs[i].AddressMask))
if (!cbs[i].Address.HasValue || (cbs[i].Scope == scope && cbs[i].Address == (addr & cbs[i].AddressMask)))
{
cbs[i].Callback();
}
}
}
public void CallReads(uint addr)
public void CallReads(uint addr, string scope)
{
if (_hasReads)
{
Call(_reads, addr);
Call(_reads, addr, scope);
}
}
public void CallWrites(uint addr)
public void CallWrites(uint addr, string scope)
{
if (_hasWrites)
{
Call(_writes, addr);
Call(_writes, addr, scope);
}
}
public void CallExecutes(uint addr)
public void CallExecutes(uint addr, string scope)
{
if (_hasExecutes)
{
Call(_execs, addr);
Call(_execs, addr, scope);
}
}
@ -102,6 +115,21 @@ namespace BizHawk.Emulation.Common
public bool HasExecutes => _hasExecutes;
public bool HasReadsForScope(string scope)
{
return _reads.Where(e => e.Scope == scope).Any();
}
public bool HasWritesForScope(string scope)
{
return _writes.Where(e => e.Scope == scope).Any();
}
public bool HasExecutesForScope(string scope)
{
return _execs.Where(e => e.Scope == scope).Any();
}
private void UpdateHasVariables()
{
_hasReads = _reads.Count > 0;
@ -273,7 +301,7 @@ namespace BizHawk.Emulation.Common
public class MemoryCallback : IMemoryCallback
{
public MemoryCallback(MemoryCallbackType type, string name, Action callback, uint? address, uint? mask)
public MemoryCallback(string scope, MemoryCallbackType type, string name, Action callback, uint? address, uint? mask)
{
if (type == MemoryCallbackType.Execute && !address.HasValue)
{
@ -285,6 +313,7 @@ namespace BizHawk.Emulation.Common
Callback = callback;
Address = address;
AddressMask = mask ?? 0xFFFFFFFF;
Scope = scope;
}
public MemoryCallbackType Type { get; }
@ -292,5 +321,6 @@ namespace BizHawk.Emulation.Common
public Action Callback { get; }
public uint? Address { get; }
public uint? AddressMask { get; }
public string Scope { get; }
}
}

View File

@ -20,6 +20,20 @@ namespace BizHawk.Emulation.Common
}
}
public class NoAvailableCoreException : Exception
{
public NoAvailableCoreException()
: base("System is currently NOT emulated")
{
}
public NoAvailableCoreException(string message)
: base ("System is currently NOT emulated: " + message)
{
}
}
public class CGBNotSupportedException : Exception
{
public CGBNotSupportedException()

View File

@ -37,27 +37,49 @@ namespace BizHawk.Emulation.Common
/// </summary>
bool HasExecutes { get; }
/// <summary>
/// Gets a value indicating whether or not there are currently any read hooks
/// </summary>
bool HasReadsForScope(string scope);
/// <summary>
/// Gets a value indicating whether or not there are currently any write hooks
/// </summary>
bool HasWritesForScope(string scope);
/// <summary>
/// Gets a value indicating whether or not there are currently any execute hooks
/// </summary>
bool HasExecutesForScope(string scope);
/// <summary>
/// Adds a callback for the given type to the given address
/// If no address is specified the callback will be hooked to all addresses
/// Note: an execute callback can not be added without an address, else an InvalidOperationException will occur
/// </summary>
/// <exception cref="InvalidCastException">Thrown when the <see cref="IMemoryCallback.Scope"/> property of the <see cref="IMemoryCallback"/> is not in the <see cref="AvailableScopes"/></exception>
void Add(IMemoryCallback callback);
/// <summary>
/// Executes all Read callbacks for the given address
/// Executes all Read callbacks for the given address and domain
/// </summary>
void CallReads(uint addr);
/// <param name="addr">The address to check for callbacks</param>
/// <param name="scope">The scope that the address pertains to. Must be a value in <see cref="AvailableScopes"></param>
void CallReads(uint addr, string scope);
/// <summary>
/// Executes all Write callbacks for the given address
/// Executes all Write callbacks for the given address and domain
/// </summary>
void CallWrites(uint addr);
/// <param name="addr">The address to check for callbacks</param>
/// <param name="scope">The scope that the address pertains to. Must be a value in <see cref="AvailableScopes"></param>
void CallWrites(uint addr, string scope);
/// <summary>
/// Executes all Execute callbacks for the given address
/// Executes all Execute callbacks for the given address and domain
/// </summary>
void CallExecutes(uint addr);
/// <param name="addr">The address to check for callbacks</param>
/// <param name="scope">The scope that the address pertains to. Must be a value in <see cref="AvailableScopes"></param>
void CallExecutes(uint addr, string scope);
/// <summary>
/// Removes the given callback from the list
@ -73,6 +95,12 @@ namespace BizHawk.Emulation.Common
/// Removes all read,write, and execute callbacks
/// </summary>
void Clear();
/// <summary>
/// A list of available "scopes" (memory domains, cpus, etc) that a the <see cref="IMemoryCallback.Scope"/> property of the <see cref="IMemoryCallback"/> can have
/// Passing a <see cref="IMemoryCallback"/> into the <see cref="Add(IMemoryCallback)"/> method that is not in this list will result in an <seealso cref="InvalidOperationException"/>
/// </summary>
string[] AvailableScopes { get; }
}
/// <summary>
@ -86,6 +114,7 @@ namespace BizHawk.Emulation.Common
Action Callback { get; }
uint? Address { get; }
uint? AddressMask { get; }
string Scope { get; }
}
public enum MemoryCallbackType

View File

@ -365,7 +365,7 @@
</Compile>
<Compile Include="Consoles\Atari\A7800Hawk\M6532.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Maria.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Pokey.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\Pokey.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\TIA_Sound\Tia.Audio.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\TIA_Sound\TIA.cs" />
<Compile Include="Consoles\Atari\A7800Hawk\TIA_Sound\Tia.SyncState.cs" />
@ -463,6 +463,9 @@
<Compile Include="Consoles\Nintendo\Gameboy\Gambatte.IEmulator.cs">
<DependentUpon>Gambatte.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\Gameboy\Gambatte.ILinkable.cs">
<DependentUpon>Gambatte.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\Gameboy\Gambatte.IMemoryDomains.cs">
<DependentUpon>Gambatte.cs</DependentUpon>
</Compile>
@ -749,6 +752,7 @@
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper049.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper052.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper074.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper114.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper115.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper121.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper123.cs" />
@ -877,6 +881,9 @@
<Compile Include="Consoles\Nintendo\NES\NES.IDriveLight.cs">
<DependentUpon>NES.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\NES\NES.ICodeDataLogger.cs">
<DependentUpon>NES.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\NES\NES.IInputPollable.cs">
<DependentUpon>NES.cs</DependentUpon>
</Compile>
@ -1068,6 +1075,8 @@
<Compile Include="Consoles\Sega\Saturn\LibSaturnus.cs" />
<Compile Include="Consoles\Sega\Saturn\Saturnus.cs" />
<Compile Include="Consoles\Sega\Saturn\SaturnusControllerDeck.cs" />
<Compile Include="Consoles\Sega\SMS\EEPROM.93c46.cs" />
<Compile Include="Consoles\Sega\SMS\MemoryMap.EEPROM.cs" />
<Compile Include="Consoles\Sega\SMS\SMS.cs" />
<Compile Include="Consoles\Sega\SMS\SMS.ICodeDataLogger.cs">
<DependentUpon>SMS.cs</DependentUpon>
@ -1183,12 +1192,14 @@
<Compile Include="CPUs\Z80-GB\Registers.cs" />
<Compile Include="CPUs\Z80-GB\Tables.cs" />
<Compile Include="CPUs\Z80-GB\Z80.cs" />
<Compile Include="CPUs\Z80\Disassembler.cs" />
<Compile Include="CPUs\Z80\Execute.cs" />
<Compile Include="CPUs\Z80\Interrupts.cs" />
<Compile Include="CPUs\Z80\Registers.cs" />
<Compile Include="CPUs\Z80\Tables.cs" />
<Compile Include="CPUs\Z80\Z80A.cs" />
<Compile Include="CPUs\Z80A\NewDisassembler.cs" />
<Compile Include="CPUs\Z80A\Execute.cs" />
<Compile Include="CPUs\Z80A\Interrupts.cs" />
<Compile Include="CPUs\Z80A\Registers.cs" />
<Compile Include="CPUs\Z80A\Operations.cs" />
<Compile Include="CPUs\Z80A\Tables_Direct.cs" />
<Compile Include="CPUs\Z80A\Tables_Indirect.cs" />
<Compile Include="CPUs\Z80A\Z80A.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

View File

@ -192,7 +192,7 @@ namespace BizHawk.Emulation.Cores.Components.CP1610
if (MemoryCallbacks != null)
{
MemoryCallbacks.CallExecutes(RegisterPC);
MemoryCallbacks.CallExecutes(RegisterPC, "System Bus");
}
switch (opcode)

View File

@ -31,7 +31,7 @@ namespace BizHawk.Emulation.Cores.Components.CP1610
{
if (MemoryCallbacks != null && !peek)
{
MemoryCallbacks.CallReads(addr);
MemoryCallbacks.CallReads(addr, "System Bus");
}
return ReadMemory(addr, peek);
@ -41,7 +41,7 @@ namespace BizHawk.Emulation.Cores.Components.CP1610
{
if (MemoryCallbacks != null && !poke)
{
MemoryCallbacks.CallWrites(addr);
MemoryCallbacks.CallWrites(addr, "System Bus");
}
WriteMemory(addr, value, poke);

View File

@ -60,7 +60,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
LagIFlag = FlagI;
if (Debug) Logger(State());
MemoryCallbacks.CallExecutes(PC);
MemoryCallbacks.CallExecutes(PC, "System Bus");
if (CDL != null && CDL.Active) CDLOpcode();

View File

@ -230,7 +230,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
{
byte page = MPR[address >> 13];
var result = ReadMemory21((page << 13) | (address & 0x1FFF));
MemoryCallbacks.CallReads(address);
MemoryCallbacks.CallReads(address, "System Bus");
return result;
}
@ -238,7 +238,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
{
byte page = MPR[address >> 13];
WriteMemory21((page << 13) | (address & 0x1FFF), value);
MemoryCallbacks.CallWrites(address);
MemoryCallbacks.CallWrites(address, "System Bus");
}
private ushort ReadWord(ushort address)

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +0,0 @@
using System;
namespace BizHawk.Emulation.Cores.Components.Z80
{
public partial class Z80A
{
private bool iff1;
public bool IFF1 { get { return iff1; } set { iff1 = value; } }
private bool iff2;
public bool IFF2 { get { return iff2; } set { iff2 = value; } }
private bool interrupt;
public bool Interrupt { get { return interrupt; } set { interrupt = value; } }
private bool nonMaskableInterrupt;
public bool NonMaskableInterrupt
{
get { return nonMaskableInterrupt; }
set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; }
}
private bool nonMaskableInterruptPending;
public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } }
private int interruptMode;
public int InterruptMode
{
get { return interruptMode; }
set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; }
}
private bool halted;
public bool Halted { get { return halted; } set { halted = value; } }
public Action IRQCallback = delegate() { };
public Action NMICallback = delegate() { };
private void ResetInterrupts()
{
IFF1 = false;
IFF2 = false;
Interrupt = false;
NonMaskableInterrupt = false;
NonMaskableInterruptPending = false;
InterruptMode = 1;
Halted = false;
}
private void Halt()
{
Halted = true;
}
}
}

View File

@ -1,270 +0,0 @@
using System.Runtime.InteropServices;
using System;
namespace BizHawk.Emulation.Cores.Components.Z80
{
public partial class Z80A
{
[StructLayout(LayoutKind.Explicit)]
[Serializable()]
public struct RegisterPair
{
[FieldOffset(0)]
public ushort Word;
[FieldOffset(0)]
public byte Low;
[FieldOffset(1)]
public byte High;
public RegisterPair(ushort value)
{
Word = value;
Low = (byte)(Word);
High = (byte)(Word >> 8);
}
public static implicit operator ushort(RegisterPair rp)
{
return rp.Word;
}
public static implicit operator RegisterPair(ushort value)
{
return new RegisterPair(value);
}
}
private bool RegFlagC
{
get { return (RegAF.Low & 0x01) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x01) | (value ? 0x01 : 0x00)); }
}
private bool RegFlagN
{
get { return (RegAF.Low & 0x02) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x02) | (value ? 0x02 : 0x00)); }
}
private bool RegFlagP
{
get { return (RegAF.Low & 0x04) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x04) | (value ? 0x04 : 0x00)); }
}
private bool RegFlag3
{
get { return (RegAF.Low & 0x08) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x08) | (value ? 0x08 : 0x00)); }
}
private bool RegFlagH
{
get { return (RegAF.Low & 0x10) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x10) | (value ? 0x10 : 0x00)); }
}
private bool RegFlag5
{
get { return (RegAF.Low & 0x20) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x20) | (value ? 0x20 : 0x00)); }
}
private bool RegFlagZ
{
get { return (RegAF.Low & 0x40) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x40) | (value ? 0x40 : 0x00)); }
}
private bool RegFlagS
{
get { return (RegAF.Low & 0x80) != 0; }
set { RegAF.Low = (byte)((RegAF.Low & ~0x80) | (value ? 0x80 : 0x00)); }
}
private RegisterPair RegAF;
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)
private RegisterPair RegIX; // IX (index register x)
private RegisterPair RegIY; // IY (index register y)
private RegisterPair RegSP; // SP (stack pointer)
private RegisterPair RegPC; // PC (program counter)
private void ResetRegisters()
{
// Clear main registers
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
RegI = 0; RegR = 0;
RegIX.Word = 0; RegIY.Word = 0;
RegSP.Word = 0; RegPC.Word = 0;
}
public byte RegisterA
{
get { return RegAF.High; }
set { RegAF.High = value; }
}
public byte RegisterF
{
get { return RegAF.Low; }
set { RegAF.Low = value; }
}
public ushort RegisterAF
{
get { return RegAF.Word; }
set { RegAF.Word = value; }
}
public byte RegisterB
{
get { return RegBC.High; }
set { RegBC.High = value; }
}
public byte RegisterC
{
get { return RegBC.Low; }
set { RegBC.Low = value; }
}
public ushort RegisterBC
{
get { return RegBC.Word; }
set { RegBC.Word = value; }
}
public byte RegisterD
{
get { return RegDE.High; }
set { RegDE.High = value; }
}
public byte RegisterE
{
get { return RegDE.Low; }
set { RegDE.Low = value; }
}
public ushort RegisterDE
{
get { return RegDE.Word; }
set { RegDE.Word = value; }
}
public byte RegisterH
{
get { return RegHL.High; }
set { RegHL.High = value; }
}
public byte RegisterL
{
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; }
set { RegAltHL.Word = value; }
}
}
}

View File

@ -1,331 +0,0 @@
namespace BizHawk.Emulation.Cores.Components.Z80
{
public partial class Z80A
{
private void InitialiseTables()
{
InitTableInc();
InitTableDec();
InitTableParity();
InitTableALU();
InitTableRotShift();
InitTableHalfBorrow();
InitTableHalfCarry();
InitTableNeg();
InitTableDaa();
}
private byte[] TableInc;
private void InitTableInc()
{
TableInc = new byte[256];
for (int i = 0; i < 256; ++i)
TableInc[i] = FlagByte(false, false, i == 0x80, UndocumentedX(i), (i & 0xF) == 0x0, UndocumentedY(i), i == 0, i > 127);
}
private byte[] TableDec;
private void InitTableDec()
{
TableDec = new byte[256];
for (int i = 0; i < 256; ++i)
TableDec[i] = FlagByte(false, true, i == 0x7F, UndocumentedX(i), (i & 0xF) == 0xF, UndocumentedY(i), i == 0, i > 127);
}
private bool[] TableParity;
private void InitTableParity()
{
TableParity = new bool[256];
for (int i = 0; i < 256; ++i)
{
int Bits = 0;
for (int j = 0; j < 8; ++j)
{
Bits += (i >> j) & 1;
}
TableParity[i] = (Bits & 1) == 0;
}
}
private ushort[, , ,] TableALU;
private void InitTableALU()
{
TableALU = new ushort[8, 256, 256, 2]; // Class, OP1, OP2, Carry
for (int i = 0; i < 8; ++i)
{
for (int op1 = 0; op1 < 256; ++op1)
{
for (int op2 = 0; op2 < 256; ++op2)
{
for (int c = 0; c < 2; ++c)
{
int ac = (i == 1 || i == 3) ? c : 0;
bool S = false;
bool Z = false;
bool C = false;
bool H = false;
bool N = false;
bool P = false;
byte result_b = 0;
int result_si = 0;
int result_ui = 0;
// Fetch result
switch (i)
{
case 0:
case 1:
result_si = (sbyte)op1 + (sbyte)op2 + ac;
result_ui = op1 + op2 + ac;
break;
case 2:
case 3:
case 7:
result_si = (sbyte)op1 - (sbyte)op2 - ac;
result_ui = op1 - op2 - ac;
break;
case 4:
result_si = op1 & op2;
break;
case 5:
result_si = op1 ^ op2;
break;
case 6:
result_si = op1 | op2;
break;
}
result_b = (byte)result_si;
// Parity/Carry
switch (i)
{
case 0:
case 1:
case 2:
case 3:
case 7:
P = result_si < -128 || result_si > 127;
C = result_ui < 0 || result_ui > 255;
break;
case 4:
case 5:
case 6:
P = TableParity[result_b];
C = false;
break;
}
// Subtraction
N = i == 2 || i == 3 || i == 7;
// Half carry
switch (i)
{
case 0:
case 1:
H = ((op1 & 0xF) + (op2 & 0xF) + (ac & 0xF)) > 0xF;
break;
case 2:
case 3:
case 7:
H = ((op1 & 0xF) - (op2 & 0xF) - (ac & 0xF)) < 0x0;
break;
case 4:
H = true;
break;
case 5:
case 6:
H = false;
break;
}
// Undocumented
byte UndocumentedFlags = (byte)(result_b & 0x28);
if (i == 7) UndocumentedFlags = (byte)(op2 & 0x28);
S = result_b > 127;
Z = result_b == 0;
if (i == 7) result_b = (byte)op1;
TableALU[i, op1, op2, c] = (ushort)(
result_b * 256 +
((C ? 0x01 : 0) + (N ? 0x02 : 0) + (P ? 0x04 : 0) + (H ? 0x10 : 0) + (Z ? 0x40 : 0) + (S ? 0x80 : 0)) +
(UndocumentedFlags));
}
}
}
}
}
private bool[,] TableHalfBorrow;
private void InitTableHalfBorrow()
{
TableHalfBorrow = new bool[256, 256];
for (int i = 0; i < 256; i++)
{
for (int j = 0; j < 256; j++)
{
TableHalfBorrow[i, j] = ((i & 0xF) - (j & 0xF)) < 0;
}
}
}
private bool[,] TableHalfCarry;
private void InitTableHalfCarry()
{
TableHalfCarry = new bool[256, 256];
for (int i = 0; i < 256; i++)
{
for (int j = 0; j < 256; j++)
{
TableHalfCarry[i, j] = ((i & 0xF) + (j & 0xF)) > 0xF;
}
}
}
private ushort[, ,] TableRotShift;
private void InitTableRotShift()
{
TableRotShift = new ushort[2, 8, 65536]; // All, operation, AF
for (int all = 0; all < 2; all++)
{
for (int y = 0; y < 8; ++y)
{
for (int af = 0; af < 65536; af++)
{
byte Old = (byte)(af >> 8);
bool OldCarry = (af & 0x01) != 0;
ushort newAf = (ushort)(af & ~(0x13)); // Clear HALF-CARRY, SUBTRACT and CARRY flags
byte New = Old;
if ((y & 1) == 0)
{
if ((Old & 0x80) != 0) ++newAf;
New <<= 1;
if ((y & 0x04) == 0)
{
if (((y & 0x02) == 0) ? ((newAf & 0x01) != 0) : OldCarry) New |= 0x01;
}
else
{
if ((y & 0x02) != 0) New |= 0x01;
}
}
else
{
if ((Old & 0x01) != 0) ++newAf;
New >>= 1;
if ((y & 0x04) == 0)
{
if (((y & 0x02) == 0) ? ((newAf & 0x01) != 0) : OldCarry) New |= 0x80;
}
else
{
if ((y & 0x02) == 0) New |= (byte)(Old & 0x80);
}
}
newAf &= 0xFF;
newAf |= (ushort)(New * 256);
if (all == 1)
{
newAf &= unchecked((ushort)~0xC4); // Clear S, Z, P
if (New > 127) newAf |= 0x80;
if (New == 0) newAf |= 0x40;
if (TableParity[New]) newAf |= 0x04;
}
TableRotShift[all, y, af] = (ushort)((newAf & ~0x28) | ((newAf >> 8) & 0x28));
}
}
}
}
private ushort[] TableNeg;
private void InitTableNeg()
{
TableNeg = new ushort[65536];
for (int af = 0; af < 65536; af++)
{
ushort raf = 0;
byte b = (byte)(af >> 8);
byte a = (byte)-b;
raf |= (ushort)(a * 256);
raf |= FlagByte(b != 0x00, true, b == 0x80, UndocumentedX(a), TableHalfCarry[a, b], UndocumentedY(a), a == 0, a > 127);
TableNeg[af] = raf;
}
}
private ushort[] TableDaa;
private void InitTableDaa()
{
TableDaa = new ushort[65536];
for (int af = 0; af < 65536; ++af)
{
byte a = (byte)(af >> 8);
byte tmp = a;
if (IsN(af))
{
if (IsH(af) || ((a & 0x0F) > 0x09)) tmp -= 0x06;
if (IsC(af) || a > 0x99) tmp -= 0x60;
}
else
{
if (IsH(af) || ((a & 0x0F) > 0x09)) tmp += 0x06;
if (IsC(af) || a > 0x99) tmp += 0x60;
}
TableDaa[af] = (ushort)((tmp * 256) + FlagByte(IsC(af) || a > 0x99, IsN(af), TableParity[tmp], UndocumentedX(tmp), ((a ^ tmp) & 0x10) != 0, UndocumentedY(tmp), tmp == 0, tmp > 127));
}
}
private byte FlagByte(bool C, bool N, bool P, bool X, bool H, bool Y, bool Z, bool S)
{
return (byte)(
(C ? 0x01 : 0) +
(N ? 0x02 : 0) +
(P ? 0x04 : 0) +
(X ? 0x08 : 0) +
(H ? 0x10 : 0) +
(Y ? 0x20 : 0) +
(Z ? 0x40 : 0) +
(S ? 0x80 : 0)
);
}
private bool UndocumentedX(int value)
{
return (value & 0x08) != 0;
}
private bool UndocumentedY(int value)
{
return (value & 0x20) != 0;
}
private bool IsC(int value) { return (value & 0x01) != 0; }
private bool IsN(int value) { return (value & 0x02) != 0; }
private bool IsP(int value) { return (value & 0x04) != 0; }
private bool IsX(int value) { return (value & 0x08) != 0; }
private bool IsH(int value) { return (value & 0x10) != 0; }
private bool IsY(int value) { return (value & 0x20) != 0; }
private bool IsZ(int value) { return (value & 0x40) != 0; }
private bool IsS(int value) { return (value & 0x80) != 0; }
}
}

View File

@ -1,142 +0,0 @@
using System;
using System.Globalization;
using System.IO;
using BizHawk.Common;
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
{
public Z80A()
{
InitialiseTables();
Reset();
}
public void Reset()
{
ResetRegisters();
ResetInterrupts();
PendingCycles = 0;
ExpectedExecutedCycles = 0;
TotalExecutedCycles = 0;
}
public void SoftReset()
{
ResetRegisters();
ResetInterrupts();
}
// Memory Access
public Func<ushort, bool, byte> FetchMemory;
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
public byte ReadMemoryWrapper(ushort addr)
{
if (MemoryCallbacks != null)
{
MemoryCallbacks.CallReads(addr);
}
return ReadMemory(addr);
}
public byte FetchFirstMemoryWrapper(ushort addr)
{
if (MemoryCallbacks != null)
{
MemoryCallbacks.CallReads(addr);
}
if (FetchMemory != null)
{
return FetchMemory(addr, true);
}
return ReadMemory(addr);
}
public byte FetchMemoryWrapper(ushort addr)
{
if (MemoryCallbacks != null)
{
MemoryCallbacks.CallReads(addr);
}
if (FetchMemory != null)
{
return FetchMemory(addr, false);
}
return ReadMemory(addr);
}
public void WriteMemoryWrapper(ushort addr, byte value)
{
if (MemoryCallbacks != null)
{
MemoryCallbacks.CallWrites(addr);
}
WriteMemory(addr, value);
}
public IMemoryCallbackSystem MemoryCallbacks { get; set; }
// Utility function, not used by core
public ushort ReadWord(ushort addr)
{
ushort value = ReadMemory(addr++);
value |= (ushort)(ReadMemory(addr) << 8);
return value;
}
// Hardware I/O Port Access
public Func<ushort, byte> ReadHardware;
public Action<ushort, byte> WriteHardware;
// State Save/Load
public void SyncState(Serializer ser)
{
ser.BeginSection("Z80");
ser.Sync("AF", ref RegAF.Word);
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);
ser.Sync("ShadowHL", ref RegAltHL.Word);
ser.Sync("I", ref RegI);
ser.Sync("R", ref RegR);
ser.Sync("IX", ref RegIX.Word);
ser.Sync("IY", ref RegIY.Word);
ser.Sync("SP", ref RegSP.Word);
ser.Sync("PC", ref RegPC.Word);
ser.Sync("IRQ", ref interrupt);
ser.Sync("NMI", ref nonMaskableInterrupt);
ser.Sync("NMIPending", ref nonMaskableInterruptPending);
ser.Sync("IM", ref interruptMode);
ser.Sync("IFF1", ref iff1);
ser.Sync("IFF2", ref iff2);
ser.Sync("Halted", ref halted);
ser.Sync("ExecutedCycles", ref totalExecutedCycles);
ser.Sync("PendingCycles", ref pendingCycles);
ser.Sync("EI_pending", ref EI_pending);
ser.EndSection();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
using System;
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
{
private bool iff1;
public bool IFF1 { get { return iff1; } set { iff1 = value; } }
private bool iff2;
public bool IFF2 { get { return iff2; } set { iff2 = value; } }
private bool nonMaskableInterrupt;
public bool NonMaskableInterrupt
{
get { return nonMaskableInterrupt; }
set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; }
}
private bool nonMaskableInterruptPending;
public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } }
private int interruptMode;
public int InterruptMode
{
get { return interruptMode; }
set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; }
}
public Action IRQCallback = delegate () { };
public Action NMICallback = delegate () { };
private void NMI_()
{
cur_instr = new ushort[]
{IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCh,
IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCl,
IDLE,
ASGN, PCl, 0x66,
ASGN, PCh, 0,
IDLE,
OP };
}
// Mode 0 interrupts only take effect if a CALL or RST is on the data bus
// Otherwise operation just continues as normal
// For now assume a NOP is on the data bus, in which case no stack operations occur
//NOTE: TODO: When a CALL is present on the data bus, adjust WZ accordingly
private void INTERRUPT_0(ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
OP };
}
// Just jump to $0038
private void INTERRUPT_1()
{
cur_instr = new ushort[]
{DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCh,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCl,
IDLE,
ASGN, PCl, 0x38,
IDLE,
ASGN, PCh, 0,
IDLE,
OP };
}
// Interrupt mode 2 uses the I vector combined with a byte on the data bus
// Again for now we assume only a 0 on the data bus and jump to (0xI00)
private void INTERRUPT_2(ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCh,
IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCl,
IDLE,
ASGN, PCl, 0,
TR, PCh, I,
IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
TR16, PCl, PCh, Z, W,
OP };
}
private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60};
private void ResetInterrupts()
{
IFF1 = false;
IFF2 = false;
NonMaskableInterrupt = false;
NonMaskableInterruptPending = false;
FlagI = false;
InterruptMode = 1;
}
}
}

View File

@ -1,114 +1,27 @@
//http://www.zophar.net/fileuploads/2/10819kouzv/z80undoc.html
//TODO: ex. (IX+00h) could be turned into (IX)
//usage:
//VgMuseum.Z80.Disassembler disasm = new Disassembler();
//ushort pc = RegPC.Word;
//string str = disasm.Disassemble(() => ReadMemory(pc++));
//Console.WriteLine(str);
//please note that however much youre tempted to, timings can't be put in a table here because they depend on how the instruction executes at runtime
using System;
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Components.Z80
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public class Disassembler : IDisassemblable
public sealed partial class Z80A : IDisassemblable
{
readonly static sbyte[,] opcodeSizes = new sbyte[7, 256];
public static void GenerateOpcodeSizes()
{
Disassembler disasm = new Disassembler();
for (int i = 0; i < 256; i++)
{
int pc = 0;
byte[] opcode = { (byte)i, 0, 0, 0 };
disasm.Disassemble(() => opcode[pc++]);
opcodeSizes[0, i] = (sbyte)pc;
}
opcodeSizes[0, 0xCB] = -1;
opcodeSizes[0, 0xED] = -2;
opcodeSizes[0, 0xDD] = -3;
opcodeSizes[0, 0xFD] = -4;
for (int i = 0; i < 256; i++)
{
int pc = 0;
byte[] opcode = { 0xCB, (byte)i, 0, 0, 0 };
disasm.Disassemble(() => opcode[pc++]);
opcodeSizes[1, i] = (sbyte)pc;
}
for (int i = 0; i < 256; i++)
{
int pc = 0;
byte[] opcode = { 0xED, (byte)i, 0, 0, 0 };
disasm.Disassemble(() => opcode[pc++]);
opcodeSizes[2, i] = (sbyte)pc;
}
for (int i = 0; i < 256; i++)
{
int pc = 0;
byte[] opcode = { 0xDD, (byte)i, 0, 0, 0 };
disasm.Disassemble(() => opcode[pc++]);
opcodeSizes[3, i] = (sbyte)pc;
}
opcodeSizes[3, 0xCB] = -5;
opcodeSizes[3, 0xED] = -2;
for (int i = 0; i < 256; i++)
{
int pc = 0;
byte[] opcode = { 0xFD, (byte)i, 0, 0, 0 };
disasm.Disassemble(() => opcode[pc++]);
opcodeSizes[4, i] = (sbyte)pc;
}
opcodeSizes[3, 0xCB] = -6;
opcodeSizes[3, 0xED] = -2;
for (int i = 0; i < 256; i++)
{
int pc = 0;
byte[] opcode = { 0xDD, 0xCB, (byte)i, 0, 0, 0 };
disasm.Disassemble(() => opcode[pc++]);
opcodeSizes[5, i] = (sbyte)pc;
}
for (int i = 0; i < 256; i++)
{
int pc = 0;
byte[] opcode = { 0xFD, 0xCB, (byte)i, 0, 0, 0 };
disasm.Disassemble(() => opcode[pc++]);
opcodeSizes[6, i] = (sbyte)pc;
}
}
static string Result(string format, Func<byte> read)
static string Result(string format, Func<ushort, byte> read, ref ushort addr)
{
//d immediately succeeds the opcode
//n immediate succeeds the opcode and the displacement (if present)
//nn immediately succeeds the opcode and the displacement (if present)
if (format.IndexOf("nn") != -1)
{
byte B = read();
byte C = read();
byte B = read(addr++);
byte C = read(addr++);
format = format.Replace("nn", string.Format("{0:X4}h", B + C * 256));
}
if (format.IndexOf("n") != -1)
{
byte B = read();
byte B = read(addr++);
format = format.Replace("n", string.Format("{0:X2}h", B));
}
@ -116,7 +29,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80
if (format.IndexOf("d") != -1)
{
byte B = read();
byte B = read(addr++);
bool neg = ((B & 0x80) != 0);
char sign = neg ? '-' : '+';
int val = neg ? 256 - B : B;
@ -480,46 +393,49 @@ namespace BizHawk.Emulation.Cores.Components.Z80
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x100
};
string DisassembleInternal(Func<byte> read)
public string Disassemble(ushort addr, Func<ushort, byte> read, out ushort size)
{
byte A = read();
ushort start_addr = addr;
ushort extra_inc = 0;
byte A = read(addr++);
string format;
switch (A)
{
case 0xCB:
A = read();
A = read(addr++);
format = mnemonicsCB[A];
break;
case 0xDD:
A = read();
A = read(addr++);
switch (A)
{
case 0xCB: format = mnemonicsDDCB[A]; break;
case 0xCB: format = mnemonicsDDCB[read((ushort)(addr + 1))]; extra_inc = 1; break;
case 0xED: format = mnemonicsED[A]; break;
default: format = mnemonicsDD[A]; break;
}
break;
case 0xED:
A = read();
A = read(addr++);
format = mnemonicsED[A];
break;
case 0xFD:
A = read();
A = read(addr++);
switch (A)
{
case 0xCB: format = mnemonicsFDCB[A]; break;
case 0xCB: format = mnemonicsFDCB[read((ushort)(addr + 1))]; extra_inc = 1; break;
case 0xED: format = mnemonicsED[A]; break;
default: format = mnemonicsFD[A]; break;
}
break;
default: format = mnemonics[A]; break;
}
return format;
}
string temp = Result(format, read, ref addr);
public string Disassemble(Func<byte> read)
{
return Result(DisassembleInternal(read), read);
addr += extra_inc;
size = (ushort)(addr - start_addr);
return temp;
}
#region IDisassemblable
@ -543,7 +459,8 @@ namespace BizHawk.Emulation.Cores.Components.Z80
public string Disassemble(MemoryDomain m, uint addr, out int length)
{
int loc = (int)addr;
string ret = Disassemble(() => m.PeekByte(loc++));
ushort unused = 0;
string ret = Disassemble((ushort) addr, a => m.PeekByte(a), out unused);
length = loc - (int)addr;
return ret;
}

View File

@ -0,0 +1,742 @@
using BizHawk.Common.NumberExtensions;
using System;
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
{
public void Read_Func(ushort dest, ushort src_l, ushort src_h)
{
Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
}
public void I_Read_Func(ushort dest, ushort src_l, ushort src_h, ushort inc)
{
Regs[dest] = ReadMemory((ushort)((Regs[src_l] | (Regs[src_h] << 8)) + inc));
}
public void Write_Func(ushort dest_l, ushort dest_h, ushort src)
{
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
}
public void I_Write_Func(ushort dest_l, ushort dest_h, ushort inc, ushort src)
{
WriteMemory((ushort)((Regs[dest_l] | (Regs[dest_h] << 8)) + inc), (byte)Regs[src]);
}
public void OUT_Func(ushort dest, ushort src)
{
WriteHardware(Regs[dest], (byte)(Regs[src]));
}
public void IN_Func(ushort dest, ushort src)
{
Regs[dest] = ReadHardware(Regs[src]);
}
public void TR_Func(ushort dest, ushort src)
{
Regs[dest] = Regs[src];
}
public void TR16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
Regs[dest_l] = Regs[src_l];
Regs[dest_h] = Regs[src_h];
}
public void ADD16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8);
int Reg16_s = Regs[src_l] | (Regs[src_h] << 8);
int temp = Reg16_d + Reg16_s;
FlagC = temp.Bit(16);
FlagH = ((Reg16_d & 0xFFF) + (Reg16_s & 0xFFF)) > 0xFFF;
FlagN = false;
Flag3 = (temp & 0x0800) != 0;
Flag5 = (temp & 0x2000) != 0;
Regs[dest_l] = (ushort)(temp & 0xFF);
Regs[dest_h] = (ushort)((temp & 0xFF00) >> 8);
}
public void ADD8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
Reg16_d += Regs[src];
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d += (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
FlagN = false;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void SUB8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
Reg16_d -= Regs[src];
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d -= (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
FlagN = true;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void BIT_Func(ushort bit, ushort src)
{
FlagZ = !Regs[src].Bit(bit);
FlagP = FlagZ; // special case
FlagH = true;
FlagN = false;
FlagS = ((bit == 7) && Regs[src].Bit(bit));
Flag5 = Regs[src].Bit(5);
Flag3 = Regs[src].Bit(3);
}
// When doing I* + n bit tests, flags 3 and 5 come from I* + n
// This cooresponds to the high byte of WZ
// This is the same for the (HL) bit tests, except that WZ were not assigned to before the test occurs
public void I_BIT_Func(ushort bit, ushort src)
{
FlagZ = !Regs[src].Bit(bit);
FlagP = FlagZ; // special case
FlagH = true;
FlagN = false;
FlagS = ((bit == 7) && Regs[src].Bit(bit));
Flag5 = Regs[W].Bit(5);
Flag3 = Regs[W].Bit(3);
}
public void SET_Func(ushort bit, ushort src)
{
Regs[src] |= (ushort)(1 << bit);
}
public void RES_Func(ushort bit, ushort src)
{
Regs[src] &= (ushort)(0xFF - (1 << bit));
}
public void ASGN_Func(ushort src, ushort val)
{
Regs[src] = val;
}
public void SLL_Func(ushort src)
{
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | 0x1);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void SLA_Func(ushort src)
{
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)((Regs[src] << 1) & 0xFF);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void SRA_Func(ushort src)
{
FlagC = Regs[src].Bit(0);
ushort temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation
Regs[src] = (ushort)((Regs[src] >> 1) | temp);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void SRL_Func(ushort src)
{
FlagC = Regs[src].Bit(0) ? true : false;
Regs[src] = (ushort)(Regs[src] >> 1);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void CPL_Func(ushort src)
{
Regs[src] = (ushort)((~Regs[src]) & 0xFF);
FlagH = true;
FlagN = true;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void CCF_Func(ushort src)
{
FlagH = FlagC;
FlagC = !FlagC;
FlagN = false;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void SCF_Func(ushort src)
{
FlagC = true;
FlagH = false;
FlagN = false;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void AND8_Func(ushort dest, ushort src)
{
Regs[dest] = (ushort)(Regs[dest] & Regs[src]);
FlagZ = Regs[dest] == 0;
FlagC = false;
FlagH = true;
FlagN = false;
Flag3 = (Regs[dest] & 0x08) != 0;
Flag5 = (Regs[dest] & 0x20) != 0;
FlagS = Regs[dest] > 127;
FlagP = TableParity[Regs[dest]];
}
public void OR8_Func(ushort dest, ushort src)
{
Regs[dest] = (ushort)(Regs[dest] | Regs[src]);
FlagZ = Regs[dest] == 0;
FlagC = false;
FlagH = false;
FlagN = false;
Flag3 = (Regs[dest] & 0x08) != 0;
Flag5 = (Regs[dest] & 0x20) != 0;
FlagS = Regs[dest] > 127;
FlagP = TableParity[Regs[dest]];
}
public void XOR8_Func(ushort dest, ushort src)
{
Regs[dest] = (ushort)((Regs[dest] ^ Regs[src]));
FlagZ = Regs[dest] == 0;
FlagC = false;
FlagH = false;
FlagN = false;
Flag3 = (Regs[dest] & 0x08) != 0;
Flag5 = (Regs[dest] & 0x20) != 0;
FlagS = Regs[dest] > 127;
FlagP = TableParity[Regs[dest]];
}
public void CP8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
Reg16_d -= Regs[src];
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d -= (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
FlagN = true;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
}
public void RRC_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
FlagC = Regs[src].Bit(0);
Regs[src] = (ushort)((FlagC ? 0x80 : 0) | (Regs[src] >> 1));
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void RR_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
ushort c = (ushort)(FlagC ? 0x80 : 0);
FlagC = Regs[src].Bit(0);
Regs[src] = (ushort)(c | (Regs[src] >> 1));
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void RLC_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
ushort c = (ushort)(Regs[src].Bit(7) ? 1 : 0);
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void RL_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
ushort c = (ushort)(FlagC ? 1 : 0);
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void INC8_Func(ushort src)
{
int Reg16_d = Regs[src];
Reg16_d += 1;
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[src] & 0xF;
Reg16_d += 1;
FlagH = Reg16_d.Bit(4);
FlagN = false;
Regs[src] = ans;
FlagS = Regs[src].Bit(7);
FlagP = Regs[src] == 0x80;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void DEC8_Func(ushort src)
{
int Reg16_d = Regs[src];
Reg16_d -= 1;
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[src] & 0xF;
Reg16_d -= 1;
FlagH = Reg16_d.Bit(4);
FlagN = true;
Regs[src] = ans;
FlagS = Regs[src].Bit(7);
FlagP = Regs[src] == 0x7F;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void INC16_Func(ushort src_l, ushort src_h)
{
int Reg16_d = Regs[src_l] | (Regs[src_h] << 8);
Reg16_d += 1;
Regs[src_l] = (ushort)(Reg16_d & 0xFF);
Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8);
}
public void DEC16_Func(ushort src_l, ushort src_h)
{
int Reg16_d = Regs[src_l] | (Regs[src_h] << 8);
Reg16_d -= 1;
Regs[src_l] = (ushort)(Reg16_d & 0xFF);
Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8);
}
public void ADC8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
int c = FlagC ? 1 : 0;
Reg16_d += (Regs[src] + c);
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d += ((Regs[src] & 0xF) + c);
FlagH = Reg16_d.Bit(4);
FlagN = false;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void SBC8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
int c = FlagC ? 1 : 0;
Reg16_d -= (Regs[src] + c);
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d -= ((Regs[src] & 0xF) + c);
FlagH = Reg16_d.Bit(4);
FlagN = true;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void DA_Func(ushort src)
{
byte a = (byte)Regs[src];
byte temp = a;
if (FlagN)
{
if (FlagH || ((a & 0x0F) > 0x09)) { temp -= 0x06; }
if (FlagC || a > 0x99) { temp -= 0x60; }
}
else
{
if (FlagH || ((a & 0x0F) > 0x09)) { temp += 0x06; }
if (FlagC || a > 0x99) { temp += 0x60; }
}
temp &= 0xFF;
FlagC = FlagC || a > 0x99;
FlagZ = temp == 0;
FlagH = ((a ^ temp) & 0x10) != 0;
FlagP = TableParity[temp];
FlagS = temp > 127;
Flag3 = (temp & 0x08) != 0;
Flag5 = (temp & 0x20) != 0;
Regs[src] = temp;
}
// used for signed operations
public void ADDS_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l];
int Reg16_s = Regs[src_l];
Reg16_d += Reg16_s;
ushort temp = 0;
// since this is signed addition, calculate the high byte carry appropriately
// note that flags are unaffected by this operation
if (Reg16_s.Bit(7))
{
if (((Reg16_d & 0xFF) >= Regs[dest_l]))
{
temp = 0xFF;
}
else
{
temp = 0;
}
}
else
{
temp = (ushort)(Reg16_d.Bit(8) ? 1 : 0);
}
ushort ans_l = (ushort)(Reg16_d & 0xFF);
Regs[dest_l] = ans_l;
Regs[dest_h] += temp;
Regs[dest_h] &= 0xFF;
}
public void EXCH_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
ushort temp = Regs[dest_l];
Regs[dest_l] = Regs[src_l];
Regs[src_l] = temp;
temp = Regs[dest_h];
Regs[dest_h] = Regs[src_h];
Regs[src_h] = temp;
}
public void SBC_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8);
int Reg16_s = Regs[src_l] | (Regs[src_h] << 8);
int c = FlagC ? 1 : 0;
int ans = Reg16_d - Reg16_s - c;
FlagN = true;
FlagC = ans.Bit(16);
FlagP = (Reg16_d.Bit(15) != Reg16_s.Bit(15)) && (Reg16_d.Bit(15) != ans.Bit(15));
FlagS = (ushort)(ans & 0xFFFF) > 32767;
FlagZ = (ans & 0xFFFF) == 0;
Flag3 = (ans & 0x0800) != 0;
Flag5 = (ans & 0x2000) != 0;
// redo for half carry flag
Reg16_d &= 0xFFF;
Reg16_d -= ((Reg16_s & 0xFFF) + c);
FlagH = Reg16_d.Bit(12);
Regs[dest_l] = (ushort)(ans & 0xFF);
Regs[dest_h] = (ushort)((ans >> 8) & 0xFF);
}
public void ADC_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8);
int Reg16_s = Regs[src_l] | (Regs[src_h] << 8);
int ans = Reg16_d + Reg16_s + (FlagC ? 1 : 0);
FlagH = ((Reg16_d & 0xFFF) + (Reg16_s & 0xFFF) + (FlagC ? 1 : 0)) > 0xFFF;
FlagN = false;
FlagC = ans.Bit(16);
FlagP = (Reg16_d.Bit(15) == Reg16_s.Bit(15)) && (Reg16_d.Bit(15) != ans.Bit(15));
FlagS = (ans & 0xFFFF) > 32767;
FlagZ = (ans & 0xFFFF) == 0;
Flag3 = (ans & 0x0800) != 0;
Flag5 = (ans & 0x2000) != 0;
Regs[dest_l] = (ushort)(ans & 0xFF);
Regs[dest_h] = (ushort)((ans >> 8) & 0xFF);
}
public void NEG_8_Func(ushort src)
{
int Reg16_d = 0;
Reg16_d -= Regs[src];
FlagC = Regs[src] != 0x0;
FlagZ = (Reg16_d & 0xFF) == 0;
FlagP = Regs[src] == 0x80;
FlagS = (Reg16_d & 0xFF) > 127;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = 0;
Reg16_d -= (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
Regs[src] = ans;
FlagN = true;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
}
public void RRD_Func(ushort dest, ushort src)
{
ushort temp1 = Regs[src];
ushort temp2 = Regs[dest];
Regs[dest] = (ushort)(((temp1 & 0x0F) << 4) + ((temp2 & 0xF0) >> 4));
Regs[src] = (ushort)((temp1 & 0xF0) + (temp2 & 0x0F));
temp1 = Regs[src];
FlagS = temp1 > 127;
FlagZ = temp1 == 0;
FlagH = false;
FlagP = TableParity[temp1];
FlagN = false;
Flag3 = (temp1 & 0x08) != 0;
Flag5 = (temp1 & 0x20) != 0;
}
public void RLD_Func(ushort dest, ushort src)
{
ushort temp1 = Regs[src];
ushort temp2 = Regs[dest];
Regs[dest] = (ushort)((temp1 & 0x0F) + ((temp2 & 0x0F) << 4));
Regs[src] = (ushort)((temp1 & 0xF0) + ((temp2 & 0xF0) >> 4));
temp1 = Regs[src];
FlagS = temp1 > 127;
FlagZ = temp1 == 0;
FlagH = false;
FlagP = TableParity[temp1];
FlagN = false;
Flag3 = (temp1 & 0x08) != 0;
Flag5 = (temp1 & 0x20) != 0;
}
// sets flags for LD/R
public void SET_FL_LD_Func()
{
FlagP = (Regs[C] | (Regs[B] << 8)) != 0;
FlagH = false;
FlagN = false;
Flag5 = ((Regs[ALU] + Regs[A]) & 0x02) != 0;
Flag3 = ((Regs[ALU] + Regs[A]) & 0x08) != 0;
}
// set flags for CP/R
public void SET_FL_CP_Func()
{
int Reg8_d = Regs[A];
int Reg8_s = Regs[ALU];
// get half carry flag
byte temp = (byte)((Reg8_d & 0xF) - (Reg8_s & 0xF));
FlagH = temp.Bit(4);
temp = (byte)(Reg8_d - Reg8_s);
FlagN = true;
FlagZ = temp == 0;
FlagS = temp > 127;
FlagP = (Regs[C] | (Regs[B] << 8)) != 0;
temp = (byte)(Reg8_d - Reg8_s - (FlagH ? 1 : 0));
Flag5 = (temp & 0x02) != 0;
Flag3 = (temp & 0x08) != 0;
}
// set flags for LD A, I/R
public void SET_FL_IR_Func(ushort dest)
{
if (dest == A)
{
FlagN = false;
FlagH = false;
FlagZ = Regs[A] == 0;
FlagS = Regs[A] > 127;
FlagP = iff2;
Flag5 = (Regs[A] & 0x02) != 0;
Flag3 = (Regs[A] & 0x08) != 0;
}
}
}
}

View File

@ -0,0 +1,8 @@
TODO:
Mode 0 and 2 interrupts
Check T-cycle level memory access timing
Check R register
new tests for WZ Registers
Memory refresh - IR is pushed onto the address bus at instruction start, does anything need this?
Data Bus - For mode zero and 2 interrupts, need a system that uses it to test

View File

@ -0,0 +1,132 @@
using System.Runtime.InteropServices;
using System;
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
{
// registers
// note these are not constants. When shadows are used, they will be changed accordingly
public ushort PCl = 0;
public ushort PCh = 1;
public ushort SPl = 2;
public ushort SPh = 3;
public ushort A = 4;
public ushort F = 5;
public ushort B = 6;
public ushort C = 7;
public ushort D = 8;
public ushort E = 9;
public ushort H = 10;
public ushort L = 11;
public ushort W = 12;
public ushort Z = 13;
public ushort Aim = 14; // use this indicator for RLCA etc., since the Z flag is reset on those
public ushort Ixl = 15;
public ushort Ixh = 16;
public ushort Iyl = 17;
public ushort Iyh = 18;
public ushort Int = 19;
public ushort R = 20;
public ushort I = 21;
public ushort ZERO = 22; // it is convenient to have a register that is always zero, to reuse instructions
public ushort ALU = 23; // This will be temporary arthimatic storage
// shadow registers
public ushort A_s = 24;
public ushort F_s = 25;
public ushort B_s = 26;
public ushort C_s = 27;
public ushort D_s = 28;
public ushort E_s = 29;
public ushort H_s = 30;
public ushort L_s = 31;
public ushort[] Regs = new ushort[36];
public bool FlagI;
public bool FlagC
{
get { return (Regs[5] & 0x01) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x01) | (value ? 0x01 : 0x00)); }
}
public bool FlagN
{
get { return (Regs[5] & 0x02) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x02) | (value ? 0x02 : 0x00)); }
}
public bool FlagP
{
get { return (Regs[5] & 0x04) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x04) | (value ? 0x04 : 0x00)); }
}
public bool Flag3
{
get { return (Regs[5] & 0x08) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x08) | (value ? 0x08 : 0x00)); }
}
public bool FlagH
{
get { return (Regs[5] & 0x10) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x10) | (value ? 0x10 : 0x00)); }
}
public bool Flag5
{
get { return (Regs[5] & 0x20) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x20) | (value ? 0x20 : 0x00)); }
}
public bool FlagZ
{
get { return (Regs[5] & 0x40) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x40) | (value ? 0x40 : 0x00)); }
}
public bool FlagS
{
get { return (Regs[5] & 0x80) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x80) | (value ? 0x80 : 0x00)); }
}
public ushort RegPC
{
get { return (ushort)(Regs[0] | (Regs[1] << 8)); }
set
{
Regs[0] = (ushort)(value & 0xFF);
Regs[1] = (ushort)((value >> 8) & 0xFF);
}
}
private void ResetRegisters()
{
for (int i=0; i < 36; i++)
{
Regs[i] = 0;
}
}
private bool[] TableParity;
private void InitTableParity()
{
TableParity = new bool[256];
for (int i = 0; i < 256; ++i)
{
int Bits = 0;
for (int j = 0; j < 8; ++j)
{
Bits += (i >> j) & 1;
}
TableParity[i] = (Bits & 1) == 0;
}
}
}
}

View File

@ -0,0 +1,572 @@
using System;
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
{
// this contains the vectors of instrcution operations
// NOTE: This list is NOT confirmed accurate for each individual cycle
private void NOP_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
OP };
}
// NOTE: In a real Z80, this operation just flips a switch to choose between 2 registers
// but it's simpler to emulate just by exchanging the register with it's shadow
private void EXCH_()
{
cur_instr = new ushort[]
{EXCH,
IDLE,
IDLE,
OP };
}
private void EXX_()
{
cur_instr = new ushort[]
{EXX,
IDLE,
IDLE,
OP };
}
// this exchanges 2 16 bit registers
private void EXCH_16_(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{EXCH_16, dest_l, dest_h, src_l, src_h,
IDLE,
IDLE,
OP };
}
private void INC_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
INC16, src_l, src_h,
IDLE,
OP };
}
private void DEC_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
DEC16, src_l, src_h,
IDLE,
IDLE,
OP };
}
// this is done in two steps technically, but the flags don't work out using existing funcitons
// so let's use a different function since it's an internal operation anyway
private void ADD_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
TR16, Z, W, dest_l, dest_h,
INC16, Z, W,
IDLE,
IDLE,
ADD16, dest_l, dest_h, src_l, src_h,
IDLE,
IDLE,
OP };
}
private void REG_OP(ushort operation, ushort dest, ushort src)
{
cur_instr = new ushort[]
{operation, dest, src,
IDLE,
IDLE,
OP };
}
// Operations using the I and R registers take one T-cycle longer
private void REG_OP_IR(ushort operation, ushort dest, ushort src)
{
cur_instr = new ushort[]
{operation, dest, src,
IDLE,
IDLE,
SET_FL_IR, dest,
OP };
}
// note: do not use DEC here since no flags are affected by this operation
private void DJNZ_()
{
if ((Regs[B] - 1) != 0)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
ASGN, B, (ushort)((Regs[B] - 1) & 0xFF),
IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
ASGN, W, 0,
IDLE,
ADDS, PCl, PCh, Z, W,
TR16, Z, W, PCl, PCh,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
ASGN, B, (ushort)((Regs[B] - 1) & 0xFF),
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
OP };
}
}
private void HALT_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
HALT };
}
private void JR_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
IDLE,
IDLE,
ASGN, W, 0,
IDLE,
ADDS, PCl, PCh, Z, W,
TR16, Z, W, PCl, PCh,
IDLE,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
OP };
}
}
private void JP_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
TR16, PCl, PCh, Z, W,
IDLE,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
INC16, PCl, PCh,
IDLE,
IDLE,
OP };
}
}
private void RET_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
TR16, PCl, PCh, Z, W,
OP };
}
private void RETI_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
TR16, PCl, PCh, Z, W,
OP };
}
private void RETN_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
EI_RETN,
TR16, PCl, PCh, Z, W,
OP };
}
private void RET_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
IDLE,
TR16, PCl, PCh, Z, W,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
IDLE,
OP };
}
}
private void CALL_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
INC16, PCl, PCh,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCh,
DEC16, SPl, SPh,
WR, SPl, SPh, PCl,
IDLE,
TR, PCl, Z,
TR, PCh, W,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
OP };
}
}
private void INT_OP(ushort operation, ushort src)
{
cur_instr = new ushort[]
{operation, src,
IDLE,
IDLE,
OP };
}
private void BIT_OP(ushort operation, ushort bit, ushort src)
{
cur_instr = new ushort[]
{operation, bit, src,
IDLE,
IDLE,
OP };
}
private void PUSH_(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, src_h,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, src_l,
IDLE,
OP };
}
private void POP_(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
RD, src_l, SPl, SPh,
IDLE,
INC16, SPl, SPh,
IDLE,
RD, src_h, SPl, SPh,
IDLE,
INC16, SPl, SPh,
IDLE,
OP };
}
private void RST_(ushort n)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCh,
DEC16, SPl, SPh,
WR, SPl, SPh, PCl,
IDLE,
ASGN, Z, n,
ASGN, W, 0,
TR16, PCl, PCh, Z, W,
OP };
}
private void PREFIX_(ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
PREFIX, src};
}
private void PREFETCH_(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{TR16, Z, W, src_l, src_h,
ADDS, Z, W, ALU, ZERO,
IDLE,
PREFIX, IXYprefetch };
}
private void DI_()
{
cur_instr = new ushort[]
{DI,
IDLE,
IDLE,
OP };
}
private void EI_()
{
cur_instr = new ushort[]
{EI,
IDLE,
IDLE,
OP };
}
private void JP_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{TR, PCl, src_l,
IDLE,
TR, PCh, src_h,
OP };
}
private void LD_SP_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
TR, SPl, src_l,
TR, SPh, src_h,
IDLE,
OP };
}
private void OUT_()
{
cur_instr = new ushort[]
{IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
TR, W, A,
OUT, ALU, A,
TR, Z, ALU,
INC16, Z, ALU,
IDLE,
IDLE,
OP};
}
private void OUT_REG_(ushort dest, ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
OUT, dest, src,
IDLE,
TR16, Z, W, C, B,
INC16, Z, W,
IDLE,
OP};
}
private void IN_()
{
cur_instr = new ushort[]
{IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
TR, W, A,
IN, A, ALU,
TR, Z, ALU,
INC16, Z, W,
IDLE,
IDLE,
OP};
}
private void IN_REG_(ushort dest, ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IN, dest, src,
IDLE,
TR16, Z, W, C, B,
INC16, Z, W,
IDLE,
OP};
}
private void REG_OP_16_(ushort op, ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
TR16, Z, W, dest_l, dest_h,
INC16, Z, W,
IDLE,
IDLE,
op, dest_l, dest_h, src_l, src_h,
IDLE,
IDLE,
OP};
}
private void INT_MODE_(ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
INT_MODE, src,
OP };
}
private void RRD_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
TR16, Z, W, L, H,
IDLE,
RD, ALU, Z, W,
IDLE,
RRD, ALU, A,
IDLE,
WR, Z, W, ALU,
IDLE,
INC16, Z, W,
IDLE,
IDLE,
OP };
}
private void RLD_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
TR16, Z, W, L, H,
IDLE,
RD, ALU, Z, W,
IDLE,
RLD, ALU, A,
IDLE,
WR, Z, W, ALU,
IDLE,
INC16, Z, W,
IDLE,
IDLE,
OP };
}
}
}

View File

@ -0,0 +1,478 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
{
private void INT_OP_IND(ushort operation, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
operation, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
private void BIT_OP_IND(ushort operation, ushort bit, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
operation, bit, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
// Note that this operation uses I_BIT, same as indexed BIT.
// This is where the strange behaviour in Flag bits 3 and 5 come from.
// normally WZ contain I* + n when doing I_BIT ops, but here we use that code path
// even though WZ is not assigned to, letting it's value from other operations show through
private void BIT_TE_IND(ushort operation, ushort bit, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
I_BIT, bit, ALU,
IDLE,
OP };
}
private void REG_OP_IND_INC(ushort operation, ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
operation, dest, ALU,
INC16, src_l, src_h,
OP };
}
private void REG_OP_IND(ushort operation, ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
TR16, Z, W, src_l, src_h,
RD, ALU, Z, W,
INC16, Z, W,
operation, dest, ALU,
OP };
}
private void LD_16_IND_nn(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
WR, Z, W, src_l,
IDLE,
INC16, Z, W,
IDLE,
WR, Z, W, src_h,
IDLE,
OP };
}
private void LD_IND_16_nn(ushort dest_l, ushort dest_h)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, dest_l, Z, W,
IDLE,
INC16, Z, W,
IDLE,
RD, dest_h, Z, W,
IDLE,
OP };
}
private void LD_8_IND_nn(ushort src)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
WR, Z, W, src,
INC16, Z, W,
TR, W, A,
OP };
}
private void LD_IND_8_nn(ushort dest)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, dest, Z, W,
IDLE,
INC16, Z, W,
OP };
}
private void LD_8_IND(ushort dest_l, ushort dest_h, ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
TR16, Z, W, dest_l, dest_h,
WR, Z, W, src,
INC16, Z, W,
TR, W, A,
OP };
}
private void LD_8_IND_IND(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
INC16, src_l, src_h,
IDLE,
WR, dest_l, dest_h, ALU,
IDLE,
OP };
}
private void LD_IND_8_INC(ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, dest, src_l, src_h,
IDLE,
INC16, src_l, src_h,
OP };
}
private void LD_IND_8_DEC(ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, dest, src_l, src_h,
IDLE,
DEC16, src_l, src_h,
IDLE,
OP };
}
private void LD_IND_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, dest_l, src_l, src_h,
IDLE,
INC16, src_l, src_h,
RD, dest_h, src_l, src_h,
IDLE,
INC16, src_l, src_h,
OP };
}
private void INC_8_IND(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
INC8, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
private void DEC_8_IND(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
DEC8, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
// NOTE: WZ implied for the wollowing 3 functions
private void I_INT_OP(ushort operation, ushort dest)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
operation, ALU,
IDLE,
WR, Z, W, ALU,
IDLE,
TR, dest, ALU,
IDLE,
OP };
}
private void I_BIT_OP(ushort operation, ushort bit, ushort dest)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
operation, bit, ALU,
IDLE,
WR, Z, W, ALU,
IDLE,
TR, dest, ALU,
IDLE,
OP };
}
private void I_BIT_TE(ushort bit)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
I_BIT, bit, ALU,
IDLE,
OP };
}
private void I_OP_n(ushort operation, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, src_l, src_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
RD, ALU, Z, W,
IDLE,
IDLE,
operation, ALU,
IDLE,
IDLE,
IDLE,
WR, Z, W, ALU,
IDLE,
OP };
}
private void I_OP_n_n(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, src_l, src_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
RD, ALU, PCl, PCh,
INC16, PCl, PCh,
IDLE,
WR, Z, W, ALU,
IDLE,
OP };
}
private void I_REG_OP_IND_n(ushort operation, ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, src_l, src_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
RD, ALU, Z, W,
IDLE,
operation, dest, ALU,
IDLE,
OP };
}
private void I_LD_8_IND_n(ushort dest_l, ushort dest_h, ushort src)
{
cur_instr = new ushort[]
{IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, dest_l, dest_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
WR, Z, W, src,
IDLE,
IDLE,
IDLE,
IDLE,
OP };
}
private void LD_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{RD, ALU, L, H,
IDLE,
WR, E, D, ALU,
IDLE,
operation, L, H,
IDLE,
operation, E, D,
IDLE,
DEC16, C, B,
SET_FL_LD,
IDLE,
OP_R, 0, operation, repeat_instr };
}
private void CP_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, L, H,
operation, L, H,
IDLE,
IDLE,
DEC16, C, B,
SET_FL_CP,
IDLE,
operation, Z, W,
IDLE,
OP_R, 1, operation, repeat_instr };
}
private void IN_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{IN, ALU, C,
IDLE,
WR, L, H, ALU,
IDLE,
operation, L, H,
IDLE,
TR16, Z, W, C, B,
operation, Z, W,
IDLE,
DEC8, B,
IDLE,
OP_R, 2, operation, repeat_instr };
}
private void OUT_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{RD, ALU, L, H,
IDLE,
OUT, C, ALU,
IDLE,
IDLE,
operation, L, H,
DEC8, B,
IDLE,
TR16, Z, W, C, B,
operation, Z, W,
IDLE,
OP_R, 3, operation, repeat_instr };
}
// this is an indirect change of a a 16 bit register with memory
private void EXCH_16_IND_(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, dest_l, dest_h,
IDLE,
IDLE,
I_RD, W, dest_l, dest_h, 1,
IDLE,
IDLE,
WR, dest_l, dest_h, src_l,
IDLE,
IDLE,
I_WR, dest_l, dest_h, 1, src_h,
IDLE,
IDLE,
TR16, src_l, src_h, Z, W,
IDLE,
IDLE,
IDLE,
OP };
}
}
}

View File

@ -0,0 +1,688 @@
using System;
using System.Globalization;
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Common.NumberExtensions;
// Z80A CPU
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public sealed partial class Z80A
{
// operations that can take place in an instruction
public const ushort IDLE = 0;
public const ushort OP = 1;
public const ushort OP_R = 2; // used for repeating operations
public const ushort HALT = 3;
public const ushort RD = 4;
public const ushort WR = 5;
public const ushort I_RD = 6;
public const ushort I_WR = 7;
public const ushort TR = 8;
public const ushort TR16 = 9;
public const ushort ADD16 = 10;
public const ushort ADD8 = 11;
public const ushort SUB8 = 12;
public const ushort ADC8 = 13;
public const ushort SBC8 = 14;
public const ushort SBC16 = 15;
public const ushort ADC16 = 16;
public const ushort INC16 = 17;
public const ushort INC8 = 18;
public const ushort DEC16 = 19;
public const ushort DEC8 = 20;
public const ushort RLC = 21;
public const ushort RL = 22;
public const ushort RRC = 23;
public const ushort RR = 24;
public const ushort CPL = 25;
public const ushort DA = 26;
public const ushort SCF = 27;
public const ushort CCF = 28;
public const ushort AND8 = 29;
public const ushort XOR8 = 30;
public const ushort OR8 = 31;
public const ushort CP8 = 32;
public const ushort SLA = 33;
public const ushort SRA = 34;
public const ushort SRL = 35;
public const ushort SLL = 36;
public const ushort BIT = 37;
public const ushort RES = 38;
public const ushort SET = 39;
public const ushort EI = 40;
public const ushort DI = 41;
public const ushort EXCH = 42;
public const ushort EXX = 43;
public const ushort EXCH_16 = 44;
public const ushort PREFIX = 45;
public const ushort PREFETCH = 46;
public const ushort ASGN = 47;
public const ushort ADDS = 48; // signed 16 bit operation used in 2 instructions
public const ushort INT_MODE = 49;
public const ushort EI_RETN = 50;
public const ushort EI_RETI = 51; // reti has no delay in interrupt enable
public const ushort OUT = 52;
public const ushort IN = 53;
public const ushort NEG = 54;
public const ushort RRD = 55;
public const ushort RLD = 56;
public const ushort SET_FL_LD = 57;
public const ushort SET_FL_CP = 58;
public const ushort SET_FL_IR = 59;
public const ushort I_BIT = 60;
public const ushort HL_BIT = 61;
public byte temp_R;
public Z80A()
{
Reset();
InitTableParity();
}
public void Reset()
{
ResetRegisters();
ResetInterrupts();
TotalExecutedCycles = 0;
cur_instr = new ushort[] { OP };
instr_pntr = 0;
NO_prefix = true;
}
public IMemoryCallbackSystem MemoryCallbacks { get; set; }
// Memory Access
public Func<ushort, byte> FetchMemory;
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
public Func<ushort, byte> PeekMemory;
public Func<ushort, byte> DummyReadMemory;
// Hardware I/O Port Access
public Func<ushort, byte> ReadHardware;
public Action<ushort, byte> WriteHardware;
//this only calls when the first byte of an instruction is fetched.
public Action<ushort> OnExecFetch;
public void UnregisterMemoryMapper()
{
ReadMemory = null;
WriteMemory = null;
PeekMemory = null;
DummyReadMemory = null;
ReadHardware = null;
WriteHardware = null;
}
public void SetCallbacks
(
Func<ushort, byte> ReadMemory,
Func<ushort, byte> DummyReadMemory,
Func<ushort, byte> PeekMemory,
Action<ushort, byte> WriteMemory,
Func<ushort, byte> ReadHardware,
Action<ushort, byte> WriteHardware
)
{
this.ReadMemory = ReadMemory;
this.DummyReadMemory = DummyReadMemory;
this.PeekMemory = PeekMemory;
this.WriteMemory = WriteMemory;
this.ReadHardware = ReadHardware;
this.WriteHardware = WriteHardware;
}
// Execute instructions
public void ExecuteOne()
{
if (Regs[A] > 255) { Console.WriteLine(RegPC); }
switch (cur_instr[instr_pntr++])
{
case IDLE:
// do nothing
break;
case OP:
// Read the opcode of the next instruction
if (EI_pending > 0)
{
EI_pending--;
if (EI_pending == 0) { IFF1 = IFF2 = true; }
}
// Process interrupt requests.
if (nonMaskableInterruptPending)
{
nonMaskableInterruptPending = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""});
}
iff2 = iff1;
iff1 = false;
NMI_();
NMICallback();
}
else if (iff1 && FlagI)
{
iff1 = iff2 = false;
EI_pending = 0;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""});
}
switch (interruptMode)
{
case 0:
// Requires something to be pushed onto the data bus
// we'll assume it's a zero for now
INTERRUPT_0(0);
break;
case 1:
INTERRUPT_1();
break;
case 2:
// Low byte of interrupt vector comes from data bus
// We'll assume it's zero for now
INTERRUPT_2(0);
break;
}
IRQCallback();
}
else
{
if (OnExecFetch != null) OnExecFetch(RegPC);
if (TraceCallback != null) TraceCallback(State());
FetchInstruction(FetchMemory(RegPC++));
}
instr_pntr = 0;
temp_R = (byte)(Regs[R] & 0x7F);
temp_R++;
temp_R &= 0x7F;
Regs[R] = (byte)((Regs[R] & 0x80) | temp_R);
break;
case OP_R:
// determine if we repeat based on what operation we are doing
// single execution versions also come here, but never repeat
ushort temp1 = cur_instr[instr_pntr++];
ushort temp2 = cur_instr[instr_pntr++];
ushort temp3 = cur_instr[instr_pntr++];
bool repeat = false;
int Reg16_d = Regs[C] | (Regs[B] << 8);
switch (temp1)
{
case 0:
repeat = Reg16_d != 0;
break;
case 1:
repeat = (Reg16_d != 0) && !FlagZ;
break;
case 2:
repeat = Regs[B] != 0;
break;
case 3:
repeat = Regs[B] != 0;
break;
}
// if we repeat, we do a 5 cycle refresh which decrements PC by 2
// if we don't repeat, continue on as a normal opcode fetch
if (repeat && temp3 > 0)
{
cur_instr = new ushort[]
{IDLE,
DEC16, PCl, PCh,
IDLE,
DEC16, PCl, PCh,
OP };
// adjust WZ register accordingly
switch (temp1)
{
case 0:
// TEST: PC before or after the instruction?
Regs[Z] = Regs[PCl];
Regs[W] = Regs[PCh];
INC16_Func(Z, W);
break;
case 1:
// TEST: PC before or after the instruction?
Regs[Z] = Regs[PCl];
Regs[W] = Regs[PCh];
INC16_Func(Z, W);
break;
case 2:
// Nothing
break;
case 3:
// Nothing
break;
}
}
else
{
// Interrupts can occur at this point, so process them accordingly
// Read the opcode of the next instruction
if (EI_pending > 0)
{
EI_pending--;
if (EI_pending == 0) { IFF1 = IFF2 = true; }
}
// Process interrupt requests.
if (nonMaskableInterruptPending)
{
nonMaskableInterruptPending = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""});
}
iff2 = iff1;
iff1 = false;
NMI_();
NMICallback();
}
else if (iff1 && FlagI)
{
iff1 = iff2 = false;
EI_pending = 0;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""});
}
switch (interruptMode)
{
case 0:
// Requires something to be pushed onto the data bus
// we'll assume it's a zero for now
INTERRUPT_0(0);
break;
case 1:
INTERRUPT_1();
break;
case 2:
// Low byte of interrupt vector comes from data bus
// We'll assume it's zero for now
INTERRUPT_2(0);
break;
}
IRQCallback();
}
else
{
if (OnExecFetch != null) OnExecFetch(RegPC);
if (TraceCallback != null) TraceCallback(State());
FetchInstruction(FetchMemory(RegPC++));
}
temp_R = (byte)(Regs[R] & 0x7F);
temp_R++;
temp_R &= 0x7F;
Regs[R] = (byte)((Regs[R] & 0x80) | temp_R);
}
instr_pntr = 0;
break;
case HALT:
halted = true;
if (EI_pending > 0)
{
EI_pending--;
if (EI_pending == 0) { IFF1 = IFF2 = true; }
}
// Process interrupt requests.
if (nonMaskableInterruptPending)
{
nonMaskableInterruptPending = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""});
}
iff2 = iff1;
iff1 = false;
NMI_();
NMICallback();
halted = false;
}
else if (iff1 && FlagI)
{
iff1 = iff2 = false;
EI_pending = 0;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""});
}
switch (interruptMode)
{
case 0:
// Requires something to be pushed onto the data bus
// we'll assume it's a zero for now
INTERRUPT_0(0);
break;
case 1:
INTERRUPT_1();
break;
case 2:
// Low byte of interrupt vector comes from data bus
// We'll assume it's zero for now
INTERRUPT_2(0);
break;
}
IRQCallback();
halted = false;
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
HALT };
}
temp_R = (byte)(Regs[R] & 0x7F);
temp_R++;
temp_R &= 0x7F;
Regs[R] = (byte)((Regs[R] & 0x80) | temp_R);
instr_pntr = 0;
break;
case RD:
Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case WR:
Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case I_RD:
I_Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case I_WR:
I_Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case TR:
TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case TR16:
TR16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADD16:
ADD16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADD8:
ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SUB8:
SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADC8:
ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADC16:
ADC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SBC8:
SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SBC16:
SBC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case INC16:
INC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case INC8:
INC8_Func(cur_instr[instr_pntr++]);
break;
case DEC16:
DEC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case DEC8:
DEC8_Func(cur_instr[instr_pntr++]);
break;
case RLC:
RLC_Func(cur_instr[instr_pntr++]);
break;
case RL:
RL_Func(cur_instr[instr_pntr++]);
break;
case RRC:
RRC_Func(cur_instr[instr_pntr++]);
break;
case RR:
RR_Func(cur_instr[instr_pntr++]);
break;
case CPL:
CPL_Func(cur_instr[instr_pntr++]);
break;
case DA:
DA_Func(cur_instr[instr_pntr++]);
break;
case SCF:
SCF_Func(cur_instr[instr_pntr++]);
break;
case CCF:
CCF_Func(cur_instr[instr_pntr++]);
break;
case AND8:
AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case XOR8:
XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case OR8:
OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case CP8:
CP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SLA:
SLA_Func(cur_instr[instr_pntr++]);
break;
case SRA:
SRA_Func(cur_instr[instr_pntr++]);
break;
case SRL:
SRL_Func(cur_instr[instr_pntr++]);
break;
case SLL:
SLL_Func(cur_instr[instr_pntr++]);
break;
case BIT:
BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case I_BIT:
I_BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case RES:
RES_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SET:
SET_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case EI:
EI_pending = 2;
break;
case DI:
IFF1 = IFF2 = false;
break;
case EXCH:
EXCH_16_Func(F_s, A_s, F, A);
break;
case EXX:
EXCH_16_Func(C_s, B_s, C, B);
EXCH_16_Func(E_s, D_s, E, D);
EXCH_16_Func(L_s, H_s, L, H);
break;
case EXCH_16:
EXCH_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case PREFIX:
ushort prefix_src = cur_instr[instr_pntr++];
NO_prefix = false;
if (prefix_src == CBpre) { CB_prefix = true; }
if (prefix_src == EXTDpre) { EXTD_prefix = true; }
if (prefix_src == IXpre) { IX_prefix = true; }
if (prefix_src == IYpre) { IY_prefix = true; }
if (prefix_src == IXCBpre) { IXCB_prefix = true; IXCB_prefetch = true; }
if (prefix_src == IYCBpre) { IYCB_prefix = true; IYCB_prefetch = true; }
FetchInstruction(FetchMemory(RegPC++));
instr_pntr = 0;
// only the first prefix in a double prefix increases R, although I don't know how / why
if (prefix_src < 4)
{
temp_R = (byte)(Regs[R] & 0x7F);
temp_R++;
temp_R &= 0x7F;
Regs[R] = (byte)((Regs[R] & 0x80) | temp_R);
}
break;
case ASGN:
ASGN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADDS:
ADDS_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case EI_RETI:
// NOTE: This is needed for systems using multiple interrupt sources, it triggers the next interrupt
// Not currently implemented here
iff1 = iff2;
break;
case EI_RETN:
iff1 = iff2;
break;
case OUT:
OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case IN:
IN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case NEG:
NEG_8_Func(cur_instr[instr_pntr++]);
break;
case INT_MODE:
interruptMode = cur_instr[instr_pntr++];
break;
case RRD:
RRD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case RLD:
RLD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SET_FL_LD:
SET_FL_LD_Func();
break;
case SET_FL_CP:
SET_FL_CP_Func();
break;
case SET_FL_IR:
SET_FL_IR_Func(cur_instr[instr_pntr++]);
break;
}
totalExecutedCycles++;
}
// tracer stuff
public Action<TraceInfo> TraceCallback;
public string TraceHeader
{
get { return "Z80A: PC, machine code, mnemonic, operands, registers (AF, BC, DE, HL, IX, IY, SP, Cy), flags (CNP3H5ZS)"; }
}
public TraceInfo State(bool disassemble = true)
{
ushort bytes_read = 0;
string disasm = disassemble ? Disassemble(RegPC, ReadMemory, out bytes_read) : "---";
string byte_code = null;
for (ushort i = 0; i < bytes_read; i++)
{
byte_code += ReadMemory((ushort)(RegPC + i)).ToHexString(2);
if (i < (bytes_read - 1))
{
byte_code += " ";
}
}
return new TraceInfo
{
Disassembly = string.Format(
"{0:X4}: {1} {2}",
RegPC,
byte_code.PadRight(12),
disasm.PadRight(26)),
RegisterInfo = string.Format(
"AF:{0:X4} BC:{1:X4} DE:{2:X4} HL:{3:X4} IX:{4:X4} IY:{5:X4} SP:{6:X4} Cy:{7} {8}{9}{10}{11}{12}{13}{14}{15}{16}",
(Regs[A] << 8) + Regs[F],
(Regs[B] << 8) + Regs[C],
(Regs[D] << 8) + Regs[E],
(Regs[H] << 8) + Regs[L],
(Regs[Ixh] << 8) + Regs[Ixl],
(Regs[Iyh] << 8) + Regs[Iyl],
Regs[SPl] | (Regs[SPh] << 8),
TotalExecutedCycles,
FlagC ? "C" : "c",
FlagN ? "N" : "n",
FlagP ? "P" : "p",
Flag3 ? "3" : "-",
FlagH ? "H" : "h",
Flag5 ? "5" : "-",
FlagZ ? "Z" : "z",
FlagS ? "S" : "s",
FlagI ? "E" : "e")
};
}
// State Save/Load
public void SyncState(Serializer ser)
{
ser.BeginSection("Z80A");
ser.Sync("Regs", ref Regs, false);
ser.Sync("NMI", ref nonMaskableInterrupt);
ser.Sync("NMIPending", ref nonMaskableInterruptPending);
ser.Sync("IM", ref interruptMode);
ser.Sync("IFF1", ref iff1);
ser.Sync("IFF2", ref iff2);
ser.Sync("Halted", ref halted);
ser.Sync("ExecutedCycles", ref totalExecutedCycles);
ser.Sync("EI_pending", ref EI_pending);
ser.Sync("instruction_pointer", ref instr_pntr);
ser.Sync("current instruction", ref cur_instr, false);
ser.Sync("opcode", ref opcode);
ser.Sync("FlagI", ref FlagI);
ser.Sync("NO Preifx", ref NO_prefix);
ser.Sync("CB Preifx", ref CB_prefix);
ser.Sync("IX_prefix", ref IX_prefix);
ser.Sync("IY_prefix", ref IY_prefix);
ser.Sync("IXCB_prefix", ref IXCB_prefix);
ser.Sync("IYCB_prefix", ref IYCB_prefix);
ser.Sync("EXTD_prefix", ref EXTD_prefix);
ser.Sync("IXCB_prefetch", ref IXCB_prefetch);
ser.Sync("IYCB_prefetch", ref IYCB_prefetch);
ser.Sync("PF", ref PF);
ser.EndSection();
}
}
}

View File

@ -12,36 +12,36 @@ namespace BizHawk.Emulation.Cores.Calculators
{
return new Dictionary<string, RegisterValue>
{
["A"] = _cpu.RegisterA,
["AF"] = _cpu.RegisterAF,
["B"] = _cpu.RegisterB,
["BC"] = _cpu.RegisterBC,
["C"] = _cpu.RegisterC,
["D"] = _cpu.RegisterD,
["DE"] = _cpu.RegisterDE,
["E"] = _cpu.RegisterE,
["F"] = _cpu.RegisterF,
["H"] = _cpu.RegisterH,
["HL"] = _cpu.RegisterHL,
["I"] = _cpu.RegisterI,
["IX"] = _cpu.RegisterIX,
["IY"] = _cpu.RegisterIY,
["L"] = _cpu.RegisterL,
["PC"] = _cpu.RegisterPC,
["R"] = _cpu.RegisterR,
["Shadow AF"] = _cpu.RegisterShadowAF,
["Shadow BC"] = _cpu.RegisterShadowBC,
["Shadow DE"] = _cpu.RegisterShadowDE,
["Shadow HL"] = _cpu.RegisterShadowHL,
["SP"] = _cpu.RegisterSP,
["Flag C"] = _cpu.RegisterF.Bit(0),
["Flag N"] = _cpu.RegisterF.Bit(1),
["Flag P/V"] = _cpu.RegisterF.Bit(2),
["Flag 3rd"] = _cpu.RegisterF.Bit(3),
["Flag H"] = _cpu.RegisterF.Bit(4),
["Flag 5th"] = _cpu.RegisterF.Bit(5),
["Flag Z"] = _cpu.RegisterF.Bit(6),
["Flag S"] = _cpu.RegisterF.Bit(7)
["A"] = _cpu.Regs[_cpu.A],
["AF"] = _cpu.Regs[_cpu.F] + (_cpu.Regs[_cpu.A] << 8),
["B"] = _cpu.Regs[_cpu.B],
["BC"] = _cpu.Regs[_cpu.C] + (_cpu.Regs[_cpu.B] << 8),
["C"] = _cpu.Regs[_cpu.C],
["D"] = _cpu.Regs[_cpu.D],
["DE"] = _cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8),
["E"] = _cpu.Regs[_cpu.E],
["F"] = _cpu.Regs[_cpu.F],
["H"] = _cpu.Regs[_cpu.H],
["HL"] = _cpu.Regs[_cpu.L] + (_cpu.Regs[_cpu.H] << 8),
["I"] = _cpu.Regs[_cpu.I],
["IX"] = _cpu.Regs[_cpu.Ixl] + (_cpu.Regs[_cpu.Ixh] << 8),
["IY"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8),
["L"] = _cpu.Regs[_cpu.L],
["PC"] = _cpu.Regs[_cpu.PCl] + (_cpu.Regs[_cpu.PCh] << 8),
["R"] = _cpu.Regs[_cpu.R],
["Shadow AF"] = _cpu.Regs[_cpu.F_s] + (_cpu.Regs[_cpu.A_s] << 8),
["Shadow BC"] = _cpu.Regs[_cpu.C_s] + (_cpu.Regs[_cpu.B_s] << 8),
["Shadow DE"] = _cpu.Regs[_cpu.E_s] + (_cpu.Regs[_cpu.D_s] << 8),
["Shadow HL"] = _cpu.Regs[_cpu.L_s] + (_cpu.Regs[_cpu.H_s] << 8),
["SP"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8),
["Flag C"] = _cpu.FlagC,
["Flag N"] = _cpu.FlagN,
["Flag P/V"] = _cpu.FlagP,
["Flag 3rd"] = _cpu.Flag3,
["Flag H"] = _cpu.FlagH,
["Flag 5th"] = _cpu.Flag5,
["Flag Z"] = _cpu.FlagZ,
["Flag S"] = _cpu.FlagS
};
}
@ -49,78 +49,90 @@ namespace BizHawk.Emulation.Cores.Calculators
{
switch (register)
{
default:
throw new InvalidOperationException();
case "A":
_cpu.RegisterA = (byte)value;
break;
case "AF":
_cpu.RegisterAF = (byte)value;
break;
case "B":
_cpu.RegisterB = (byte)value;
break;
case "BC":
_cpu.RegisterBC = (byte)value;
break;
case "C":
_cpu.RegisterC = (byte)value;
break;
case "D":
_cpu.RegisterD = (byte)value;
break;
case "DE":
_cpu.RegisterDE = (byte)value;
break;
case "E":
_cpu.RegisterE = (byte)value;
break;
case "F":
_cpu.RegisterF = (byte)value;
break;
case "H":
_cpu.RegisterH = (byte)value;
break;
case "HL":
_cpu.RegisterHL = (byte)value;
break;
case "I":
_cpu.RegisterI = (byte)value;
break;
case "IX":
_cpu.RegisterIX = (byte)value;
break;
case "IY":
_cpu.RegisterIY = (byte)value;
break;
case "L":
_cpu.RegisterL = (byte)value;
break;
case "PC":
_cpu.RegisterPC = (ushort)value;
break;
case "R":
_cpu.RegisterR = (byte)value;
break;
case "Shadow AF":
_cpu.RegisterShadowAF = (byte)value;
break;
case "Shadow BC":
_cpu.RegisterShadowBC = (byte)value;
break;
case "Shadow DE":
_cpu.RegisterShadowDE = (byte)value;
break;
case "Shadow HL":
_cpu.RegisterShadowHL = (byte)value;
break;
case "SP":
_cpu.RegisterSP = (byte)value;
default:
throw new InvalidOperationException();
case "A":
_cpu.Regs[_cpu.A] = (ushort)value;
break;
case "AF":
_cpu.Regs[_cpu.F] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.A] = (ushort)(value & 0xFF00);
break;
case "B":
_cpu.Regs[_cpu.B] = (ushort)value;
break;
case "BC":
_cpu.Regs[_cpu.C] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.B] = (ushort)(value & 0xFF00);
break;
case "C":
_cpu.Regs[_cpu.C] = (ushort)value;
break;
case "D":
_cpu.Regs[_cpu.D] = (ushort)value;
break;
case "DE":
_cpu.Regs[_cpu.E] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.D] = (ushort)(value & 0xFF00);
break;
case "E":
_cpu.Regs[_cpu.E] = (ushort)value;
break;
case "F":
_cpu.Regs[_cpu.F] = (ushort)value;
break;
case "H":
_cpu.Regs[_cpu.H] = (ushort)value;
break;
case "HL":
_cpu.Regs[_cpu.L] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.H] = (ushort)(value & 0xFF00);
break;
case "I":
_cpu.Regs[_cpu.I] = (ushort)value;
break;
case "IX":
_cpu.Regs[_cpu.Ixl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.Ixh] = (ushort)(value & 0xFF00);
break;
case "IY":
_cpu.Regs[_cpu.Iyl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.Iyh] = (ushort)(value & 0xFF00);
break;
case "L":
_cpu.Regs[_cpu.L] = (ushort)value;
break;
case "PC":
_cpu.Regs[_cpu.PCl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.PCh] = (ushort)(value & 0xFF00);
break;
case "R":
_cpu.Regs[_cpu.R] = (ushort)value;
break;
case "Shadow AF":
_cpu.Regs[_cpu.F_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.A_s] = (ushort)(value & 0xFF00);
break;
case "Shadow BC":
_cpu.Regs[_cpu.C_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.B_s] = (ushort)(value & 0xFF00);
break;
case "Shadow DE":
_cpu.Regs[_cpu.E_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.D_s] = (ushort)(value & 0xFF00);
break;
case "Shadow HL":
_cpu.Regs[_cpu.L_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.H_s] = (ushort)(value & 0xFF00);
break;
case "SP":
_cpu.Regs[_cpu.SPl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.SPh] = (ushort)(value & 0xFF00);
break;
}
}
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem();
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
[FeatureNotImplemented]
public void Step(StepType type)

View File

@ -13,21 +13,42 @@ namespace BizHawk.Emulation.Cores.Calculators
_controller = controller;
_lagged = true;
_cpu.Debug = _tracer.Enabled;
if (_cpu.Debug && _cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first
if (_tracer.Enabled)
{
_cpu.Logger = s => _tracer.Put(s);
_cpu.TraceCallback = s => _tracer.Put(s);
}
else
{
_cpu.TraceCallback = null;
}
// I eyeballed this speed
for (int i = 0; i < 5; i++)
{
_onPressed = controller.IsPressed("ON");
_onPressed = controller.IsPressed("ON");
// and this was derived from other emus
_cpu.ExecuteCycles(10000);
_cpu.Interrupt = true;
if (_onPressed && ON_key_int_EN && !ON_key_int)
{
ON_key_int = true;
_cpu.FlagI = true;
}
// see: http://wikiti.brandonw.net/index.php?title=83:Ports:04
// for timer interrupt frequency
// CPU frequency is 6MHz
for (int i = 0; i < 100000; i++)
{
_cpu.ExecuteOne();
TIM_count++;
if (TIM_count >= TIM_hit)
{
TIM_count = 0;
if (TIM_1_int_EN)
{
TIM_1_int = true;
_cpu.FlagI = true;
}
}
}
Frame++;

View File

@ -7,55 +7,52 @@ namespace BizHawk.Emulation.Cores.Calculators
{
public partial class TI83 : IStatable
{
private byte[] _stateBuffer;
public bool BinarySaveStatesPreferred
{
get { return true; }
}
public bool BinarySaveStatesPreferred => false;
public void SaveStateText(TextWriter writer)
{
SyncState(new Serializer(writer));
}
public void LoadStateText(TextReader reader)
{
SyncState(new Serializer(reader));
}
public void SaveStateBinary(BinaryWriter bw)
{
SyncState(Serializer.CreateBinaryWriter(bw));
SyncState(new Serializer(bw));
}
public void LoadStateBinary(BinaryReader br)
{
SyncState(Serializer.CreateBinaryReader(br));
}
public void SaveStateText(TextWriter tw)
{
SyncState(Serializer.CreateTextWriter(tw));
}
public void LoadStateText(TextReader tr)
{
SyncState(Serializer.CreateTextReader(tr));
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
if (_stateBuffer == null)
{
var stream = new MemoryStream();
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
_stateBuffer = stream.ToArray();
writer.Close();
return _stateBuffer;
}
else
{
var stream = new MemoryStream(_stateBuffer);
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Close();
return _stateBuffer;
}
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.BeginSection("TI83");
byte[] core = null;
if (ser.IsWriter)
{
var ms = new MemoryStream();
ms.Close();
core = ms.ToArray();
}
_cpu.SyncState(ser);
ser.BeginSection("TI83");
ser.Sync("RAM", ref _ram, false);
ser.Sync("romPageLow3Bits", ref _romPageLow3Bits);
ser.Sync("romPageHighBit", ref _romPageHighBit);
@ -72,6 +69,15 @@ namespace BizHawk.Emulation.Cores.Calculators
ser.Sync("Frame", ref _frame);
ser.Sync("LagCount", ref _lagCount);
ser.Sync("IsLag", ref _isLag);
ser.Sync("ON_key_int", ref ON_key_int);
ser.Sync("ON_key_int_EN", ref ON_key_int_EN);
ser.Sync("TIM_1_int", ref TIM_1_int);
ser.Sync("TIM_1_int_EN", ref TIM_1_int_EN);
ser.Sync("TIM_frq", ref TIM_frq);
ser.Sync("TIM_mult", ref TIM_mult);
ser.Sync("TIM_count", ref TIM_count);
ser.Sync("TIM_hit", ref TIM_hit);
ser.EndSection();
if (ser.IsReader)

View File

@ -2,7 +2,7 @@ using System;
using System.Globalization;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components.Z80;
using BizHawk.Emulation.Cores.Components.Z80A;
// http://www.ticalc.org/pub/text/calcinfo/
namespace BizHawk.Emulation.Cores.Calculators
@ -23,6 +23,7 @@ namespace BizHawk.Emulation.Cores.Calculators
PutSettings((TI83Settings)settings ?? new TI83Settings());
CoreComm = comm;
_cpu.FetchMemory = ReadMemory;
_cpu.ReadMemory = ReadMemory;
_cpu.WriteMemory = WriteMemory;
_cpu.ReadHardware = ReadHardware;
@ -34,21 +35,13 @@ namespace BizHawk.Emulation.Cores.Calculators
_rom = rom;
LinkPort = new TI83LinkPort(this);
// different calculators (different revisions?) have different initPC. we track this in the game database by rom hash
// if( *(unsigned long *)(m_pRom + 0x6ce) == 0x04D3163E ) m_Regs.PC.W = 0x6ce; //KNOWN
// else if( *(unsigned long *)(m_pRom + 0x6f6) == 0x04D3163E ) m_Regs.PC.W = 0x6f6; //UNKNOWN
if (game["initPC"])
{
_startPC = ushort.Parse(game.OptionValue("initPC"), NumberStyles.HexNumber);
}
HardReset();
SetupMemoryDomains();
_tracer = new TraceBuffer { Header = _cpu.TraceHeader };
ser.Register<ITraceable>(_tracer);
ser.Register<IDisassemblable>(new Disassembler());
ser.Register<IDisassemblable>(_cpu);
}
private readonly TraceBuffer _tracer;
@ -57,8 +50,6 @@ namespace BizHawk.Emulation.Cores.Calculators
private readonly byte[] _rom;
// configuration
private readonly ushort _startPC;
private IController _controller;
private byte[] _ram;
@ -75,6 +66,10 @@ namespace BizHawk.Emulation.Cores.Calculators
private bool _cursorMoved;
private int _frame;
public bool ON_key_int, ON_key_int_EN;
public bool TIM_1_int, TIM_1_int_EN;
public int TIM_frq, TIM_mult, TIM_count, TIM_hit;
// Link Cable
public TI83LinkPort LinkPort { get; }
@ -151,7 +146,7 @@ namespace BizHawk.Emulation.Cores.Calculators
if (LinkActive)
{
// Prevent rom calls from disturbing link port activity
if (LinkActive && _cpu.RegisterPC < 0x4000)
if (LinkActive && _cpu.RegPC < 0x4000)
{
return;
}
@ -169,7 +164,60 @@ namespace BizHawk.Emulation.Cores.Calculators
_romPageLow3Bits = value & 0x7;
break;
case 3: // PORT_STATUS
_maskOn = (byte)(value & 1);
// controls ON key interrupts
if ((value & 0x1) == 0)
{
ON_key_int = false;
ON_key_int_EN = false;
}
else
{
ON_key_int_EN = true;
}
// controls first timer interrupts
if ((value & 0x2) == 0)
{
TIM_1_int = false;
TIM_1_int_EN = false;
}
else
{
TIM_1_int_EN = true;
}
// controls second timer, not yet implemented and unclear how to differentiate
if ((value & 0x4) == 0)
{
}
else
{
}
// controls low power mode, not yet implemeneted
if ((value & 0x8) == 0)
{
}
else
{
}
break;
case 4: // PORT_INTCTRL
// controls ON key interrupts
TIM_frq = value & 6;
TIM_mult = ((value & 0x10) == 0x10) ? 1800 : 1620;
TIM_hit = (int)Math.Floor((double)TIM_mult / (3 + TIM_frq * 2));
TIM_hit = (int)Math.Floor((double)6000000 / TIM_hit);
// Bit 0 is some form of memory mapping
// Bit 5 controls reset
// Bit 6-7 controls battery power compare (not implemented, will always return full power)
break;
case 16: // PORT_DISPCTRL
////Console.WriteLine("write PORT_DISPCTRL {0}",value);
@ -198,22 +246,23 @@ namespace BizHawk.Emulation.Cores.Calculators
{
// Console.WriteLine("read PORT_STATUS");
// Bits:
// 0 - Set if ON key is down and ON key is trapped
// 0 - Set if ON key Interrupt generated
// 1 - Update things (keyboard etc)
// 2 - Unknown, but used
// 3 - Set if ON key is up
// 4-7 - Unknown
////if (onPressed && maskOn) ret |= 1;
////if (!onPressed) ret |= 0x8;
return (byte)((_controller.IsPressed("ON") ? _maskOn : 8) | (LinkActive ? 0 : 2));
return (byte)((_controller.IsPressed("ON") ? 0 : 8) |
(TIM_1_int ? 2 : 0) |
(ON_key_int ? 1 : 0));
}
case 4: // PORT_INTCTRL
////Console.WriteLine("read PORT_INTCTRL");
return 0xFF;
// returns mirror of link port
return (byte)((_romPageHighBit << 4) | (LinkState << 2) | LinkOutput);
case 16: // PORT_DISPCTRL
////Console.WriteLine("read DISPCTRL");
// Console.WriteLine("read DISPCTRL");
break;
case 17: // PORT_DISPDATA
@ -428,13 +477,13 @@ namespace BizHawk.Emulation.Cores.Calculators
private void IRQCallback()
{
// Console.WriteLine("IRQ with vec {0} and cpu.InterruptMode {1}", cpu.RegisterI, cpu.InterruptMode);
_cpu.Interrupt = false;
//Console.WriteLine("IRQ with vec {0} and cpu.InterruptMode {1}", _cpu.Regs[_cpu.I], _cpu.InterruptMode);
_cpu.FlagI = false;
}
private void NMICallback()
{
Console.WriteLine("NMI");
//Console.WriteLine("NMI");
_cpu.NonMaskableInterrupt = false;
}
@ -447,7 +496,7 @@ namespace BizHawk.Emulation.Cores.Calculators
_ram[i] = 0xFF;
}
_cpu.RegisterPC = _startPC;
_cpu.RegPC = 0;
_cpu.IFF1 = false;
_cpu.IFF2 = false;
@ -463,4 +512,4 @@ namespace BizHawk.Emulation.Cores.Calculators
_displayX = _displayY = 0;
}
}
}
}

View File

@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
}
}
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem();
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
public bool CanStep(StepType type)
{

View File

@ -183,9 +183,9 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
private void SetCallbacks()
{
_machine.Memory.ReadCallback = MemoryCallbacks.CallReads;
_machine.Memory.WriteCallback = MemoryCallbacks.CallWrites;
_machine.Memory.ExecuteCallback = MemoryCallbacks.CallExecutes;
_machine.Memory.ReadCallback = (addr) => MemoryCallbacks.CallReads(addr, "System Bus");
_machine.Memory.WriteCallback = (addr) => MemoryCallbacks.CallWrites(addr, "System Bus");
_machine.Memory.ExecuteCallback = (addr) => MemoryCallbacks.CallExecutes(addr, "System Bus");
_machine.Memory.InputCallback = InputCallbacks.Call;
}
}

View File

@ -32,7 +32,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
Init(SyncSettings.VicType, Settings.BorderType, SyncSettings.SidType, SyncSettings.TapeDriveType, SyncSettings.DiskDriveType);
_cyclesPerFrame = _board.Vic.CyclesPerFrame;
_memoryCallbacks = new MemoryCallbackSystem();
_memoryCallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
HardReset();

View File

@ -148,6 +148,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private const byte JsrSize = 3;
IMemoryCallbackSystem IDebuggable.MemoryCallbacks { get; } = new MemoryCallbackSystem();
IMemoryCallbackSystem IDebuggable.MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
}
}

View File

@ -21,7 +21,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private IController _controller;
private int _frame;
private int _lastAddress;
private bool _frameStartPending = true;
private bool _leftDifficultySwitchPressed;
private bool _rightDifficultySwitchPressed;
@ -34,6 +33,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
internal byte[] Rom { get; }
internal int DistinctAccessCount { get; private set; }
// keeps track of tia cycles, 3 cycles per CPU cycle
private int cyc_counter;
private static MapperBase SetMultiCartMapper(int romLength, int gameTotal)
{
switch (romLength / gameTotal)
@ -134,7 +136,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_mapper.Bit13 = addr.Bit(13);
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF));
_tia.BusState = temp;
MemoryCallbacks.CallReads(addr);
MemoryCallbacks.CallReads(addr, "System Bus");
return temp;
}
@ -155,7 +157,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_mapper.WriteMemory((ushort)(addr & 0x1FFF), value);
MemoryCallbacks.CallWrites(addr);
MemoryCallbacks.CallWrites(addr, "System Bus");
}
internal void PokeMemory(ushort addr, byte value)
@ -165,7 +167,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private void ExecFetch(ushort addr)
{
MemoryCallbacks.CallExecutes(addr);
MemoryCallbacks.CallExecutes(addr, "System Bus");
}
private void RebootCore()
@ -319,17 +321,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_m6532 = new M6532(this);
// Set up the system state here. for instance..
// Read from the reset vector for where to start
Cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8)); // set the initial PC
HardReset();
// Show mapper class on romstatusdetails
CoreComm.RomStatusDetails = $"{this._game.Name}\r\nSHA1:{Rom.HashSHA1()}\r\nMD5:{Rom.HashMD5()}\r\nMapper Impl \"{_mapper.GetType()}\"";
// as it turns out, the stack pointer cannot be set to 0 for some games as they do not initilize it themselves.
// some documentation seems to indicate it should beset to FD, but currently there is no documentation of the 6532
// executing a reset sequence at power on, but it's needed so let's hard code it for now
Cpu.S = 0xFD;
}
private bool _pal;
@ -349,96 +344,28 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
};
_tia.Reset();
_m6532 = new M6532(this);
Cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8)); // set the initial PC
// as it turns out, the stack pointer cannot be set to 0 for some games as they do not initilize it themselves.
// some documentation seems to indicate it should beset to FD, but currently there is no documentation of the 6532
// executing a reset sequence at power on, but it's needed so let's hard code it for now
Cpu.S = 0xFD;
SetupMemoryDomains();
}
private void VFrameAdvance() // advance up to 500 lines looking for end of video frame
// after vsync falling edge, continues to end of next line
{
bool frameend = false;
_tia.FrameEndCallBack = (n) => frameend = true;
for (int i = 0; i < 500 && !frameend; i++)
{
ScanlineAdvance();
}
_tia.FrameEndCallBack = null;
}
private void StartFrameCond()
{
if (_frameStartPending)
{
_frame++;
_islag = true;
if (_controller.IsPressed("Power"))
{
HardReset();
}
if (_controller.IsPressed("Toggle Left Difficulty") && !_leftDifficultySwitchHeld)
{
_leftDifficultySwitchPressed ^= true;
_leftDifficultySwitchHeld = true;
}
else if (!_controller.IsPressed("Toggle Left Difficulty"))
{
_leftDifficultySwitchHeld = false;
}
if (_controller.IsPressed("Toggle Right Difficulty") && !_rightDifficultySwitchHeld)
{
_rightDifficultySwitchPressed ^= true;
_rightDifficultySwitchHeld = true;
}
else if (!_controller.IsPressed("Toggle Right Difficulty"))
{
_rightDifficultySwitchHeld = false;
}
_tia.BeginAudioFrame();
_frameStartPending = false;
}
}
private void FinishFrameCond()
{
if (_tia.LineCount >= _tia.NominalNumScanlines)
{
_tia.CompleteAudioFrame();
if (_islag)
{
_lagcount++;
}
_tia.LineCount = 0;
_frameStartPending = true;
}
cyc_counter = 0;
}
private void Cycle()
{
_tia.Execute(1);
_tia.Execute(1);
_tia.Execute(1);
_m6532.Timer.Tick();
if (Tracer.Enabled)
_tia.Execute();
cyc_counter++;
if (cyc_counter == 3)
{
Tracer.Put(Cpu.TraceState());
}
_m6532.Timer.Tick();
if (Tracer.Enabled)
{
Tracer.Put(Cpu.TraceState());
}
Cpu.ExecuteOne();
_mapper.ClockCpu();
Cpu.ExecuteOne();
_mapper.ClockCpu();
cyc_counter = 0;
}
}
internal byte ReadControls1(bool peek)

View File

@ -56,101 +56,22 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem();
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
public bool CanStep(StepType type)
{
switch (type)
{
case StepType.Into:
case StepType.Out:
case StepType.Over:
return true;
default:
return false;
}
return false;
}
[FeatureNotImplemented]
public void Step(StepType type)
{
switch (type)
{
case StepType.Into:
StepInto();
break;
case StepType.Out:
StepOut();
break;
case StepType.Over:
StepOver();
break;
}
throw new NotImplementedException();
}
public int TotalExecutedCycles => Cpu.TotalExecutedCycles;
private void StepInto()
{
do
{
CycleAdvance();
} while (!Cpu.AtStart);
}
private void StepOver()
{
var instruction = Cpu.PeekMemory(Cpu.PC);
if (instruction == JSR)
{
var destination = Cpu.PC + opsize[JSR];
while (Cpu.PC != destination)
{
StepInto();
}
}
else
{
StepInto();
}
}
private void StepOut()
{
var instruction = Cpu.PeekMemory(Cpu.PC);
JSRCount = instruction == JSR ? 1 : 0;
var bailOutFrame = Frame + 1;
while (true)
{
StepInto();
var instr = Cpu.PeekMemory(Cpu.PC);
if (instr == JSR)
{
JSRCount++;
}
else if (instr == RTS && JSRCount <= 0)
{
StepInto();
JSRCount = 0;
break;
}
else if (instr == RTS)
{
JSRCount--;
}
else // Emergency bail out logic
{
if (Frame == bailOutFrame)
{
break;
}
}
}
}
private int JSRCount = 0;
private const byte JSR = 0x20;
@ -212,22 +133,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
#region Currently Unused Debug hooks
private void ScanlineAdvance()
{
StartFrameCond();
int currentLine = _tia.LineCount;
while (_tia.LineCount == currentLine)
Cycle();
FinishFrameCond();
}
private void CycleAdvance()
{
StartFrameCond();
Cycle();
FinishFrameCond();
}
private int CurrentScanLine
{
get { return _tia.LineCount; }

View File

@ -1,4 +1,5 @@
using BizHawk.Emulation.Common;
using System;
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
@ -12,18 +13,56 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
_controller = controller;
StartFrameCond();
while (_tia.LineCount < _tia.NominalNumScanlines)
_frame++;
_islag = true;
// Handle all the console controls here
if (_controller.IsPressed("Power"))
{
HardReset();
}
if (_controller.IsPressed("Toggle Left Difficulty") && !_leftDifficultySwitchHeld)
{
_leftDifficultySwitchPressed ^= true;
_leftDifficultySwitchHeld = true;
}
else if (!_controller.IsPressed("Toggle Left Difficulty"))
{
_leftDifficultySwitchHeld = false;
}
if (_controller.IsPressed("Toggle Right Difficulty") && !_rightDifficultySwitchHeld)
{
_rightDifficultySwitchPressed ^= true;
_rightDifficultySwitchHeld = true;
}
else if (!_controller.IsPressed("Toggle Right Difficulty"))
{
_rightDifficultySwitchHeld = false;
}
int count = 0;
while (!_tia.New_Frame)
{
Cycle();
count++;
if (count > 1000000) { throw new Exception("ERROR: Unable to resolve Frame. Please Report."); }
}
_tia.New_Frame = false;
if (rendersound == false)
{
_tia.AudioClocks = 0; // we need this here since the async sound provider won't check in this case
}
FinishFrameCond();
if (_islag)
{
_lagcount++;
}
_tia.LineCount = 0;
}
public int Frame => _frame;

View File

@ -46,7 +46,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("Lag", ref _lagcount);
ser.Sync("Frame", ref _frame);
ser.Sync("IsLag", ref _islag);
ser.Sync("frameStartPending", ref _frameStartPending);
ser.Sync("cyc_counter", ref cyc_counter);
ser.Sync("leftDifficultySwitchPressed", ref _leftDifficultySwitchPressed);
ser.Sync("rightDifficultySwitchPressed", ref _rightDifficultySwitchPressed);
ser.Sync("leftDifficultySwitchHeld", ref _leftDifficultySwitchHeld);

View File

@ -41,7 +41,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
if (Rom.HashSHA1() == "3A77DB43B6583E8689435F0F14AA04B9E57BDDED" ||
Rom.HashSHA1() == "E986E1818E747BEB9B33CE4DFF1CDC6B55BDB620")
Rom.HashSHA1() == "E986E1818E747BEB9B33CE4DFF1CDC6B55BDB620" ||
Rom.HashSHA1() == "982B8016B393A9AA7DD110295A53C4612ECF2141")
{
game.RemoveOption("m");
game.AddOption("m", "F8_sega");
@ -102,18 +103,25 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// give the emu a minimal of input\output connections so it doesn't crash
var comm = new CoreComm(null, null);
// here we advance past start up irregularities to see how long a frame is based on calls to Vsync
// we run 72 frames, then run 270 scanlines worth of cycles.
// if we don't hit a new frame, we can be pretty confident we are in PAL
using (Atari2600 emu = new Atari2600(new CoreComm(null, null), newgame, rom, null, null))
{
List<int> framecounts = new List<int>();
emu._tia.FrameEndCallBack = (i) => framecounts.Add(i);
for (int i = 0; i < 71; i++) // run for 71 * 262 lines, since we're in NTSC mode
for (int i = 0; i < 72; i++)
{
emu.FrameAdvance(NullController.Instance, false, false);
}
int numpal = framecounts.Count((i) => i > 287);
bool pal = numpal >= 25;
Console.WriteLine("PAL Detection: {0} lines, {1}", numpal, pal);
for (int i = 0; i < 61560; i++)
{
emu.Cycle();
}
bool pal = !emu._tia.New_Frame;
Console.WriteLine("PAL Detection: {0}", pal);
return pal;
}
}

View File

@ -35,6 +35,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_spf = _vsyncNum / (double)_vsyncDen > 55.0 ? 735 : 882;
}
// indicates to the core where a new frame is starting
public bool New_Frame = false;
private const int BackColor = unchecked((int)0xff000000);
private const int ScreenWidth = 160;
private const int MaxScreenHeight = 312;
@ -161,11 +164,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
/// </summary>
public int LineCount { get; set; }
/// <summary>
/// Gets or sets a callback that is called at the end of a video frame. used internally
/// </summary>
public Action<int> FrameEndCallBack { private get; set; }
public void Reset()
{
_hsyncCnt = 0;
@ -229,11 +227,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
// Execute TIA cycles
public void Execute(int cycles)
public void Execute()
{
// Still ignoring cycles...
// delay vblank latch
// Handle all of the Latch delays that occur in the TIA
if (_vblankDelay > 0)
{
_vblankDelay++;
@ -244,7 +240,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
// delay latch to new playfield register
if (_pf0Updater)
{
_pf0DelayClock++;
@ -275,7 +270,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
// delay latch to missile enable
if (_enam0Delay > 0)
{
_enam0Delay++;
@ -296,7 +290,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
// delay latch to ball enable
if (_enambDelay > 0)
{
_enambDelay++;
@ -307,7 +300,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
// delay latch to player graphics registers
if (_prg0Delay > 0)
{
_prg0Delay++;
@ -333,7 +325,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
// HMP write delay
if (_hmp0Delay > 0)
{
_hmp0Delay++;
@ -773,9 +764,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// do the audio sampling
if (_hsyncCnt == 36 || _hsyncCnt == 148)
{
LocalAudioCycles[AudioClocks] += (short)(AUD[0].Cycle() / 2);
LocalAudioCycles[AudioClocks] += (short)(AUD[1].Cycle() / 2);
AudioClocks++;
if (AudioClocks < 2000)
{
LocalAudioCycles[AudioClocks] += (short)(AUD[0].Cycle() / 2);
LocalAudioCycles[AudioClocks] += (short)(AUD[1].Cycle() / 2);
AudioClocks++;
}
}
// Increment the hsync counter
@ -796,7 +790,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
int topLine = _pal ? _core.Settings.PALTopLine : _core.Settings.NTSCTopLine;
int bottomLine = _pal ? _core.Settings.PALBottomLine : _core.Settings.NTSCBottomLine;
// if vsync occured unexpectedly early, black out the remainer
// if vsync occured unexpectedly early, black out the remainder
for (; validlines < bottomLine; validlines++)
{
for (int i = 0; i < 160; i++)
@ -972,7 +966,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// write to frame buffer
OutputFrame(_currentScanLine);
FrameEndCallBack?.Invoke(_currentScanLine);
New_Frame = true;
// Clear all from last frame
_currentScanLine = 0;
@ -1337,17 +1331,5 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
AUDC, AUDF, AUDV
}
private int _frameStartCycles, _frameEndCycles;
public void BeginAudioFrame()
{
_frameStartCycles = _core.Cpu.TotalExecutedCycles;
}
public void CompleteAudioFrame()
{
_frameEndCycles = _core.Cpu.TotalExecutedCycles;
}
}
}

View File

@ -62,10 +62,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("vblankEnabled", ref _vblankEnabled);
ser.Sync("vsyncEnabled", ref _vsyncEnabled);
ser.Sync("CurrentScanLine", ref _currentScanLine);
ser.Sync("scanlinebuffer", ref _scanlinebuffer, false);
ser.Sync("AudioClocks", ref AudioClocks);
ser.Sync("FrameStartCycles", ref _frameStartCycles);
ser.Sync("FrameEndCycles", ref _frameEndCycles);
ser.Sync("New_Frame", ref New_Frame);
ser.BeginSection("Player0");
_player0.SyncState(ser);

View File

@ -54,7 +54,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
}
}
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem();
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
public bool CanStep(StepType type)
{

View File

@ -268,7 +268,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
private void ExecFetch(ushort addr)
{
MemoryCallbacks.CallExecutes(addr);
MemoryCallbacks.CallExecutes(addr, "System Bus");
}
private void Reset_Mapper(string m)

View File

@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
public byte ReadMemory(ushort addr)
{
MemoryCallbacks.CallReads(addr);
MemoryCallbacks.CallReads(addr, "System Bus");
if ((addr & 0xFCE0) == 0)
{
@ -100,7 +100,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
public void WriteMemory(ushort addr, byte value)
{
MemoryCallbacks.CallWrites(addr);
MemoryCallbacks.CallWrites(addr, "System Bus");
if ((addr & 0xFCE0) == 0)
{

View File

@ -169,7 +169,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
BoolButtons = { "Up", "Down", "Left", "Right", "A", "B", "Option 1", "Option 2", "Pause", "Power" },
};
public ControllerDefinition ControllerDefinition { get { return LynxTroller; } }
public ControllerDefinition ControllerDefinition => LynxTroller;
private LibLynx.Buttons GetButtons(IController controller)
{

View File

@ -30,6 +30,10 @@ namespace BizHawk.Emulation.Cores.ColecoVision
Name = "ColecoVision Basic Controller",
BoolButtons = Port1.Definition.BoolButtons
.Concat(Port2.Definition.BoolButtons)
.Concat(new[]
{
"Power", "Reset"
})
.ToList()
};

View File

@ -38,7 +38,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public byte Read(IController c, bool left_mode, int wheel)
{
return 0; // needs checking
return 0x7F; // needs checking
}
public ControllerDefinition Definition { get; }

View File

@ -12,36 +12,36 @@ namespace BizHawk.Emulation.Cores.ColecoVision
{
return new Dictionary<string, RegisterValue>
{
["A"] = _cpu.RegisterA,
["AF"] = _cpu.RegisterAF,
["B"] = _cpu.RegisterB,
["BC"] = _cpu.RegisterBC,
["C"] = _cpu.RegisterC,
["D"] = _cpu.RegisterD,
["DE"] = _cpu.RegisterDE,
["E"] = _cpu.RegisterE,
["F"] = _cpu.RegisterF,
["H"] = _cpu.RegisterH,
["HL"] = _cpu.RegisterHL,
["I"] = _cpu.RegisterI,
["IX"] = _cpu.RegisterIX,
["IY"] = _cpu.RegisterIY,
["L"] = _cpu.RegisterL,
["PC"] = _cpu.RegisterPC,
["R"] = _cpu.RegisterR,
["Shadow AF"] = _cpu.RegisterShadowAF,
["Shadow BC"] = _cpu.RegisterShadowBC,
["Shadow DE"] = _cpu.RegisterShadowDE,
["Shadow HL"] = _cpu.RegisterShadowHL,
["SP"] = _cpu.RegisterSP,
["Flag C"] = _cpu.RegisterF.Bit(0),
["Flag N"] = _cpu.RegisterF.Bit(1),
["Flag P/V"] = _cpu.RegisterF.Bit(2),
["Flag 3rd"] = _cpu.RegisterF.Bit(3),
["Flag H"] = _cpu.RegisterF.Bit(4),
["Flag 5th"] = _cpu.RegisterF.Bit(5),
["Flag Z"] = _cpu.RegisterF.Bit(6),
["Flag S"] = _cpu.RegisterF.Bit(7)
["A"] = _cpu.Regs[_cpu.A],
["AF"] = _cpu.Regs[_cpu.F] + (_cpu.Regs[_cpu.A] << 8),
["B"] = _cpu.Regs[_cpu.B],
["BC"] = _cpu.Regs[_cpu.C] + (_cpu.Regs[_cpu.B] << 8),
["C"] = _cpu.Regs[_cpu.C],
["D"] = _cpu.Regs[_cpu.D],
["DE"] = _cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8),
["E"] = _cpu.Regs[_cpu.E],
["F"] = _cpu.Regs[_cpu.F],
["H"] = _cpu.Regs[_cpu.H],
["HL"] = _cpu.Regs[_cpu.L] + (_cpu.Regs[_cpu.H] << 8),
["I"] = _cpu.Regs[_cpu.I],
["IX"] = _cpu.Regs[_cpu.Ixl] + (_cpu.Regs[_cpu.Ixh] << 8),
["IY"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8),
["L"] = _cpu.Regs[_cpu.L],
["PC"] = _cpu.Regs[_cpu.PCl] + (_cpu.Regs[_cpu.PCh] << 8),
["R"] = _cpu.Regs[_cpu.R],
["Shadow AF"] = _cpu.Regs[_cpu.F_s] + (_cpu.Regs[_cpu.A_s] << 8),
["Shadow BC"] = _cpu.Regs[_cpu.C_s] + (_cpu.Regs[_cpu.B_s] << 8),
["Shadow DE"] = _cpu.Regs[_cpu.E_s] + (_cpu.Regs[_cpu.D_s] << 8),
["Shadow HL"] = _cpu.Regs[_cpu.L_s] + (_cpu.Regs[_cpu.H_s] << 8),
["SP"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8),
["Flag C"] = _cpu.FlagC,
["Flag N"] = _cpu.FlagN,
["Flag P/V"] = _cpu.FlagP,
["Flag 3rd"] = _cpu.Flag3,
["Flag H"] = _cpu.FlagH,
["Flag 5th"] = _cpu.Flag5,
["Flag Z"] = _cpu.FlagZ,
["Flag S"] = _cpu.FlagS
};
}
@ -52,70 +52,82 @@ namespace BizHawk.Emulation.Cores.ColecoVision
default:
throw new InvalidOperationException();
case "A":
_cpu.RegisterA = (byte)value;
_cpu.Regs[_cpu.A] = (ushort)value;
break;
case "AF":
_cpu.RegisterAF = (byte)value;
_cpu.Regs[_cpu.F] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.A] = (ushort)(value & 0xFF00);
break;
case "B":
_cpu.RegisterB = (byte)value;
_cpu.Regs[_cpu.B] = (ushort)value;
break;
case "BC":
_cpu.RegisterBC = (byte)value;
_cpu.Regs[_cpu.C] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.B] = (ushort)(value & 0xFF00);
break;
case "C":
_cpu.RegisterC = (byte)value;
_cpu.Regs[_cpu.C] = (ushort)value;
break;
case "D":
_cpu.RegisterD = (byte)value;
_cpu.Regs[_cpu.D] = (ushort)value;
break;
case "DE":
_cpu.RegisterDE = (byte)value;
_cpu.Regs[_cpu.E] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.D] = (ushort)(value & 0xFF00);
break;
case "E":
_cpu.RegisterE = (byte)value;
_cpu.Regs[_cpu.E] = (ushort)value;
break;
case "F":
_cpu.RegisterF = (byte)value;
_cpu.Regs[_cpu.F] = (ushort)value;
break;
case "H":
_cpu.RegisterH = (byte)value;
_cpu.Regs[_cpu.H] = (ushort)value;
break;
case "HL":
_cpu.RegisterHL = (byte)value;
_cpu.Regs[_cpu.L] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.H] = (ushort)(value & 0xFF00);
break;
case "I":
_cpu.RegisterI = (byte)value;
_cpu.Regs[_cpu.I] = (ushort)value;
break;
case "IX":
_cpu.RegisterIX = (byte)value;
_cpu.Regs[_cpu.Ixl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.Ixh] = (ushort)(value & 0xFF00);
break;
case "IY":
_cpu.RegisterIY = (byte)value;
_cpu.Regs[_cpu.Iyl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.Iyh] = (ushort)(value & 0xFF00);
break;
case "L":
_cpu.RegisterL = (byte)value;
_cpu.Regs[_cpu.L] = (ushort)value;
break;
case "PC":
_cpu.RegisterPC = (ushort)value;
_cpu.Regs[_cpu.PCl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.PCh] = (ushort)(value & 0xFF00);
break;
case "R":
_cpu.RegisterR = (byte)value;
_cpu.Regs[_cpu.R] = (ushort)value;
break;
case "Shadow AF":
_cpu.RegisterShadowAF = (byte)value;
_cpu.Regs[_cpu.F_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.A_s] = (ushort)(value & 0xFF00);
break;
case "Shadow BC":
_cpu.RegisterShadowBC = (byte)value;
_cpu.Regs[_cpu.C_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.B_s] = (ushort)(value & 0xFF00);
break;
case "Shadow DE":
_cpu.RegisterShadowDE = (byte)value;
_cpu.Regs[_cpu.E_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.D_s] = (ushort)(value & 0xFF00);
break;
case "Shadow HL":
_cpu.RegisterShadowHL = (byte)value;
_cpu.Regs[_cpu.L_s] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.H_s] = (ushort)(value & 0xFF00);
break;
case "SP":
_cpu.RegisterSP = (byte)value;
_cpu.Regs[_cpu.SPl] = (ushort)(value & 0xFF);
_cpu.Regs[_cpu.SPh] = (ushort)(value & 0xFF00);
break;
}
}

View File

@ -12,16 +12,30 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public void FrameAdvance(IController controller, bool render, bool renderSound)
{
_controller = controller;
_cpu.Debug = _tracer.Enabled;
// NOTE: Need to research differences between reset and power cycle
if (_controller.IsPressed("Power"))
{
HardReset();
}
if (_controller.IsPressed("Reset"))
{
SoftReset();
}
_frame++;
_isLag = true;
PSG.BeginFrame(_cpu.TotalExecutedCycles);
if (_cpu.Debug && _cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first
if (_tracer.Enabled)
{
_cpu.Logger = (s) => _tracer.Put(s);
_cpu.TraceCallback = s => _tracer.Put(s);
}
else
{
_cpu.TraceCallback = null;
}
byte tempRet1 = ControllerDeck.ReadPort1(controller, true, true);
byte tempRet2 = ControllerDeck.ReadPort2(controller, true, true);

View File

@ -7,53 +7,52 @@ namespace BizHawk.Emulation.Cores.ColecoVision
{
public partial class ColecoVision : IStatable
{
public bool BinarySaveStatesPreferred => false;
public bool BinarySaveStatesPreferred
{
get { return true; }
}
public void SaveStateText(TextWriter writer)
{
SyncState(new Serializer(writer));
}
public void LoadStateText(TextReader reader)
{
SyncState(new Serializer(reader));
}
public void SaveStateBinary(BinaryWriter bw)
{
SyncState(Serializer.CreateBinaryWriter(bw));
SyncState(new Serializer(bw));
}
public void LoadStateBinary(BinaryReader br)
{
SyncState(Serializer.CreateBinaryReader(br));
}
public void SaveStateText(TextWriter tw)
{
SyncState(Serializer.CreateTextWriter(tw));
}
public void LoadStateText(TextReader tr)
{
SyncState(Serializer.CreateTextReader(tr));
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
if (_stateBuffer == null)
{
var stream = new MemoryStream();
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
_stateBuffer = stream.ToArray();
writer.Close();
return _stateBuffer;
}
else
{
var stream = new MemoryStream(_stateBuffer);
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Close();
return _stateBuffer;
}
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
ser.BeginSection("Coleco");
byte[] core = null;
if (ser.IsWriter)
{
var ms = new MemoryStream();
ms.Close();
core = ms.ToArray();
}
_cpu.SyncState(ser);
ser.BeginSection("Coleco");
_vdp.SyncState(ser);
PSG.SyncState(ser);
ser.Sync("RAM", ref _ram, false);

View File

@ -1,6 +1,6 @@
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components;
using BizHawk.Emulation.Cores.Components.Z80;
using BizHawk.Emulation.Cores.Components.Z80A;
namespace BizHawk.Emulation.Cores.ColecoVision
{
@ -17,13 +17,14 @@ namespace BizHawk.Emulation.Cores.ColecoVision
{
var ser = new BasicServiceProvider(this);
ServiceProvider = ser;
MemoryCallbacks = new MemoryCallbackSystem();
MemoryCallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
CoreComm = comm;
_syncSettings = (ColecoSyncSettings)syncSettings ?? new ColecoSyncSettings();
bool skipbios = _syncSettings.SkipBiosIntro;
_cpu = new Z80A
{
FetchMemory = ReadMemory,
ReadMemory = ReadMemory,
WriteMemory = WriteMemory,
ReadHardware = ReadPort,
@ -53,7 +54,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
SetupMemoryDomains();
_tracer.Header = _cpu.TraceHeader;
ser.Register<IDisassemblable>(new Disassembler());
ser.Register<IDisassemblable>(_cpu);
ser.Register<ITraceable>(_tracer);
}
@ -223,5 +224,17 @@ namespace BizHawk.Emulation.Cores.ColecoVision
////Console.WriteLine("Unhandled write at {0:X4}:{1:X2}", addr, value);
}
private void HardReset()
{
PSG.Reset();
_cpu.Reset();
}
private void SoftReset()
{
PSG.Reset();
_cpu.Reset();
}
}
}
}

View File

@ -2,7 +2,7 @@
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components.Z80;
using BizHawk.Emulation.Cores.Components.Z80A;
namespace BizHawk.Emulation.Cores.ColecoVision
{
@ -54,14 +54,17 @@ namespace BizHawk.Emulation.Cores.ColecoVision
Cpu.NonMaskableInterrupt = true;
}
Cpu.ExecuteCycles(228);
Cpu.Interrupt = false;
for (int i = 0; i < 228; i++)
{
Cpu.ExecuteOne();
}
Cpu.FlagI = false;
if (Int_pending && scanLine==50)
{
if (EnableInterrupts)
{
Cpu.Interrupt = true;
Cpu.FlagI = true;
Int_pending = false;
}
}

View File

@ -82,7 +82,7 @@ namespace BizHawk.Emulation.Cores.Intellivision
}
}
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem();
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
public bool CanStep(StepType type)
{

View File

@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
return false;
}
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem();
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
public IMemoryCallbackSystem MemoryCallbacks => _memorycallbacks;
[FeatureNotImplemented]

View File

@ -166,9 +166,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
void InitCallbacks()
{
padcb = new LibVBANext.StandardCallback(() => InputCallbacks.Call());
fetchcb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallExecutes(addr));
readcb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallReads(addr));
writecb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallWrites(addr));
fetchcb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallExecutes(addr, "System Bus"));
readcb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallReads(addr, "System Bus"));
writecb = new LibVBANext.AddressCallback((addr) => MemoryCallbacks.CallWrites(addr, "System Bus"));
tracecb = new LibVBANext.TraceCallback((addr, opcode) => Tracer.Put(Trace(addr, opcode)));
_inputCallbacks.ActiveChanged += SyncPadCallback;
_memorycallbacks.ActiveChanged += SyncMemoryCallbacks;

View File

@ -56,7 +56,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
private LibGambatte.MemoryCallback _writecb;
private LibGambatte.MemoryCallback _execcb;
private MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem();
private MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
/// <summary>
/// for use in dual core
@ -68,9 +68,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
private void InitMemoryCallbacks()
{
_readcb = addr => MemoryCallbacks.CallReads(addr);
_writecb = addr => MemoryCallbacks.CallWrites(addr);
_execcb = addr => MemoryCallbacks.CallExecutes(addr);
_readcb = addr => MemoryCallbacks.CallReads(addr, "System Bus");
_writecb = addr => MemoryCallbacks.CallWrites(addr, "System Bus");
_execcb = addr => MemoryCallbacks.CallExecutes(addr, "System Bus");
_memorycallbacks.ActiveChanged += RefreshMemoryCallbacks;
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
public partial class Gameboy : ILinkable
{
public bool LinkConnected { get; private set; }
}
}

View File

@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[ServiceNotApplicable(typeof(IDriveLight), typeof(IDriveLight))]
public partial class Gameboy : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable, ICodeDataLogger,
IBoardInfo, IDebuggable, ISettable<Gameboy.GambatteSettings, Gameboy.GambatteSyncSettings>,
IGameboyCommon, ICycleTiming
IGameboyCommon, ICycleTiming, ILinkable
{
[CoreConstructor("GB", "GBC")]
public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, object syncSettings, bool deterministic)
@ -513,9 +513,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
if (callback != null)
{
printer = new GambattePrinter(this, callback);
LinkConnected = true;
}
else
{
LinkConnected = false;
printer.Disconnect();
printer = null;
}

View File

@ -50,6 +50,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
get { throw new NotImplementedException(); }
}
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem();
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
}
}

View File

@ -64,7 +64,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
{
Filename = "sameboy.wbx",
SbrkHeapSizeKB = 192,
InvisibleHeapSizeKB = 4,
InvisibleHeapSizeKB = 12,
SealedHeapSizeKB = 9 * 1024,
PlainHeapSizeKB = 4,
MmapHeapSizeKB = 1024
@ -300,6 +300,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
protected override void LoadStateBinaryInternal(BinaryReader reader)
{
UpdateCoreScanlineCallback(false);
_core.SetPrinterCallback(_printerCallback);
}
public bool IsCGBMode() => _cgb;

View File

@ -82,7 +82,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
get { return _memorycallbacks; }
}
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem();
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
public bool CanStep(StepType type)
{

View File

@ -759,13 +759,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
switch (_breakparams._type)
{
case BreakType.Read:
_breakparams._mcs.CallReads(_breakparams._addr);
_breakparams._mcs.CallReads(_breakparams._addr, "System Bus");
break;
case BreakType.Write:
_breakparams._mcs.CallWrites(_breakparams._addr);
_breakparams._mcs.CallWrites(_breakparams._addr, "System Bus");
break;
case BreakType.Execute:
_breakparams._mcs.CallExecutes(_breakparams._addr);
_breakparams._mcs.CallExecutes(_breakparams._addr, "System Bus");
break;
}

View File

@ -20,13 +20,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
public sealed class APU
{
public static bool CFG_DECLICK = true;
public int Square1V = 376;
public int Square2V = 376;
public int TriangleV = 426;
public int NoiseV = 247;
public int DMCV = 167;
public int m_vol = 1;
public int dmc_dma_countdown = -1;
public bool call_from_write;
@ -53,11 +47,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
pulse[1] = new PulseUnit(this, 1);
if (old != null)
{
Square1V = old.Square1V;
Square2V = old.Square2V;
TriangleV = old.TriangleV;
NoiseV = old.NoiseV;
DMCV = old.DMCV;
m_vol = old.m_vol;
}
}
@ -1338,8 +1328,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
SyncIRQ();
nes.irq_apu = irq_pending;
// since the units run concurrently, the APU frame sequencer is ran last because
// it can change the ouput values of the pulse/triangle channels
// we want the changes to affect it on the *next* cycle.
@ -1419,7 +1408,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
float output = pulse_out + tnd_out;
// output = output * 2 - 1;
// this needs to leave enough headroom for straying DC bias due to the DMC unit getting stuck outputs. smb3 is bad about that.
int mix = (int)(20000 * output);
int mix = (int)(20000 * output * (1 + m_vol/5));
dlist.Add(new Delta(sampleclock, mix - oldmix));
oldmix = mix;

View File

@ -1,5 +1,6 @@
using BizHawk.Common;
using BizHawk.Common.NumberExtensions;
using System;
namespace BizHawk.Emulation.Cores.Nintendo.NES
{
@ -108,6 +109,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
cheetahmen = true;
}
else
{
prg_bank_mask_16k = 0x1F;
prg_bank_mask_32k = 0xF;
}
AutoMapperProps.Apply(this);
@ -155,6 +161,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//$8000-FFFF: [.... ..CC] Low 2 bits of CHR
//A~[..MH HPPP PPO. CCCC]
addr += 0x8000;
if (addr.Bit(13))
{
SetMirrorType(EMirrorType.Horizontal);
@ -173,7 +181,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
switch (chip)
{
case 0:
chip_offset = 0;
chip_offset = 0x0;
break;
case 1:
chip_offset = 0x80000;
@ -201,7 +209,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (prg_mode == false)
{
int bank = (prg_reg >> 1) & prg_bank_mask_32k;
return ROM[(bank * 0x8000) + addr];
return ROM[(bank * 0x8000) + addr + chip_offset];
}
else
{

View File

@ -0,0 +1,107 @@
using BizHawk.Common;
using System;
namespace BizHawk.Emulation.Cores.Nintendo.NES
{
// Mapper for Aladdin Super Game
public sealed class Mapper114 : MMC3Board_Base
{
private ByteBuffer EXPREGS = new ByteBuffer(2);
private int prg_mask_16;
private byte[] sec = { 0, 3, 1, 5, 6, 7, 2, 4 };
public override bool Configure(NES.EDetectionOrigin origin)
{
switch (Cart.board_type)
{
case "MAPPER114":
break;
default:
return false;
}
BaseSetup();
SetMirrorType(EMirrorType.Horizontal);
mmc3.MMC3Type = MMC3.EMMC3Type.MMC3A;
prg_mask_16 = Cart.prg_size / 16 - 1;
return true;
}
public override void Dispose()
{
EXPREGS.Dispose();
base.Dispose();
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("expregs", ref EXPREGS);
}
public override void WriteEXP(int addr, byte value)
{
if ((addr & 0x7) == 0 && addr >= 0x1000)
{
EXPREGS[0] = value;
}
}
public override void WriteWRAM(int addr, byte value)
{
if ((addr & 0x7) == 0)
{
EXPREGS[0] = value;
}
}
public override void WritePRG(int addr, byte value)
{
switch (addr & 0x6000)
{
case 0x0000: //$8000
base.SetMirrorType((value & 1) == 1 ? EMirrorType.Horizontal : EMirrorType.Vertical);
break;
case 0x2000: //$A000
value = (byte)((value & 0xC0) | sec[value & 0x07]);
EXPREGS[1] = 1;
base.WritePRG(0, value);
break;
case 0x4000: //$C000
if(EXPREGS[1] == 1)
{
EXPREGS[1] = 0;
base.WritePRG(1, value);
}
break;
case 0x6000: //$E000
if (value > 0)
{
base.WritePRG(0x6001, value);
base.WritePRG(0x4000, value);
base.WritePRG(0x4001, value);
}
else
{
base.WritePRG(0x6000, value);
}
break;
}
}
public override byte ReadPRG(int addr)
{
if ((EXPREGS[0] & 0x80) > 0)
{
var bank = EXPREGS[0] & 0x1F & prg_mask_16;
return ROM[(bank << 14) + (addr & 0x3FFF)];
}
else
{
return base.ReadPRG(addr);
}
}
}
}

View File

@ -146,7 +146,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
void WriteModeControl(int addr, byte value)
{
if (((addr & 0x4100) != 0x4100) || addr>=0x4200) return;
if ((addr & 0x4100) != 0x4100) return;
mode = value & 3;
bool chr_base = value.Bit(2);

View File

@ -255,19 +255,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
case 0x0020:
timerlatch &= 0xff00;
timerlatch |= value;
//timerirq = false;
break;
case 0x0021:
timerlatch &= 0x00ff;
timerlatch |= value << 8;
//timerirq = false;
break;
case 0x0022:
timerreg = (byte)(value & 3);
timervalue = timerlatch;
if (diskenable)
{
timerreg = (byte)(value & 3);
if ((value & 0x02) == 0x02)
{
timervalue = timerlatch;
}
else
{
_timerirq = false;
}
}
break;
case 0x0023:
diskenable = (value & 1) != 0;
if (!diskenable) { _timerirq = false; }
soundenable = (value & 2) != 0;
break;
case 0x0024:
@ -344,7 +354,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public override void ClockCPU()
{
if ((timerreg & 2) != 0)// && timervalue > 0)
if ((timerreg & 2) != 0 && diskenable)
{
if (timervalue!=0)
{
@ -352,22 +362,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
if (timervalue == 0)
{
/*
if ((timerreg & 1) != 0)
{
timervalue = timerlatch;
//timervalue = 0xFFFF;
}
else
{
timerreg &= unchecked((byte)~2);
timervalue = 0;
timerlatch = 0;
}
*/
timervalue = timerlatch;
timerirq = true;
if ((timerreg & 1) == 0)
{
timerreg -= 2;
}
}
}
audio.Clock();

View File

@ -67,14 +67,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
byte[] fileheader = br.ReadBytes(16);
if (fileheader[0] != 0x03)
{
throw new Exception("Corrupt FDS block 3");
// Instead of exceptions, display strong warnings
Console.WriteLine("WARNING: INVALID FILE, BLOCK 3 ERROR");
//throw new Exception("Corrupt FDS block 3");
}
int filesize = fileheader[13] + fileheader[14] * 256;
byte[] file = br.ReadBytes(filesize + 1);
if (file[0] != 0x04)
{
throw new Exception("Corrupt FDS block 4");
Console.WriteLine("WARNING: INVALID FILE, BLOCK 4 ERROR");
//throw new Exception("Corrupt FDS block 4");
}
WriteBlock(ret, fileheader, 122);

Some files were not shown because too many files have changed in this diff Show More