Some fixes and code refactoring
This commit is contained in:
@@ -25,10 +25,12 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
public int InterruptMode { get; private set; } = 0;
|
public int InterruptMode { get; private set; } = 0;
|
||||||
|
|
||||||
|
|
||||||
// Interrupt Flip-Flops
|
// Interrupt Flip-Flops
|
||||||
public bool IFF1 { get; private set; } = false;
|
public bool IFF1 { get; private set; } = false;
|
||||||
public bool IFF2 { get; private set; } = false;
|
public bool IFF2 { get; private set; } = false;
|
||||||
public bool InterruptRequested { get; private set; } = false;
|
public bool InterruptRequested { get; private set; } = false;
|
||||||
|
private bool _eiPending = false;
|
||||||
|
|
||||||
// Main Register Set
|
// Main Register Set
|
||||||
public RegisterPair AF;
|
public RegisterPair AF;
|
||||||
@@ -214,6 +216,7 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
public int Step()
|
public int Step()
|
||||||
{
|
{
|
||||||
|
bool triggerEi = _eiPending;
|
||||||
|
|
||||||
// Fetch the next opcode and increment the Program Counter
|
// Fetch the next opcode and increment the Program Counter
|
||||||
byte opcode = ReadMemory(PC++);
|
byte opcode = ReadMemory(PC++);
|
||||||
@@ -221,6 +224,13 @@ namespace Core.Cpu
|
|||||||
int tStates = ExecuteOpcode(opcode);
|
int tStates = ExecuteOpcode(opcode);
|
||||||
TotalTStates += tStates;
|
TotalTStates += tStates;
|
||||||
|
|
||||||
|
if (triggerEi)
|
||||||
|
{
|
||||||
|
IFF1 = true;
|
||||||
|
IFF2 = true;
|
||||||
|
_eiPending = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Decode and execute
|
// Decode and execute
|
||||||
return tStates;
|
return tStates;
|
||||||
}
|
}
|
||||||
@@ -240,9 +250,6 @@ namespace Core.Cpu
|
|||||||
$"C:{f & 1}";
|
$"C:{f & 1}";
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
|
||||||
// MATH AND LOGIC HELPERS
|
|
||||||
// =========================================================================
|
|
||||||
|
|
||||||
private void SubA(byte value, bool isCompare)
|
private void SubA(byte value, bool isCompare)
|
||||||
{
|
{
|
||||||
@@ -1272,6 +1279,7 @@ namespace Core.Cpu
|
|||||||
case 0xF3: // DI
|
case 0xF3: // DI
|
||||||
IFF1 = false;
|
IFF1 = false;
|
||||||
IFF2 = false;
|
IFF2 = false;
|
||||||
|
_eiPending = false;
|
||||||
return 4;
|
return 4;
|
||||||
case 0xf5: //push af
|
case 0xf5: //push af
|
||||||
Push(AF.Word);
|
Push(AF.Word);
|
||||||
@@ -1283,8 +1291,7 @@ namespace Core.Cpu
|
|||||||
SP = HL.Word;
|
SP = HL.Word;
|
||||||
return 6;
|
return 6;
|
||||||
case 0xFB: // EI
|
case 0xFB: // EI
|
||||||
IFF1 = true;
|
_eiPending = true;
|
||||||
IFF2 = true;
|
|
||||||
return 4;
|
return 4;
|
||||||
case 0xFD:
|
case 0xFD:
|
||||||
return ExecuteFDPrefix();
|
return ExecuteFDPrefix();
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ namespace Core.Memory
|
|||||||
|
|
||||||
public byte Read(ushort address)
|
public byte Read(ushort address)
|
||||||
{
|
{
|
||||||
|
if (address < 0xC000 && !_isCartridgeLoaded)
|
||||||
|
{
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
if (address < 0x4000)
|
if (address < 0x4000)
|
||||||
{
|
{
|
||||||
if (address < 0x0400)
|
if (address < 0x0400)
|
||||||
@@ -65,7 +70,7 @@ namespace Core.Memory
|
|||||||
return _cartridgeRom[(_romBank2 * 0x4000) + (address - 0x8000)];
|
return _cartridgeRom[(_romBank2 * 0x4000) + (address - 0x8000)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// THE FIX 1: Bitwise AND perfectly forces 0xE000-0xFFFF to mirror down to 0xC000!
|
// Bitwise AND perfectly forces 0xE000-0xFFFF to mirror down to 0xC000!
|
||||||
return _workRam[address & 0x1FFF];
|
return _workRam[address & 0x1FFF];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Core.Video
|
|||||||
_isSecondControlByte = false; // Reading data resets the control latch
|
_isSecondControlByte = false; // Reading data resets the control latch
|
||||||
byte value = _readBuffer;
|
byte value = _readBuffer;
|
||||||
_readBuffer = VRAM[_controlWord & 0x3FFF];
|
_readBuffer = VRAM[_controlWord & 0x3FFF];
|
||||||
_controlWord++;
|
IncrementVdpAddress();
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ namespace Core.Video
|
|||||||
}
|
}
|
||||||
|
|
||||||
// THE FIX: The pointer MUST auto-increment so the CPU can blast data fast!
|
// THE FIX: The pointer MUST auto-increment so the CPU can blast data fast!
|
||||||
_controlWord++;
|
IncrementVdpAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteControlPort(byte value) // Port 0xBF
|
public void WriteControlPort(byte value) // Port 0xBF
|
||||||
@@ -104,7 +104,7 @@ namespace Core.Video
|
|||||||
if (command == 0) // Code 0: Prep for VRAM Read
|
if (command == 0) // Code 0: Prep for VRAM Read
|
||||||
{
|
{
|
||||||
_readBuffer = VRAM[_controlWord & 0x3FFF];
|
_readBuffer = VRAM[_controlWord & 0x3FFF];
|
||||||
_controlWord++;
|
IncrementVdpAddress();
|
||||||
}
|
}
|
||||||
else if (command == 2) // Code 2: Write to Internal VDP Register
|
else if (command == 2) // Code 2: Write to Internal VDP Register
|
||||||
{
|
{
|
||||||
@@ -116,6 +116,18 @@ namespace Core.Video
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void IncrementVdpAddress()
|
||||||
|
{
|
||||||
|
// The VDP address register is only 14 bits
|
||||||
|
// When it increments past 0x3FFF, it rolls over to 0x0000.
|
||||||
|
// It can't overflow and corrupt the 2-bit command register (bits 14 and 15).
|
||||||
|
ushort address = (ushort)(_controlWord & 0x3FFF);
|
||||||
|
ushort command = (ushort)(_controlWord & 0xC000);
|
||||||
|
|
||||||
|
address = (ushort)((address + 1) & 0x3FFF);
|
||||||
|
_controlWord = (ushort)(command | address);
|
||||||
|
}
|
||||||
|
|
||||||
public byte ReadVCounter()
|
public byte ReadVCounter()
|
||||||
{
|
{
|
||||||
// NTSC Math: 262 lines. Counts 0 to 218, jumps to 213 (0xD5), counts to 255.
|
// NTSC Math: 262 lines. Counts 0 to 218, jumps to 213 (0xD5), counts to 255.
|
||||||
|
|||||||
211
Desktop/DebuggerForm.Designer.cs
generated
211
Desktop/DebuggerForm.Designer.cs
generated
@@ -56,102 +56,102 @@
|
|||||||
lblFPS = new Label();
|
lblFPS = new Label();
|
||||||
lblFrameTime = new Label();
|
lblFrameTime = new Label();
|
||||||
richTextBox1 = new RichTextBox();
|
richTextBox1 = new RichTextBox();
|
||||||
button1 = new Button();
|
btnCpuStep = new Button();
|
||||||
CpuRun = new Button();
|
CpuRun = new Button();
|
||||||
groupBox1 = new GroupBox();
|
groupBox1 = new GroupBox();
|
||||||
lblTone0 = new Label();
|
|
||||||
lblNoise = new Label();
|
|
||||||
lblTone2 = new Label();
|
|
||||||
lblTone1 = new Label();
|
lblTone1 = new Label();
|
||||||
|
lblTone2 = new Label();
|
||||||
|
lblNoise = new Label();
|
||||||
|
lblTone0 = new Label();
|
||||||
groupBox1.SuspendLayout();
|
groupBox1.SuspendLayout();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// lblAF
|
// lblAF
|
||||||
//
|
//
|
||||||
lblAF.AutoSize = true;
|
lblAF.AutoSize = true;
|
||||||
lblAF.Location = new Point(12, 9);
|
lblAF.Location = new Point(10, 7);
|
||||||
lblAF.Margin = new Padding(2, 0, 2, 0);
|
lblAF.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblAF.Name = "lblAF";
|
lblAF.Name = "lblAF";
|
||||||
lblAF.Size = new Size(33, 25);
|
lblAF.Size = new Size(26, 20);
|
||||||
lblAF.TabIndex = 0;
|
lblAF.TabIndex = 0;
|
||||||
lblAF.Text = "AF";
|
lblAF.Text = "AF";
|
||||||
//
|
//
|
||||||
// lblBC
|
// lblBC
|
||||||
//
|
//
|
||||||
lblBC.AutoSize = true;
|
lblBC.AutoSize = true;
|
||||||
lblBC.Location = new Point(11, 60);
|
lblBC.Location = new Point(9, 48);
|
||||||
lblBC.Margin = new Padding(2, 0, 2, 0);
|
lblBC.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblBC.Name = "lblBC";
|
lblBC.Name = "lblBC";
|
||||||
lblBC.Size = new Size(33, 25);
|
lblBC.Size = new Size(27, 20);
|
||||||
lblBC.TabIndex = 1;
|
lblBC.TabIndex = 1;
|
||||||
lblBC.Text = "BC";
|
lblBC.Text = "BC";
|
||||||
//
|
//
|
||||||
// lblDE
|
// lblDE
|
||||||
//
|
//
|
||||||
lblDE.AutoSize = true;
|
lblDE.AutoSize = true;
|
||||||
lblDE.Location = new Point(12, 125);
|
lblDE.Location = new Point(10, 100);
|
||||||
lblDE.Margin = new Padding(2, 0, 2, 0);
|
lblDE.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblDE.Name = "lblDE";
|
lblDE.Name = "lblDE";
|
||||||
lblDE.Size = new Size(34, 25);
|
lblDE.Size = new Size(28, 20);
|
||||||
lblDE.TabIndex = 2;
|
lblDE.TabIndex = 2;
|
||||||
lblDE.Text = "DE";
|
lblDE.Text = "DE";
|
||||||
//
|
//
|
||||||
// lblHL
|
// lblHL
|
||||||
//
|
//
|
||||||
lblHL.AutoSize = true;
|
lblHL.AutoSize = true;
|
||||||
lblHL.Location = new Point(12, 188);
|
lblHL.Location = new Point(10, 150);
|
||||||
lblHL.Margin = new Padding(2, 0, 2, 0);
|
lblHL.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblHL.Name = "lblHL";
|
lblHL.Name = "lblHL";
|
||||||
lblHL.Size = new Size(33, 25);
|
lblHL.Size = new Size(27, 20);
|
||||||
lblHL.TabIndex = 3;
|
lblHL.TabIndex = 3;
|
||||||
lblHL.Text = "HL";
|
lblHL.Text = "HL";
|
||||||
//
|
//
|
||||||
// lblPC
|
// lblPC
|
||||||
//
|
//
|
||||||
lblPC.AutoSize = true;
|
lblPC.AutoSize = true;
|
||||||
lblPC.Location = new Point(11, 250);
|
lblPC.Location = new Point(9, 200);
|
||||||
lblPC.Margin = new Padding(2, 0, 2, 0);
|
lblPC.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblPC.Name = "lblPC";
|
lblPC.Name = "lblPC";
|
||||||
lblPC.Size = new Size(33, 25);
|
lblPC.Size = new Size(26, 20);
|
||||||
lblPC.TabIndex = 4;
|
lblPC.TabIndex = 4;
|
||||||
lblPC.Text = "PC";
|
lblPC.Text = "PC";
|
||||||
//
|
//
|
||||||
// lblSP
|
// lblSP
|
||||||
//
|
//
|
||||||
lblSP.AutoSize = true;
|
lblSP.AutoSize = true;
|
||||||
lblSP.Location = new Point(11, 315);
|
lblSP.Location = new Point(9, 252);
|
||||||
lblSP.Margin = new Padding(2, 0, 2, 0);
|
lblSP.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblSP.Name = "lblSP";
|
lblSP.Name = "lblSP";
|
||||||
lblSP.Size = new Size(32, 25);
|
lblSP.Size = new Size(25, 20);
|
||||||
lblSP.TabIndex = 6;
|
lblSP.TabIndex = 6;
|
||||||
lblSP.Text = "SP";
|
lblSP.Text = "SP";
|
||||||
//
|
//
|
||||||
// lblFlags
|
// lblFlags
|
||||||
//
|
//
|
||||||
lblFlags.AutoSize = true;
|
lblFlags.AutoSize = true;
|
||||||
lblFlags.Location = new Point(110, 65);
|
lblFlags.Location = new Point(88, 52);
|
||||||
lblFlags.Margin = new Padding(2, 0, 2, 0);
|
lblFlags.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblFlags.Name = "lblFlags";
|
lblFlags.Name = "lblFlags";
|
||||||
lblFlags.Size = new Size(53, 25);
|
lblFlags.Size = new Size(43, 20);
|
||||||
lblFlags.TabIndex = 7;
|
lblFlags.TabIndex = 7;
|
||||||
lblFlags.Text = "Flags";
|
lblFlags.Text = "Flags";
|
||||||
//
|
//
|
||||||
// lblTStates
|
// lblTStates
|
||||||
//
|
//
|
||||||
lblTStates.AutoSize = true;
|
lblTStates.AutoSize = true;
|
||||||
lblTStates.Location = new Point(110, 9);
|
lblTStates.Location = new Point(88, 7);
|
||||||
lblTStates.Margin = new Padding(2, 0, 2, 0);
|
lblTStates.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblTStates.Name = "lblTStates";
|
lblTStates.Name = "lblTStates";
|
||||||
lblTStates.Size = new Size(75, 25);
|
lblTStates.Size = new Size(63, 20);
|
||||||
lblTStates.TabIndex = 8;
|
lblTStates.TabIndex = 8;
|
||||||
lblTStates.Text = "T-States";
|
lblTStates.Text = "T-States";
|
||||||
//
|
//
|
||||||
// txtMemoryStart
|
// txtMemoryStart
|
||||||
//
|
//
|
||||||
txtMemoryStart.Location = new Point(375, 26);
|
txtMemoryStart.Location = new Point(300, 21);
|
||||||
txtMemoryStart.Margin = new Padding(2);
|
txtMemoryStart.Margin = new Padding(2);
|
||||||
txtMemoryStart.Name = "txtMemoryStart";
|
txtMemoryStart.Name = "txtMemoryStart";
|
||||||
txtMemoryStart.Size = new Size(150, 31);
|
txtMemoryStart.Size = new Size(121, 27);
|
||||||
txtMemoryStart.TabIndex = 9;
|
txtMemoryStart.TabIndex = 9;
|
||||||
txtMemoryStart.Text = "Memory Start";
|
txtMemoryStart.Text = "Memory Start";
|
||||||
txtMemoryStart.TextAlign = HorizontalAlignment.Center;
|
txtMemoryStart.TextAlign = HorizontalAlignment.Center;
|
||||||
@@ -159,10 +159,10 @@
|
|||||||
//
|
//
|
||||||
// btnRefreshMemory
|
// btnRefreshMemory
|
||||||
//
|
//
|
||||||
btnRefreshMemory.Location = new Point(531, 26);
|
btnRefreshMemory.Location = new Point(425, 21);
|
||||||
btnRefreshMemory.Margin = new Padding(2);
|
btnRefreshMemory.Margin = new Padding(2);
|
||||||
btnRefreshMemory.Name = "btnRefreshMemory";
|
btnRefreshMemory.Name = "btnRefreshMemory";
|
||||||
btnRefreshMemory.Size = new Size(112, 34);
|
btnRefreshMemory.Size = new Size(90, 27);
|
||||||
btnRefreshMemory.TabIndex = 14;
|
btnRefreshMemory.TabIndex = 14;
|
||||||
btnRefreshMemory.Text = "Refresh Memory";
|
btnRefreshMemory.Text = "Refresh Memory";
|
||||||
btnRefreshMemory.UseVisualStyleBackColor = true;
|
btnRefreshMemory.UseVisualStyleBackColor = true;
|
||||||
@@ -170,117 +170,109 @@
|
|||||||
//
|
//
|
||||||
// txtMemoryView
|
// txtMemoryView
|
||||||
//
|
//
|
||||||
txtMemoryView.Location = new Point(110, 101);
|
txtMemoryView.Location = new Point(88, 81);
|
||||||
txtMemoryView.Margin = new Padding(2);
|
txtMemoryView.Margin = new Padding(2);
|
||||||
txtMemoryView.Name = "txtMemoryView";
|
txtMemoryView.Name = "txtMemoryView";
|
||||||
txtMemoryView.Size = new Size(553, 543);
|
txtMemoryView.Size = new Size(443, 435);
|
||||||
txtMemoryView.TabIndex = 15;
|
txtMemoryView.TabIndex = 15;
|
||||||
txtMemoryView.Text = "Memory View Window";
|
txtMemoryView.Text = "Memory View Window";
|
||||||
//
|
//
|
||||||
// lstDisassembly
|
// lstDisassembly
|
||||||
//
|
//
|
||||||
lstDisassembly.FormattingEnabled = true;
|
lstDisassembly.FormattingEnabled = true;
|
||||||
lstDisassembly.ItemHeight = 25;
|
lstDisassembly.Location = new Point(567, 8);
|
||||||
lstDisassembly.Location = new Point(709, 10);
|
|
||||||
lstDisassembly.Margin = new Padding(2);
|
lstDisassembly.Margin = new Padding(2);
|
||||||
lstDisassembly.Name = "lstDisassembly";
|
lstDisassembly.Name = "lstDisassembly";
|
||||||
lstDisassembly.Size = new Size(314, 329);
|
lstDisassembly.Size = new Size(252, 264);
|
||||||
lstDisassembly.TabIndex = 16;
|
lstDisassembly.TabIndex = 16;
|
||||||
//
|
//
|
||||||
// lstStack
|
// lstStack
|
||||||
//
|
//
|
||||||
lstStack.FormattingEnabled = true;
|
lstStack.FormattingEnabled = true;
|
||||||
lstStack.ItemHeight = 25;
|
lstStack.Location = new Point(823, 8);
|
||||||
lstStack.Location = new Point(1029, 10);
|
|
||||||
lstStack.Margin = new Padding(2);
|
lstStack.Margin = new Padding(2);
|
||||||
lstStack.Name = "lstStack";
|
lstStack.Name = "lstStack";
|
||||||
lstStack.Size = new Size(162, 329);
|
lstStack.Size = new Size(130, 264);
|
||||||
lstStack.TabIndex = 17;
|
lstStack.TabIndex = 17;
|
||||||
//
|
//
|
||||||
// label1
|
// label1
|
||||||
//
|
//
|
||||||
label1.AutoSize = true;
|
label1.AutoSize = true;
|
||||||
label1.Location = new Point(710, 372);
|
label1.Location = new Point(568, 298);
|
||||||
label1.Margin = new Padding(4, 0, 4, 0);
|
|
||||||
label1.Name = "label1";
|
label1.Name = "label1";
|
||||||
label1.Size = new Size(97, 25);
|
label1.Size = new Size(81, 20);
|
||||||
label1.TabIndex = 19;
|
label1.TabIndex = 19;
|
||||||
label1.Text = "Breakpoint";
|
label1.Text = "Breakpoint";
|
||||||
//
|
//
|
||||||
// txtBreakpoint
|
// txtBreakpoint
|
||||||
//
|
//
|
||||||
txtBreakpoint.Location = new Point(819, 369);
|
txtBreakpoint.Location = new Point(655, 295);
|
||||||
txtBreakpoint.Margin = new Padding(4);
|
|
||||||
txtBreakpoint.Name = "txtBreakpoint";
|
txtBreakpoint.Name = "txtBreakpoint";
|
||||||
txtBreakpoint.Size = new Size(155, 31);
|
txtBreakpoint.Size = new Size(125, 27);
|
||||||
txtBreakpoint.TabIndex = 20;
|
txtBreakpoint.TabIndex = 20;
|
||||||
//
|
//
|
||||||
// label2
|
// label2
|
||||||
//
|
//
|
||||||
label2.AutoSize = true;
|
label2.AutoSize = true;
|
||||||
label2.Location = new Point(291, 26);
|
label2.Location = new Point(233, 21);
|
||||||
label2.Margin = new Padding(4, 0, 4, 0);
|
|
||||||
label2.Name = "label2";
|
label2.Name = "label2";
|
||||||
label2.Size = new Size(77, 25);
|
label2.Size = new Size(62, 20);
|
||||||
label2.TabIndex = 21;
|
label2.TabIndex = 21;
|
||||||
label2.Text = "Address";
|
label2.Text = "Address";
|
||||||
//
|
//
|
||||||
// lblIX
|
// lblIX
|
||||||
//
|
//
|
||||||
lblIX.AutoSize = true;
|
lblIX.AutoSize = true;
|
||||||
lblIX.Location = new Point(11, 372);
|
lblIX.Location = new Point(9, 298);
|
||||||
lblIX.Margin = new Padding(2, 0, 2, 0);
|
lblIX.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblIX.Name = "lblIX";
|
lblIX.Name = "lblIX";
|
||||||
lblIX.Size = new Size(28, 25);
|
lblIX.Size = new Size(22, 20);
|
||||||
lblIX.TabIndex = 22;
|
lblIX.TabIndex = 22;
|
||||||
lblIX.Text = "IX";
|
lblIX.Text = "IX";
|
||||||
//
|
//
|
||||||
// lblIY
|
// lblIY
|
||||||
//
|
//
|
||||||
lblIY.AutoSize = true;
|
lblIY.AutoSize = true;
|
||||||
lblIY.Location = new Point(12, 430);
|
lblIY.Location = new Point(10, 344);
|
||||||
lblIY.Margin = new Padding(2, 0, 2, 0);
|
lblIY.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblIY.Name = "lblIY";
|
lblIY.Name = "lblIY";
|
||||||
lblIY.Size = new Size(27, 25);
|
lblIY.Size = new Size(21, 20);
|
||||||
lblIY.TabIndex = 23;
|
lblIY.TabIndex = 23;
|
||||||
lblIY.Text = "IY";
|
lblIY.Text = "IY";
|
||||||
//
|
//
|
||||||
// lblIff1
|
// lblIff1
|
||||||
//
|
//
|
||||||
lblIff1.AutoSize = true;
|
lblIff1.AutoSize = true;
|
||||||
lblIff1.Location = new Point(11, 533);
|
lblIff1.Location = new Point(9, 426);
|
||||||
lblIff1.Margin = new Padding(4, 0, 4, 0);
|
|
||||||
lblIff1.Name = "lblIff1";
|
lblIff1.Name = "lblIff1";
|
||||||
lblIff1.Size = new Size(45, 25);
|
lblIff1.Size = new Size(35, 20);
|
||||||
lblIff1.TabIndex = 24;
|
lblIff1.TabIndex = 24;
|
||||||
lblIff1.Text = "IFF1";
|
lblIff1.Text = "IFF1";
|
||||||
//
|
//
|
||||||
// lblIff2
|
// lblIff2
|
||||||
//
|
//
|
||||||
lblIff2.AutoSize = true;
|
lblIff2.AutoSize = true;
|
||||||
lblIff2.Location = new Point(11, 586);
|
lblIff2.Location = new Point(9, 469);
|
||||||
lblIff2.Margin = new Padding(4, 0, 4, 0);
|
|
||||||
lblIff2.Name = "lblIff2";
|
lblIff2.Name = "lblIff2";
|
||||||
lblIff2.Size = new Size(45, 25);
|
lblIff2.Size = new Size(35, 20);
|
||||||
lblIff2.TabIndex = 25;
|
lblIff2.TabIndex = 25;
|
||||||
lblIff2.Text = "IFF2";
|
lblIff2.Text = "IFF2";
|
||||||
//
|
//
|
||||||
// lblIE
|
// lblIE
|
||||||
//
|
//
|
||||||
lblIE.AutoSize = true;
|
lblIE.AutoSize = true;
|
||||||
lblIE.Location = new Point(11, 486);
|
lblIE.Location = new Point(9, 389);
|
||||||
lblIE.Margin = new Padding(4, 0, 4, 0);
|
|
||||||
lblIE.Name = "lblIE";
|
lblIE.Name = "lblIE";
|
||||||
lblIE.Size = new Size(33, 25);
|
lblIE.Size = new Size(26, 20);
|
||||||
lblIE.TabIndex = 26;
|
lblIE.TabIndex = 26;
|
||||||
lblIE.Text = "IM";
|
lblIE.Text = "IM";
|
||||||
//
|
//
|
||||||
// btnReset
|
// btnReset
|
||||||
//
|
//
|
||||||
btnReset.Location = new Point(814, 409);
|
btnReset.Location = new Point(651, 327);
|
||||||
btnReset.Margin = new Padding(2);
|
btnReset.Margin = new Padding(2);
|
||||||
btnReset.Name = "btnReset";
|
btnReset.Name = "btnReset";
|
||||||
btnReset.Size = new Size(165, 34);
|
btnReset.Size = new Size(132, 27);
|
||||||
btnReset.TabIndex = 27;
|
btnReset.TabIndex = 27;
|
||||||
btnReset.Text = "Set Breakpoint";
|
btnReset.Text = "Set Breakpoint";
|
||||||
btnReset.UseVisualStyleBackColor = true;
|
btnReset.UseVisualStyleBackColor = true;
|
||||||
@@ -295,61 +287,58 @@
|
|||||||
// lblFrames
|
// lblFrames
|
||||||
//
|
//
|
||||||
lblFrames.AutoSize = true;
|
lblFrames.AutoSize = true;
|
||||||
lblFrames.Location = new Point(14, 660);
|
lblFrames.Location = new Point(11, 528);
|
||||||
lblFrames.Margin = new Padding(2, 0, 2, 0);
|
lblFrames.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblFrames.Name = "lblFrames";
|
lblFrames.Name = "lblFrames";
|
||||||
lblFrames.Size = new Size(149, 25);
|
lblFrames.Size = new Size(124, 20);
|
||||||
lblFrames.TabIndex = 28;
|
lblFrames.TabIndex = 28;
|
||||||
lblFrames.Text = "Frames Rendered";
|
lblFrames.Text = "Frames Rendered";
|
||||||
//
|
//
|
||||||
// lblFPS
|
// lblFPS
|
||||||
//
|
//
|
||||||
lblFPS.AutoSize = true;
|
lblFPS.AutoSize = true;
|
||||||
lblFPS.Location = new Point(129, 757);
|
lblFPS.Location = new Point(103, 606);
|
||||||
lblFPS.Margin = new Padding(2, 0, 2, 0);
|
lblFPS.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblFPS.Name = "lblFPS";
|
lblFPS.Name = "lblFPS";
|
||||||
lblFPS.Size = new Size(41, 25);
|
lblFPS.Size = new Size(32, 20);
|
||||||
lblFPS.TabIndex = 29;
|
lblFPS.TabIndex = 29;
|
||||||
lblFPS.Text = "FPS";
|
lblFPS.Text = "FPS";
|
||||||
//
|
//
|
||||||
// lblFrameTime
|
// lblFrameTime
|
||||||
//
|
//
|
||||||
lblFrameTime.AutoSize = true;
|
lblFrameTime.AutoSize = true;
|
||||||
lblFrameTime.Location = new Point(60, 706);
|
lblFrameTime.Location = new Point(48, 565);
|
||||||
lblFrameTime.Margin = new Padding(2, 0, 2, 0);
|
lblFrameTime.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblFrameTime.Name = "lblFrameTime";
|
lblFrameTime.Name = "lblFrameTime";
|
||||||
lblFrameTime.Size = new Size(104, 25);
|
lblFrameTime.Size = new Size(87, 20);
|
||||||
lblFrameTime.TabIndex = 30;
|
lblFrameTime.TabIndex = 30;
|
||||||
lblFrameTime.Text = "Frame Time";
|
lblFrameTime.Text = "Frame Time";
|
||||||
//
|
//
|
||||||
// richTextBox1
|
// richTextBox1
|
||||||
//
|
//
|
||||||
richTextBox1.Enabled = false;
|
richTextBox1.Enabled = false;
|
||||||
richTextBox1.Location = new Point(682, 474);
|
richTextBox1.Location = new Point(546, 379);
|
||||||
richTextBox1.Margin = new Padding(4);
|
|
||||||
richTextBox1.Name = "richTextBox1";
|
richTextBox1.Name = "richTextBox1";
|
||||||
richTextBox1.ReadOnly = true;
|
richTextBox1.ReadOnly = true;
|
||||||
richTextBox1.Size = new Size(379, 159);
|
richTextBox1.Size = new Size(304, 128);
|
||||||
richTextBox1.TabIndex = 32;
|
richTextBox1.TabIndex = 32;
|
||||||
richTextBox1.Text = "Sega Master System Memory Map:\n0x0000 - 0x3FFF: ROM Slot 0 (16KB)\n0x4000 - 0x7FFF: ROM Slot 1 (16KB)\n0x8000 - 0xBFFF: ROM Slot 2 (16KB)\n0xC000 - 0xDFFF: System RAM (8KB)\n0xE000 - 0xFFFF: RAM Mirror";
|
richTextBox1.Text = "Sega Master System Memory Map:\n0x0000 - 0x3FFF: ROM Slot 0 (16KB)\n0x4000 - 0x7FFF: ROM Slot 1 (16KB)\n0x8000 - 0xBFFF: ROM Slot 2 (16KB)\n0xC000 - 0xDFFF: System RAM (8KB)\n0xE000 - 0xFFFF: RAM Mirror";
|
||||||
//
|
//
|
||||||
// button1
|
// btnCpuStep
|
||||||
//
|
//
|
||||||
button1.Location = new Point(1075, 756);
|
btnCpuStep.Location = new Point(860, 605);
|
||||||
button1.Margin = new Padding(4);
|
btnCpuStep.Name = "btnCpuStep";
|
||||||
button1.Name = "button1";
|
btnCpuStep.Size = new Size(94, 29);
|
||||||
button1.Size = new Size(118, 36);
|
btnCpuStep.TabIndex = 33;
|
||||||
button1.TabIndex = 33;
|
btnCpuStep.Text = "CPU Step";
|
||||||
button1.Text = "CPU Step";
|
btnCpuStep.UseVisualStyleBackColor = true;
|
||||||
button1.UseVisualStyleBackColor = true;
|
btnCpuStep.Click += btnStep_Click;
|
||||||
button1.Click += btnStep_Click;
|
|
||||||
//
|
//
|
||||||
// CpuRun
|
// CpuRun
|
||||||
//
|
//
|
||||||
CpuRun.Location = new Point(943, 757);
|
CpuRun.Location = new Point(754, 606);
|
||||||
CpuRun.Margin = new Padding(4);
|
|
||||||
CpuRun.Name = "CpuRun";
|
CpuRun.Name = "CpuRun";
|
||||||
CpuRun.Size = new Size(118, 36);
|
CpuRun.Size = new Size(94, 29);
|
||||||
CpuRun.TabIndex = 34;
|
CpuRun.TabIndex = 34;
|
||||||
CpuRun.Text = "CPU Run";
|
CpuRun.Text = "CPU Run";
|
||||||
CpuRun.UseVisualStyleBackColor = true;
|
CpuRun.UseVisualStyleBackColor = true;
|
||||||
@@ -361,57 +350,63 @@
|
|||||||
groupBox1.Controls.Add(lblTone2);
|
groupBox1.Controls.Add(lblTone2);
|
||||||
groupBox1.Controls.Add(lblNoise);
|
groupBox1.Controls.Add(lblNoise);
|
||||||
groupBox1.Controls.Add(lblTone0);
|
groupBox1.Controls.Add(lblTone0);
|
||||||
groupBox1.Location = new Point(266, 658);
|
groupBox1.Location = new Point(213, 526);
|
||||||
|
groupBox1.Margin = new Padding(2, 2, 2, 2);
|
||||||
groupBox1.Name = "groupBox1";
|
groupBox1.Name = "groupBox1";
|
||||||
groupBox1.Size = new Size(397, 222);
|
groupBox1.Padding = new Padding(2, 2, 2, 2);
|
||||||
|
groupBox1.Size = new Size(318, 178);
|
||||||
groupBox1.TabIndex = 35;
|
groupBox1.TabIndex = 35;
|
||||||
groupBox1.TabStop = false;
|
groupBox1.TabStop = false;
|
||||||
groupBox1.Text = "Audio (SN76489)";
|
groupBox1.Text = "Audio (SN76489)";
|
||||||
//
|
//
|
||||||
// lblTone0
|
// lblTone1
|
||||||
//
|
//
|
||||||
lblTone0.AutoSize = true;
|
lblTone1.AutoSize = true;
|
||||||
lblTone0.Location = new Point(25, 48);
|
lblTone1.Location = new Point(20, 66);
|
||||||
lblTone0.Name = "lblTone0";
|
lblTone1.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblTone0.Size = new Size(59, 25);
|
lblTone1.Name = "lblTone1";
|
||||||
lblTone0.TabIndex = 0;
|
lblTone1.Size = new Size(49, 20);
|
||||||
lblTone0.Text = "Tone0";
|
lblTone1.TabIndex = 3;
|
||||||
//
|
lblTone1.Text = "Tone1";
|
||||||
// lblNoise
|
|
||||||
//
|
|
||||||
lblNoise.AutoSize = true;
|
|
||||||
lblNoise.Location = new Point(25, 160);
|
|
||||||
lblNoise.Name = "lblNoise";
|
|
||||||
lblNoise.Size = new Size(57, 25);
|
|
||||||
lblNoise.TabIndex = 1;
|
|
||||||
lblNoise.Text = "Noise";
|
|
||||||
//
|
//
|
||||||
// lblTone2
|
// lblTone2
|
||||||
//
|
//
|
||||||
lblTone2.AutoSize = true;
|
lblTone2.AutoSize = true;
|
||||||
lblTone2.Location = new Point(25, 122);
|
lblTone2.Location = new Point(20, 98);
|
||||||
|
lblTone2.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblTone2.Name = "lblTone2";
|
lblTone2.Name = "lblTone2";
|
||||||
lblTone2.Size = new Size(59, 25);
|
lblTone2.Size = new Size(49, 20);
|
||||||
lblTone2.TabIndex = 2;
|
lblTone2.TabIndex = 2;
|
||||||
lblTone2.Text = "Tone2";
|
lblTone2.Text = "Tone2";
|
||||||
//
|
//
|
||||||
// lblTone1
|
// lblNoise
|
||||||
//
|
//
|
||||||
lblTone1.AutoSize = true;
|
lblNoise.AutoSize = true;
|
||||||
lblTone1.Location = new Point(25, 83);
|
lblNoise.Location = new Point(20, 128);
|
||||||
lblTone1.Name = "lblTone1";
|
lblNoise.Margin = new Padding(2, 0, 2, 0);
|
||||||
lblTone1.Size = new Size(59, 25);
|
lblNoise.Name = "lblNoise";
|
||||||
lblTone1.TabIndex = 3;
|
lblNoise.Size = new Size(47, 20);
|
||||||
lblTone1.Text = "Tone1";
|
lblNoise.TabIndex = 1;
|
||||||
|
lblNoise.Text = "Noise";
|
||||||
|
//
|
||||||
|
// lblTone0
|
||||||
|
//
|
||||||
|
lblTone0.AutoSize = true;
|
||||||
|
lblTone0.Location = new Point(20, 38);
|
||||||
|
lblTone0.Margin = new Padding(2, 0, 2, 0);
|
||||||
|
lblTone0.Name = "lblTone0";
|
||||||
|
lblTone0.Size = new Size(49, 20);
|
||||||
|
lblTone0.TabIndex = 0;
|
||||||
|
lblTone0.Text = "Tone0";
|
||||||
//
|
//
|
||||||
// DebuggerForm
|
// DebuggerForm
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(10F, 25F);
|
AutoScaleDimensions = new SizeF(8F, 20F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
ClientSize = new Size(1206, 892);
|
ClientSize = new Size(965, 714);
|
||||||
Controls.Add(groupBox1);
|
Controls.Add(groupBox1);
|
||||||
Controls.Add(CpuRun);
|
Controls.Add(CpuRun);
|
||||||
Controls.Add(button1);
|
Controls.Add(btnCpuStep);
|
||||||
Controls.Add(richTextBox1);
|
Controls.Add(richTextBox1);
|
||||||
Controls.Add(lblFrameTime);
|
Controls.Add(lblFrameTime);
|
||||||
Controls.Add(lblFPS);
|
Controls.Add(lblFPS);
|
||||||
@@ -475,7 +470,7 @@
|
|||||||
private Label lblFPS;
|
private Label lblFPS;
|
||||||
private Label lblFrameTime;
|
private Label lblFrameTime;
|
||||||
private RichTextBox richTextBox1;
|
private RichTextBox richTextBox1;
|
||||||
private Button button1;
|
private Button btnCpuStep;
|
||||||
private Button CpuRun;
|
private Button CpuRun;
|
||||||
public System.Windows.Forms.Timer uiUpdateTimer;
|
public System.Windows.Forms.Timer uiUpdateTimer;
|
||||||
private GroupBox groupBox1;
|
private GroupBox groupBox1;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace Desktop
|
|||||||
UpdateStackView();
|
UpdateStackView();
|
||||||
UpdateDisassemblyView();
|
UpdateDisassemblyView();
|
||||||
_mainForm = mainForm;
|
_mainForm = mainForm;
|
||||||
|
CpuRun.Text = _mainForm.IsRunning ? "CPU Stop" : "CPU Run";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CpuRun_Click(object sender, EventArgs e)
|
private void CpuRun_Click(object sender, EventArgs e)
|
||||||
@@ -35,7 +36,6 @@ namespace Desktop
|
|||||||
{
|
{
|
||||||
// Stop the machine
|
// Stop the machine
|
||||||
_mainForm.StopEmulator();
|
_mainForm.StopEmulator();
|
||||||
CpuRun.Text = "CPU Run";
|
|
||||||
|
|
||||||
// Stop the live UI updates and do one final manual refresh
|
// Stop the live UI updates and do one final manual refresh
|
||||||
uiUpdateTimer.Stop();
|
uiUpdateTimer.Stop();
|
||||||
@@ -45,12 +45,12 @@ namespace Desktop
|
|||||||
{
|
{
|
||||||
// Start the machine
|
// Start the machine
|
||||||
_mainForm.StartEmulator();
|
_mainForm.StartEmulator();
|
||||||
CpuRun.Text = "CPU Stop";
|
|
||||||
|
|
||||||
// Start the timer so the debugger screen updates automatically
|
// Start the timer so the debugger screen updates automatically
|
||||||
// (Make sure your uiUpdateTimer Interval in the designer is set to something like 100ms)
|
// (Make sure your uiUpdateTimer Interval in the designer is set to something like 100ms)
|
||||||
uiUpdateTimer.Start();
|
uiUpdateTimer.Start();
|
||||||
}
|
}
|
||||||
|
CpuRun.Text = _mainForm.IsRunning ? "CPU Stop" : "CPU Run";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnStep_Click(object sender, EventArgs e)
|
private void btnStep_Click(object sender, EventArgs e)
|
||||||
@@ -92,6 +92,8 @@ namespace Desktop
|
|||||||
// Current Emulator State
|
// Current Emulator State
|
||||||
private void UpdateDisplay()
|
private void UpdateDisplay()
|
||||||
{
|
{
|
||||||
|
CpuRun.Text = _mainForm.IsRunning ? "CPU Stop" : "CPU Run";
|
||||||
|
btnCpuStep.Enabled = _mainForm.IsRunning ? false : true;
|
||||||
lblAF.Text = $"AF: {_cpu.AF.Word:X4}";
|
lblAF.Text = $"AF: {_cpu.AF.Word:X4}";
|
||||||
lblBC.Text = $"BC: {_cpu.BC.Word:X4}";
|
lblBC.Text = $"BC: {_cpu.BC.Word:X4}";
|
||||||
lblDE.Text = $"DE: {_cpu.DE.Word:X4}";
|
lblDE.Text = $"DE: {_cpu.DE.Word:X4}";
|
||||||
|
|||||||
47
Desktop/Form1.Designer.cs
generated
47
Desktop/Form1.Designer.cs
generated
@@ -32,6 +32,8 @@
|
|||||||
fileToolStripMenuItem = new ToolStripMenuItem();
|
fileToolStripMenuItem = new ToolStripMenuItem();
|
||||||
openToolStripMenuItem = new ToolStripMenuItem();
|
openToolStripMenuItem = new ToolStripMenuItem();
|
||||||
includedToolStripMenuItem = new ToolStripMenuItem();
|
includedToolStripMenuItem = new ToolStripMenuItem();
|
||||||
|
masterSystemToolStripMenuItem = new ToolStripMenuItem();
|
||||||
|
gameGearToolStripMenuItem = new ToolStripMenuItem();
|
||||||
selectROMToolStripMenuItem1 = new ToolStripMenuItem();
|
selectROMToolStripMenuItem1 = new ToolStripMenuItem();
|
||||||
exitToolStripMenuItem = new ToolStripMenuItem();
|
exitToolStripMenuItem = new ToolStripMenuItem();
|
||||||
viewToolStripMenuItem = new ToolStripMenuItem();
|
viewToolStripMenuItem = new ToolStripMenuItem();
|
||||||
@@ -44,8 +46,6 @@
|
|||||||
turboModeToolStripMenuItem = new ToolStripMenuItem();
|
turboModeToolStripMenuItem = new ToolStripMenuItem();
|
||||||
helpToolStripMenuItem = new ToolStripMenuItem();
|
helpToolStripMenuItem = new ToolStripMenuItem();
|
||||||
aboutToolStripMenuItem = new ToolStripMenuItem();
|
aboutToolStripMenuItem = new ToolStripMenuItem();
|
||||||
masterSystemToolStripMenuItem = new ToolStripMenuItem();
|
|
||||||
gameGearToolStripMenuItem = new ToolStripMenuItem();
|
|
||||||
menuStrip1.SuspendLayout();
|
menuStrip1.SuspendLayout();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
@@ -71,27 +71,39 @@
|
|||||||
//
|
//
|
||||||
openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, selectROMToolStripMenuItem1 });
|
openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, selectROMToolStripMenuItem1 });
|
||||||
openToolStripMenuItem.Name = "openToolStripMenuItem";
|
openToolStripMenuItem.Name = "openToolStripMenuItem";
|
||||||
openToolStripMenuItem.Size = new Size(224, 26);
|
openToolStripMenuItem.Size = new Size(128, 26);
|
||||||
openToolStripMenuItem.Text = "Open";
|
openToolStripMenuItem.Text = "Open";
|
||||||
//
|
//
|
||||||
// includedToolStripMenuItem
|
// includedToolStripMenuItem
|
||||||
//
|
//
|
||||||
includedToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { masterSystemToolStripMenuItem, gameGearToolStripMenuItem });
|
includedToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { masterSystemToolStripMenuItem, gameGearToolStripMenuItem });
|
||||||
includedToolStripMenuItem.Name = "includedToolStripMenuItem";
|
includedToolStripMenuItem.Name = "includedToolStripMenuItem";
|
||||||
includedToolStripMenuItem.Size = new Size(224, 26);
|
includedToolStripMenuItem.Size = new Size(178, 26);
|
||||||
includedToolStripMenuItem.Text = "Included";
|
includedToolStripMenuItem.Text = "Included";
|
||||||
//
|
//
|
||||||
|
// masterSystemToolStripMenuItem
|
||||||
|
//
|
||||||
|
masterSystemToolStripMenuItem.Name = "masterSystemToolStripMenuItem";
|
||||||
|
masterSystemToolStripMenuItem.Size = new Size(188, 26);
|
||||||
|
masterSystemToolStripMenuItem.Text = "Master System";
|
||||||
|
//
|
||||||
|
// gameGearToolStripMenuItem
|
||||||
|
//
|
||||||
|
gameGearToolStripMenuItem.Name = "gameGearToolStripMenuItem";
|
||||||
|
gameGearToolStripMenuItem.Size = new Size(188, 26);
|
||||||
|
gameGearToolStripMenuItem.Text = "Game Gear";
|
||||||
|
//
|
||||||
// selectROMToolStripMenuItem1
|
// selectROMToolStripMenuItem1
|
||||||
//
|
//
|
||||||
selectROMToolStripMenuItem1.Name = "selectROMToolStripMenuItem1";
|
selectROMToolStripMenuItem1.Name = "selectROMToolStripMenuItem1";
|
||||||
selectROMToolStripMenuItem1.Size = new Size(224, 26);
|
selectROMToolStripMenuItem1.Size = new Size(178, 26);
|
||||||
selectROMToolStripMenuItem1.Text = "Select ROM...";
|
selectROMToolStripMenuItem1.Text = "Select ROM...";
|
||||||
selectROMToolStripMenuItem1.Click += selectROMToolStripMenuItem_Click;
|
selectROMToolStripMenuItem1.Click += selectROMToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// exitToolStripMenuItem
|
// exitToolStripMenuItem
|
||||||
//
|
//
|
||||||
exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
||||||
exitToolStripMenuItem.Size = new Size(224, 26);
|
exitToolStripMenuItem.Size = new Size(128, 26);
|
||||||
exitToolStripMenuItem.Text = "Exit";
|
exitToolStripMenuItem.Text = "Exit";
|
||||||
exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
|
exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
@@ -126,28 +138,28 @@
|
|||||||
// resetToolStripMenuItem
|
// resetToolStripMenuItem
|
||||||
//
|
//
|
||||||
resetToolStripMenuItem.Name = "resetToolStripMenuItem";
|
resetToolStripMenuItem.Name = "resetToolStripMenuItem";
|
||||||
resetToolStripMenuItem.Size = new Size(224, 26);
|
resetToolStripMenuItem.Size = new Size(174, 26);
|
||||||
resetToolStripMenuItem.Text = "Reset";
|
resetToolStripMenuItem.Text = "Reset";
|
||||||
resetToolStripMenuItem.Click += resetToolStripMenuItem_Click;
|
resetToolStripMenuItem.Click += resetToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// saveStateToolStripMenuItem
|
// saveStateToolStripMenuItem
|
||||||
//
|
//
|
||||||
saveStateToolStripMenuItem.Name = "saveStateToolStripMenuItem";
|
saveStateToolStripMenuItem.Name = "saveStateToolStripMenuItem";
|
||||||
saveStateToolStripMenuItem.Size = new Size(224, 26);
|
saveStateToolStripMenuItem.Size = new Size(174, 26);
|
||||||
saveStateToolStripMenuItem.Text = "Save State";
|
saveStateToolStripMenuItem.Text = "Save State";
|
||||||
saveStateToolStripMenuItem.Click += saveStateToolStripMenuItem_Click;
|
saveStateToolStripMenuItem.Click += saveStateToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// loadStateToolStripMenuItem
|
// loadStateToolStripMenuItem
|
||||||
//
|
//
|
||||||
loadStateToolStripMenuItem.Name = "loadStateToolStripMenuItem";
|
loadStateToolStripMenuItem.Name = "loadStateToolStripMenuItem";
|
||||||
loadStateToolStripMenuItem.Size = new Size(224, 26);
|
loadStateToolStripMenuItem.Size = new Size(174, 26);
|
||||||
loadStateToolStripMenuItem.Text = "Load State";
|
loadStateToolStripMenuItem.Text = "Load State";
|
||||||
loadStateToolStripMenuItem.Click += loadStateToolStripMenuItem_Click;
|
loadStateToolStripMenuItem.Click += loadStateToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// turboModeToolStripMenuItem
|
// turboModeToolStripMenuItem
|
||||||
//
|
//
|
||||||
turboModeToolStripMenuItem.Name = "turboModeToolStripMenuItem";
|
turboModeToolStripMenuItem.Name = "turboModeToolStripMenuItem";
|
||||||
turboModeToolStripMenuItem.Size = new Size(224, 26);
|
turboModeToolStripMenuItem.Size = new Size(174, 26);
|
||||||
turboModeToolStripMenuItem.Text = "Turbo Mode";
|
turboModeToolStripMenuItem.Text = "Turbo Mode";
|
||||||
turboModeToolStripMenuItem.Click += turboModeToolStripMenuItem_Click;
|
turboModeToolStripMenuItem.Click += turboModeToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
@@ -161,20 +173,9 @@
|
|||||||
// aboutToolStripMenuItem
|
// aboutToolStripMenuItem
|
||||||
//
|
//
|
||||||
aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
|
aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
|
||||||
aboutToolStripMenuItem.Size = new Size(133, 26);
|
aboutToolStripMenuItem.Size = new Size(224, 26);
|
||||||
aboutToolStripMenuItem.Text = "About";
|
aboutToolStripMenuItem.Text = "About";
|
||||||
//
|
aboutToolStripMenuItem.Click += aboutToolStripMenuItem_Click;
|
||||||
// masterSystemToolStripMenuItem
|
|
||||||
//
|
|
||||||
masterSystemToolStripMenuItem.Name = "masterSystemToolStripMenuItem";
|
|
||||||
masterSystemToolStripMenuItem.Size = new Size(224, 26);
|
|
||||||
masterSystemToolStripMenuItem.Text = "Master System";
|
|
||||||
//
|
|
||||||
// gameGearToolStripMenuItem
|
|
||||||
//
|
|
||||||
gameGearToolStripMenuItem.Name = "gameGearToolStripMenuItem";
|
|
||||||
gameGearToolStripMenuItem.Size = new Size(224, 26);
|
|
||||||
gameGearToolStripMenuItem.Text = "Game Gear";
|
|
||||||
//
|
//
|
||||||
// ParsonsForm1
|
// ParsonsForm1
|
||||||
//
|
//
|
||||||
|
|||||||
107
Desktop/Form1.cs
107
Desktop/Form1.cs
@@ -59,6 +59,7 @@ namespace Desktop
|
|||||||
_machine = new SmsMachine();
|
_machine = new SmsMachine();
|
||||||
_audioPlayer = new NAudioPlayer();
|
_audioPlayer = new NAudioPlayer();
|
||||||
_machine.AudioProcessor.AudioDevice = _audioPlayer;
|
_machine.AudioProcessor.AudioDevice = _audioPlayer;
|
||||||
|
IsRunning = false;
|
||||||
|
|
||||||
PopulateIncludedRomsMenu();
|
PopulateIncludedRomsMenu();
|
||||||
}
|
}
|
||||||
@@ -253,50 +254,51 @@ namespace Desktop
|
|||||||
{
|
{
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
}
|
}
|
||||||
private async void LoadRomAndStart(string filePath)
|
|
||||||
|
private async void LoadRomDataAndStart(byte[] romData, string fileName, string uniqueId)
|
||||||
{
|
{
|
||||||
StopEmulator();
|
StopEmulator();
|
||||||
if (_emulatorTask != null)
|
if (_emulatorTask != null)
|
||||||
{
|
{
|
||||||
await _emulatorTask;
|
await _emulatorTask;
|
||||||
}
|
}
|
||||||
_romType = Path.GetExtension(filePath);
|
|
||||||
if (_romType == ".sms")
|
|
||||||
{
|
|
||||||
_machine.VideoProcessor.IsGameGear = false;
|
|
||||||
}
|
|
||||||
else if (_romType == ".gg")
|
|
||||||
{
|
|
||||||
_machine.VideoProcessor.IsGameGear = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw new Exception("Incorrect ROM Type!");
|
|
||||||
_romType = _machine.VideoProcessor.IsGameGear ? "GG" : "SMS";
|
|
||||||
|
|
||||||
// 1. SAVE THE PREVIOUS GAME!
|
|
||||||
SaveCurrentSram();
|
SaveCurrentSram();
|
||||||
|
|
||||||
// 2. Load the file
|
// Blast the bytes straight into the virtual cartridge slot!
|
||||||
byte[] rom = File.ReadAllBytes(filePath);
|
_machine.LoadCartridge(romData);
|
||||||
|
|
||||||
// 3. Jam it into the Sega Mapper
|
// Check the hardware mode based on the file name
|
||||||
_machine.LoadCartridge(rom);
|
bool isGG = fileName.EndsWith(".gg", StringComparison.OrdinalIgnoreCase);
|
||||||
|
_machine.VideoProcessor.IsGameGear = isGG;
|
||||||
|
|
||||||
// 4. Update the path tracking
|
// We use uniqueId to track the SRAM file path (works for both real paths and resource names)
|
||||||
_currentRomPath = filePath;
|
_currentRomPath = uniqueId;
|
||||||
_currentRomName = Path.GetFileNameWithoutExtension(filePath);
|
_currentRomName = Path.GetFileNameWithoutExtension(fileName);
|
||||||
//this.Text = $"{_romType} Parsons Master System 2026 - {_currentRomName}";
|
|
||||||
|
// Update the window title dynamically
|
||||||
|
_romType = isGG ? "GG" : "MS";
|
||||||
|
this.Text = $"{_romType} Parsons Master System 2026 - {_currentRomName}";
|
||||||
|
|
||||||
// 5. LOAD THE NEW SAVE DATA FROM THE EXE FOLDER!
|
|
||||||
string savPath = GetSaveFilePath();
|
string savPath = GetSaveFilePath();
|
||||||
if (savPath != null)
|
if (savPath != null)
|
||||||
{
|
{
|
||||||
_machine.MemoryBus.LoadSaveData(savPath);
|
_machine.MemoryBus.LoadSaveData(savPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Turn the power on!
|
|
||||||
StartEmulator();
|
StartEmulator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadRomAndStart(string filePath)
|
||||||
|
{
|
||||||
|
if (!File.Exists(filePath)) return;
|
||||||
|
|
||||||
|
// Read from the hard drive, then pass to the universal loader
|
||||||
|
byte[] romData = File.ReadAllBytes(filePath);
|
||||||
|
LoadRomDataAndStart(romData, Path.GetFileName(filePath), filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private string GetSaveFilePath()
|
private string GetSaveFilePath()
|
||||||
{
|
{
|
||||||
// Don't try to save if a game hasn't been loaded yet!
|
// Don't try to save if a game hasn't been loaded yet!
|
||||||
@@ -339,7 +341,7 @@ namespace Desktop
|
|||||||
ToolStripMenuItem romMenuItem = new ToolStripMenuItem(menuName);
|
ToolStripMenuItem romMenuItem = new ToolStripMenuItem(menuName);
|
||||||
|
|
||||||
// 3. Point the click event to our new extraction helper!
|
// 3. Point the click event to our new extraction helper!
|
||||||
romMenuItem.Click += (sender, e) => ExtractAndLoadEmbeddedRom(resourceName);
|
romMenuItem.Click += (sender, e) => LoadEmbeddedRom(resourceName);
|
||||||
|
|
||||||
// 4. Sort into the correct menu based on extension!
|
// 4. Sort into the correct menu based on extension!
|
||||||
if (resourceName.EndsWith(".gg", StringComparison.OrdinalIgnoreCase))
|
if (resourceName.EndsWith(".gg", StringComparison.OrdinalIgnoreCase))
|
||||||
@@ -353,32 +355,28 @@ namespace Desktop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExtractAndLoadEmbeddedRom(string resourceName)
|
private void LoadEmbeddedRom(string resourceName)
|
||||||
{
|
{
|
||||||
// 1. Strip off the ugly "Desktop.ROMS." prefix to get the real file name
|
// 1. Strip off the ugly prefix to get the real file name for the UI and the .gg check
|
||||||
string cleanFileName = resourceName.Replace("Desktop.ROMS.", "");
|
string cleanFileName = resourceName.Replace("Desktop.ROMS.", "");
|
||||||
|
|
||||||
// 2. Create a physical path right next to your emulator .exe
|
|
||||||
string physicalPath = Path.Combine(Application.StartupPath, cleanFileName);
|
|
||||||
|
|
||||||
// 3. If we haven't extracted this game yet, extract it now!
|
|
||||||
if (!File.Exists(physicalPath))
|
|
||||||
{
|
|
||||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
|
||||||
|
// 2. Open a direct pipe to the internal resource
|
||||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||||
{
|
{
|
||||||
if (stream == null) return;
|
if (stream == null) return;
|
||||||
using (FileStream fileStream = new FileStream(physicalPath, FileMode.Create))
|
|
||||||
{
|
|
||||||
stream.CopyTo(fileStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Now that it is a REAL file on the hard drive, pass it to your normal loader!
|
// 3. Copy the stream entirely in RAM—never touching the hard drive!
|
||||||
LoadRomAndStart(physicalPath);
|
using (MemoryStream ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
stream.CopyTo(ms);
|
||||||
|
byte[] romData = ms.ToArray();
|
||||||
|
|
||||||
|
// 4. Pass the raw bytes to our universal loader
|
||||||
|
LoadRomDataAndStart(romData, cleanFileName, resourceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] GetFilesInResourceDirectory(string directoryPrefix)
|
public static string[] GetFilesInResourceDirectory(string directoryPrefix)
|
||||||
@@ -532,5 +530,28 @@ namespace Desktop
|
|||||||
turboModeToolStripMenuItem.Checked = !turboModeToolStripMenuItem.Checked;
|
turboModeToolStripMenuItem.Checked = !turboModeToolStripMenuItem.Checked;
|
||||||
isTurboMode = turboModeToolStripMenuItem.Checked ? true : false;
|
isTurboMode = turboModeToolStripMenuItem.Checked ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
$"First full release of Parsons Master System Emulator 2026!\r\n\r\nFeatures (v1.0):\r\n\r\n" +
|
||||||
|
$" *Full compatibility with all Master System and Game Gear ROMs\r\n" +
|
||||||
|
$" *Full window scaling with fixed aspect ratio (SMS & GG)\r\n" +
|
||||||
|
$" *Full 4 channel SN76489 implememtation using NAudio\r\n" +
|
||||||
|
$" *SRAM auto save and load (Battery Backed RAM)\r\n" +
|
||||||
|
$" *Keyboard and XInput control pad support\r\n" +
|
||||||
|
$" *Comprehensive Debugger\r\n" +
|
||||||
|
$" *VRAM Viewer\r\n" +
|
||||||
|
$" *Single point Save State\r\n" +
|
||||||
|
$" *Turbo mode\r\n" +
|
||||||
|
$" *Includes a selection of commercial ROMs\r\n\r\n" +
|
||||||
|
$"Planned updates (v1.1):\r\n\r\n" +
|
||||||
|
$" *Architectural double buffering (prevent screen tear)\r\n" +
|
||||||
|
$" *Graphics shaders (scanlines etc...)\r\n" +
|
||||||
|
$" *Add multiple Save States per game\r\n\r\n\r\n" +
|
||||||
|
$"(c) Marc Parsons 2026","Parsons Master System 2026 v1.0",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user