Got main system and VDP working! There is a display!
This commit is contained in:
@@ -1275,6 +1275,18 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
switch (extendedOpcode)
|
switch (extendedOpcode)
|
||||||
{
|
{
|
||||||
|
case 0x41: // OUT (C), B
|
||||||
|
_simpleIoBus.WritePort(BC.Word, BC.High);
|
||||||
|
return 12;
|
||||||
|
case 0x49: // OUT (C), C
|
||||||
|
_simpleIoBus.WritePort(BC.Word, BC.Low);
|
||||||
|
return 12;
|
||||||
|
case 0x61: // OUT (C), H
|
||||||
|
_simpleIoBus.WritePort(BC.Word, HL.High);
|
||||||
|
return 12;
|
||||||
|
case 0x69: // OUT (C), L
|
||||||
|
_simpleIoBus.WritePort(BC.Word, HL.Low);
|
||||||
|
return 12;
|
||||||
case 0x43: // LD (nn), BC
|
case 0x43: // LD (nn), BC
|
||||||
ushort dest43 = FetchWord();
|
ushort dest43 = FetchWord();
|
||||||
WriteMemory(dest43, BC.Low);
|
WriteMemory(dest43, BC.Low);
|
||||||
@@ -1494,6 +1506,48 @@ namespace Core.Cpu
|
|||||||
if ((n & 0x02) != 0) AF.Low |= 0x20; // Bit 5 from bit 1
|
if ((n & 0x02) != 0) AF.Low |= 0x20; // Bit 5 from bit 1
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
case 0xA3: // OUTI
|
||||||
|
{
|
||||||
|
// 1. Read data from memory at HL
|
||||||
|
byte valA3 = ReadMemory(HL.Word);
|
||||||
|
|
||||||
|
// 2. Decrement the B register
|
||||||
|
BC.High--;
|
||||||
|
|
||||||
|
// 3. Output the data to the port specified by C
|
||||||
|
_simpleIoBus.WritePort(BC.Word, valA3);
|
||||||
|
|
||||||
|
// 4. Increment the memory pointer
|
||||||
|
HL.Word++;
|
||||||
|
|
||||||
|
// 5. Update Flags (N is always set. Z is set if B reached 0)
|
||||||
|
AF.Low |= 0x02;
|
||||||
|
if (BC.High == 0) AF.Low |= 0x40;
|
||||||
|
else AF.Low &= 0xBF;
|
||||||
|
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
case 0xB3: // OTIR
|
||||||
|
{
|
||||||
|
// This does exactly the same thing as OUTI, but loops until B == 0
|
||||||
|
byte valB3 = ReadMemory(HL.Word);
|
||||||
|
BC.High--;
|
||||||
|
_simpleIoBus.WritePort(BC.Word, valB3);
|
||||||
|
HL.Word++;
|
||||||
|
|
||||||
|
AF.Low |= 0x02;
|
||||||
|
if (BC.High != 0)
|
||||||
|
{
|
||||||
|
AF.Low &= 0xBF; // Z is reset
|
||||||
|
PC -= 2; // Loop back and execute ED B3 again!
|
||||||
|
return 21;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AF.Low |= 0x40; // Z is set
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
case 0xB0: // LDIR
|
case 0xB0: // LDIR
|
||||||
{
|
{
|
||||||
byte val00 = ReadMemory(HL.Word);
|
byte val00 = ReadMemory(HL.Word);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using Core.Interfaces;
|
using Core.Interfaces;
|
||||||
|
using Core.Video;
|
||||||
|
|
||||||
namespace Core.Io
|
namespace Core.Io
|
||||||
{
|
{
|
||||||
public class SmsIoBus : IIoBus
|
public class SmsIoBus : IIoBus
|
||||||
{
|
{
|
||||||
// We will wire these up in the next phases!
|
public SmsVdp VideoProcessor { get; set; }
|
||||||
// public Vdp VideoProcessor { get; set; }
|
|
||||||
// public Psg AudioProcessor { get; set; }
|
// public Psg AudioProcessor { get; set; }
|
||||||
|
|
||||||
// Joypad State (0xFF means no buttons pressed - the SMS uses Active-Low logic!)
|
// Joypad State (0xFF means no buttons pressed - the SMS uses Active-Low logic!)
|
||||||
@@ -18,11 +18,17 @@ namespace Core.Io
|
|||||||
// hardware only physically wires up the bottom 8 bits.
|
// hardware only physically wires up the bottom 8 bits.
|
||||||
byte lowerPort = (byte)(port & 0xFF);
|
byte lowerPort = (byte)(port & 0xFF);
|
||||||
|
|
||||||
|
if (lowerPort == 0x7E)
|
||||||
|
{
|
||||||
|
// VDP V-Counter (Vertical Scanline Position)
|
||||||
|
return VideoProcessor.ReadVCounter();
|
||||||
|
}
|
||||||
|
|
||||||
if (lowerPort >= 0x80 && lowerPort <= 0xBF)
|
if (lowerPort >= 0x80 && lowerPort <= 0xBF)
|
||||||
{
|
{
|
||||||
// VDP Read (Usually 0xBE for VRAM Data, 0xBF for Status Flags)
|
// Even ports (like 0xBE) are Data. Odd ports (like 0xBF) are Control.
|
||||||
// return VideoProcessor.ReadPort(lowerPort);
|
if ((lowerPort & 0x01) == 0) return VideoProcessor.ReadDataPort();
|
||||||
return 0x00;
|
else return VideoProcessor.ReadControlPort();
|
||||||
}
|
}
|
||||||
if (lowerPort == 0xDC)
|
if (lowerPort == 0xDC)
|
||||||
{
|
{
|
||||||
@@ -49,8 +55,8 @@ namespace Core.Io
|
|||||||
}
|
}
|
||||||
else if (lowerPort >= 0x80 && lowerPort <= 0xBF)
|
else if (lowerPort >= 0x80 && lowerPort <= 0xBF)
|
||||||
{
|
{
|
||||||
// VDP Write (Usually 0xBE for VRAM Data, 0xBF for Control Registers)
|
if ((lowerPort & 0x01) == 0) VideoProcessor.WriteDataPort(value);
|
||||||
// VideoProcessor.WritePort(lowerPort, value);
|
else VideoProcessor.WriteControlPort(value);
|
||||||
}
|
}
|
||||||
else if (lowerPort <= 0x3F)
|
else if (lowerPort <= 0x3F)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using Core.Cpu;
|
using Core.Cpu;
|
||||||
using Core.Io;
|
using Core.Io;
|
||||||
using Core.Memory;
|
using Core.Memory;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
@@ -9,18 +12,17 @@ namespace Core
|
|||||||
public Z80 Cpu { get; private set; }
|
public Z80 Cpu { get; private set; }
|
||||||
public SmsMemoryBus MemoryBus { get; private set; }
|
public SmsMemoryBus MemoryBus { get; private set; }
|
||||||
public SmsIoBus IoBus { get; private set; }
|
public SmsIoBus IoBus { get; private set; }
|
||||||
|
public Core.Video.SmsVdp VideoProcessor { get; private set; }
|
||||||
public ushort? Breakpoint { get; set; } = null;
|
public ushort? Breakpoint { get; set; } = null;
|
||||||
|
|
||||||
// NTSC SMS T-States per frame
|
// NTSC SMS T-States per frame
|
||||||
public const int TStatesPerFrame = 59736;
|
public const int TStatesPerFrame = 59736;
|
||||||
public long TotalFrameCount { get; private set; } = 0;
|
|
||||||
public double FramesPerSecond { get; private set; } = 0;
|
|
||||||
public double FrameTime { get; private set; } = 0;
|
|
||||||
|
|
||||||
public SmsMachine()
|
public SmsMachine()
|
||||||
{
|
{
|
||||||
MemoryBus = new SmsMemoryBus();
|
MemoryBus = new SmsMemoryBus();
|
||||||
IoBus = new SmsIoBus();
|
VideoProcessor = new Core.Video.SmsVdp();
|
||||||
|
IoBus = new SmsIoBus { VideoProcessor = this.VideoProcessor };
|
||||||
Cpu = new Z80(MemoryBus, IoBus);
|
Cpu = new Z80(MemoryBus, IoBus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,8 +36,23 @@ namespace Core
|
|||||||
{
|
{
|
||||||
MemoryBus.CleanRAMData();
|
MemoryBus.CleanRAMData();
|
||||||
Cpu.Reset();
|
Cpu.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
// We will reset the VDP and PSG here later!
|
public int StepMachine()
|
||||||
|
{
|
||||||
|
// 1. Tick the CPU
|
||||||
|
int tStates = Cpu.Step();
|
||||||
|
|
||||||
|
// 2. Tell the VDP how much time just passed
|
||||||
|
VideoProcessor.Update(tStates);
|
||||||
|
|
||||||
|
// 3. Trigger interrupts if the VDP hit scanline 192
|
||||||
|
if (VideoProcessor.InterruptPending)
|
||||||
|
{
|
||||||
|
tStates += Cpu.RequestInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
return tStates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RunFrame()
|
public void RunFrame()
|
||||||
@@ -44,18 +61,51 @@ namespace Core
|
|||||||
|
|
||||||
while (currentFrameTStates < TStatesPerFrame)
|
while (currentFrameTStates < TStatesPerFrame)
|
||||||
{
|
{
|
||||||
int tStates = Cpu.Step();
|
currentFrameTStates += StepMachine();
|
||||||
currentFrameTStates += tStates;
|
string filePath = "captured_data.txt";
|
||||||
|
|
||||||
// --- FUTURE EXPANSION ---
|
// Mock data to loop through
|
||||||
// VideoProcessor.Update(tStates);
|
//List<ushort> sensorReadings = new List<ushort> { Cpu.PC, Cpu.AF.Word, Cpu.BC.Word, Cpu.DE.Word, Cpu.HL.Word, Cpu.SP};
|
||||||
// AudioProcessor.Update(tStates);
|
//List<string> type = new List<string> {"PC: 0x", "AF: 0x", "BC: 0x", "DE: 0x", "HL: 0x", "SP: 0x" };
|
||||||
|
|
||||||
// if (VideoProcessor.IsVBlanking && VideoProcessor.InterruptsEnabled)
|
//try
|
||||||
// {
|
//{
|
||||||
// Cpu.RequestInterrupt();
|
// // 2. Initialize StreamWriter within a 'using' block
|
||||||
// }
|
// // The 'true' parameter means "append" to the file. Use 'false' to overwrite.
|
||||||
|
// using (StreamWriter writer = new StreamWriter(filePath, append: true))
|
||||||
|
// {
|
||||||
|
// foreach (int reading in sensorReadings)
|
||||||
|
// {
|
||||||
|
// string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
// // 3. Construct your string and write it
|
||||||
|
// foreach (string _type in type)
|
||||||
|
// {
|
||||||
|
// string line = $"{timestamp} | {_type} {reading}";
|
||||||
|
// writer.WriteLine(line);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// // Optional: Console feedback
|
||||||
|
// //Console.WriteLine($"Logged: {line}");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // File is automatically closed and saved here
|
||||||
|
|
||||||
|
// //Console.WriteLine("Data capture complete.");
|
||||||
|
//}
|
||||||
|
//catch (IOException e)
|
||||||
|
//{
|
||||||
|
// Console.WriteLine($"An error occurred: {e.Message}");
|
||||||
|
//}
|
||||||
|
|
||||||
|
// THE TRIPWIRE: Check the breakpoint after EVERY single instruction!
|
||||||
|
if (Breakpoint.HasValue && Cpu.PC == Breakpoint.Value)
|
||||||
|
{
|
||||||
|
break; // Abort the frame loop immediately!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
194
Core/Video/SmsVdp.cs
Normal file
194
Core/Video/SmsVdp.cs
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Core.Video
|
||||||
|
{
|
||||||
|
public class SmsVdp
|
||||||
|
{
|
||||||
|
// The VDP's private memory! The CPU cannot touch these arrays directly.
|
||||||
|
public byte[] VRAM { get; private set; } = new byte[0x4000]; // 16KB Video RAM
|
||||||
|
public byte[] CRAM { get; private set; } = new byte[0x20]; // 32 Bytes Color Palette
|
||||||
|
public byte[] Registers { get; private set; } = new byte[16]; // 11 Hardware Control Registers
|
||||||
|
public int[] FrameBuffer { get; private set; } = new int[256 * 192];
|
||||||
|
|
||||||
|
// The Control Port State Machine (Port 0xBF)
|
||||||
|
private bool _isSecondControlByte = false;
|
||||||
|
private ushort _controlWord = 0;
|
||||||
|
private byte _readBuffer = 0;
|
||||||
|
|
||||||
|
private int _tStateCounter = 0;
|
||||||
|
private int _currentScanline = 0;
|
||||||
|
private byte _statusRegister = 0x00;
|
||||||
|
|
||||||
|
public bool InterruptPending => (_statusRegister & 0x80) != 0 && (Registers[1] & 0x20) != 0;
|
||||||
|
|
||||||
|
public byte ReadDataPort() // Port 0xBE
|
||||||
|
{
|
||||||
|
_isSecondControlByte = false; // Reading data resets the control latch
|
||||||
|
byte value = _readBuffer;
|
||||||
|
_readBuffer = VRAM[_controlWord & 0x3FFF];
|
||||||
|
_controlWord++;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte ReadControlPort() // Port 0xBF
|
||||||
|
{
|
||||||
|
_isSecondControlByte = false;
|
||||||
|
byte currentStatus = _statusRegister;
|
||||||
|
|
||||||
|
// CRITICAL HARDWARE QUIRK: Reading the status port physically
|
||||||
|
// clears the flags inside the chip! If we don't clear this,
|
||||||
|
// the interrupt line gets stuck on forever.
|
||||||
|
_statusRegister = 0x00;
|
||||||
|
|
||||||
|
return currentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteDataPort(byte value) // Port 0xBE
|
||||||
|
{
|
||||||
|
_isSecondControlByte = false;
|
||||||
|
_readBuffer = value;
|
||||||
|
|
||||||
|
int address = _controlWord & 0x3FFF;
|
||||||
|
int command = (_controlWord >> 14) & 0x03;
|
||||||
|
|
||||||
|
if (command == 3) // Code 3: Write to Color Palette (CRAM)
|
||||||
|
{
|
||||||
|
CRAM[address & 0x1F] = value;
|
||||||
|
}
|
||||||
|
else // Code 0, 1, 2: Write to VRAM
|
||||||
|
{
|
||||||
|
VRAM[address] = value;
|
||||||
|
}
|
||||||
|
_controlWord++; // Auto-increment so the Z80 can blast data fast
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteControlPort(byte value) // Port 0xBF
|
||||||
|
{
|
||||||
|
if (!_isSecondControlByte)
|
||||||
|
{
|
||||||
|
// First byte arrives: Store it in the lower 8 bits
|
||||||
|
_controlWord = (ushort)((_controlWord & 0xFF00) | value);
|
||||||
|
_isSecondControlByte = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Second byte arrives: Store it in the upper 8 bits and execute!
|
||||||
|
_controlWord = (ushort)((_controlWord & 0x00FF) | (value << 8));
|
||||||
|
_isSecondControlByte = false;
|
||||||
|
|
||||||
|
int command = (_controlWord >> 14) & 0x03;
|
||||||
|
|
||||||
|
if (command == 0) // Code 0: Prep for VRAM Read
|
||||||
|
{
|
||||||
|
_readBuffer = VRAM[_controlWord & 0x3FFF];
|
||||||
|
_controlWord++;
|
||||||
|
}
|
||||||
|
else if (command == 2) // Code 2: Write to Internal VDP Register
|
||||||
|
{
|
||||||
|
int regIndex = value & 0x0F;
|
||||||
|
byte regData = (byte)(_controlWord & 0xFF);
|
||||||
|
|
||||||
|
if (regIndex < 16) Registers[regIndex] = regData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte ReadVCounter()
|
||||||
|
{
|
||||||
|
// Note: On real NTSC hardware, the V-Counter jumps slightly around
|
||||||
|
// the VBlank period to keep the math 8-bit, but simply returning
|
||||||
|
// the raw current scanline is perfectly fine to get us booting!
|
||||||
|
return (byte)_currentScanline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(int tStates)
|
||||||
|
{
|
||||||
|
_tStateCounter += tStates;
|
||||||
|
|
||||||
|
// 228 T-States per scanline
|
||||||
|
if (_tStateCounter >= 228)
|
||||||
|
{
|
||||||
|
_tStateCounter -= 228;
|
||||||
|
_currentScanline++;
|
||||||
|
|
||||||
|
// Line 192 is the exact moment the screen finishes drawing!
|
||||||
|
if (_currentScanline == 192)
|
||||||
|
{
|
||||||
|
_statusRegister |= 0x80; // Set Bit 7 (VBlank Flag) to 1
|
||||||
|
|
||||||
|
RenderBackground(); // <--- DRAW THE FRAME!
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of the NTSC frame (262 lines)
|
||||||
|
if (_currentScanline > 261)
|
||||||
|
{
|
||||||
|
_currentScanline = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderBackground()
|
||||||
|
{
|
||||||
|
// The Name Table base address is stored in VDP Register 2.
|
||||||
|
// It tells us where in VRAM the 32x24 screen grid starts.
|
||||||
|
ushort nameTableBase = (ushort)((Registers[2] & 0x0E) << 10);
|
||||||
|
|
||||||
|
// Loop through all 24 rows and 32 columns of the screen
|
||||||
|
for (int row = 0; row < 24; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < 32; col++)
|
||||||
|
{
|
||||||
|
// 1. Read the 16-bit Tile instruction from the Name Table
|
||||||
|
ushort nameTableAddr = (ushort)(nameTableBase + (row * 64) + (col * 2));
|
||||||
|
byte lowByte = VRAM[nameTableAddr];
|
||||||
|
byte highByte = VRAM[nameTableAddr + 1];
|
||||||
|
ushort tileData = (ushort)((highByte << 8) | lowByte);
|
||||||
|
|
||||||
|
// 2. Extract the Tile Index and Palette Info
|
||||||
|
int tileIndex = tileData & 0x01FF;
|
||||||
|
bool useSpritePalette = (tileData & 0x0800) != 0;
|
||||||
|
|
||||||
|
// 3. Find the actual pixel data for this tile in VRAM
|
||||||
|
// Each 8x8 tile takes exactly 32 bytes in memory
|
||||||
|
ushort tileAddress = (ushort)(tileIndex * 32);
|
||||||
|
|
||||||
|
// 4. Draw the 8x8 block of pixels!
|
||||||
|
for (int y = 0; y < 8; y++)
|
||||||
|
{
|
||||||
|
// The SMS uses 4 bitplanes to make a single row of pixels.
|
||||||
|
byte bp0 = VRAM[tileAddress + (y * 4) + 0];
|
||||||
|
byte bp1 = VRAM[tileAddress + (y * 4) + 1];
|
||||||
|
byte bp2 = VRAM[tileAddress + (y * 4) + 2];
|
||||||
|
byte bp3 = VRAM[tileAddress + (y * 4) + 3];
|
||||||
|
|
||||||
|
for (int x = 0; x < 8; x++)
|
||||||
|
{
|
||||||
|
// Combine 1 bit from each bitplane to get a color index (0-15)
|
||||||
|
int shift = 7 - x;
|
||||||
|
int colorIndex = ((bp0 >> shift) & 1) |
|
||||||
|
(((bp1 >> shift) & 1) << 1) |
|
||||||
|
(((bp2 >> shift) & 1) << 2) |
|
||||||
|
(((bp3 >> shift) & 1) << 3);
|
||||||
|
|
||||||
|
// Find the raw SMS color in CRAM
|
||||||
|
int paletteOffset = useSpritePalette ? 16 : 0;
|
||||||
|
byte smsColor = CRAM[paletteOffset + colorIndex];
|
||||||
|
|
||||||
|
// Translate SMS 00BBGGRR format to Windows 32-bit ARGB
|
||||||
|
int r = (smsColor & 0x03) * 85;
|
||||||
|
int g = ((smsColor >> 2) & 0x03) * 85;
|
||||||
|
int b = ((smsColor >> 4) & 0x03) * 85;
|
||||||
|
|
||||||
|
// Calculate where this pixel goes on the final 256x192 screen
|
||||||
|
int pixelX = (col * 8) + x;
|
||||||
|
int pixelY = (row * 8) + y;
|
||||||
|
|
||||||
|
FrameBuffer[(pixelY * 256) + pixelX] = (255 << 24) | (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
147
Desktop/DebuggerForm.Designer.cs
generated
147
Desktop/DebuggerForm.Designer.cs
generated
@@ -57,95 +57,95 @@
|
|||||||
lblFrameTime = new Label();
|
lblFrameTime = new Label();
|
||||||
richTextBox1 = new RichTextBox();
|
richTextBox1 = new RichTextBox();
|
||||||
button1 = new Button();
|
button1 = new Button();
|
||||||
button2 = new Button();
|
CpuRun = new Button();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// lblAF
|
// lblAF
|
||||||
//
|
//
|
||||||
lblAF.AutoSize = true;
|
lblAF.AutoSize = true;
|
||||||
lblAF.Location = new Point(10, 7);
|
lblAF.Location = new Point(12, 9);
|
||||||
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(26, 20);
|
lblAF.Size = new Size(33, 25);
|
||||||
lblAF.TabIndex = 0;
|
lblAF.TabIndex = 0;
|
||||||
lblAF.Text = "AF";
|
lblAF.Text = "AF";
|
||||||
//
|
//
|
||||||
// lblBC
|
// lblBC
|
||||||
//
|
//
|
||||||
lblBC.AutoSize = true;
|
lblBC.AutoSize = true;
|
||||||
lblBC.Location = new Point(9, 48);
|
lblBC.Location = new Point(11, 60);
|
||||||
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(27, 20);
|
lblBC.Size = new Size(33, 25);
|
||||||
lblBC.TabIndex = 1;
|
lblBC.TabIndex = 1;
|
||||||
lblBC.Text = "BC";
|
lblBC.Text = "BC";
|
||||||
//
|
//
|
||||||
// lblDE
|
// lblDE
|
||||||
//
|
//
|
||||||
lblDE.AutoSize = true;
|
lblDE.AutoSize = true;
|
||||||
lblDE.Location = new Point(10, 100);
|
lblDE.Location = new Point(12, 125);
|
||||||
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(28, 20);
|
lblDE.Size = new Size(34, 25);
|
||||||
lblDE.TabIndex = 2;
|
lblDE.TabIndex = 2;
|
||||||
lblDE.Text = "DE";
|
lblDE.Text = "DE";
|
||||||
//
|
//
|
||||||
// lblHL
|
// lblHL
|
||||||
//
|
//
|
||||||
lblHL.AutoSize = true;
|
lblHL.AutoSize = true;
|
||||||
lblHL.Location = new Point(10, 150);
|
lblHL.Location = new Point(12, 188);
|
||||||
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(27, 20);
|
lblHL.Size = new Size(33, 25);
|
||||||
lblHL.TabIndex = 3;
|
lblHL.TabIndex = 3;
|
||||||
lblHL.Text = "HL";
|
lblHL.Text = "HL";
|
||||||
//
|
//
|
||||||
// lblPC
|
// lblPC
|
||||||
//
|
//
|
||||||
lblPC.AutoSize = true;
|
lblPC.AutoSize = true;
|
||||||
lblPC.Location = new Point(9, 200);
|
lblPC.Location = new Point(11, 250);
|
||||||
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(26, 20);
|
lblPC.Size = new Size(33, 25);
|
||||||
lblPC.TabIndex = 4;
|
lblPC.TabIndex = 4;
|
||||||
lblPC.Text = "PC";
|
lblPC.Text = "PC";
|
||||||
//
|
//
|
||||||
// lblSP
|
// lblSP
|
||||||
//
|
//
|
||||||
lblSP.AutoSize = true;
|
lblSP.AutoSize = true;
|
||||||
lblSP.Location = new Point(9, 252);
|
lblSP.Location = new Point(11, 315);
|
||||||
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(25, 20);
|
lblSP.Size = new Size(32, 25);
|
||||||
lblSP.TabIndex = 6;
|
lblSP.TabIndex = 6;
|
||||||
lblSP.Text = "SP";
|
lblSP.Text = "SP";
|
||||||
//
|
//
|
||||||
// lblFlags
|
// lblFlags
|
||||||
//
|
//
|
||||||
lblFlags.AutoSize = true;
|
lblFlags.AutoSize = true;
|
||||||
lblFlags.Location = new Point(88, 52);
|
lblFlags.Location = new Point(110, 65);
|
||||||
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(43, 20);
|
lblFlags.Size = new Size(53, 25);
|
||||||
lblFlags.TabIndex = 7;
|
lblFlags.TabIndex = 7;
|
||||||
lblFlags.Text = "Flags";
|
lblFlags.Text = "Flags";
|
||||||
//
|
//
|
||||||
// lblTStates
|
// lblTStates
|
||||||
//
|
//
|
||||||
lblTStates.AutoSize = true;
|
lblTStates.AutoSize = true;
|
||||||
lblTStates.Location = new Point(88, 7);
|
lblTStates.Location = new Point(110, 9);
|
||||||
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(63, 20);
|
lblTStates.Size = new Size(75, 25);
|
||||||
lblTStates.TabIndex = 8;
|
lblTStates.TabIndex = 8;
|
||||||
lblTStates.Text = "T-States";
|
lblTStates.Text = "T-States";
|
||||||
//
|
//
|
||||||
// txtMemoryStart
|
// txtMemoryStart
|
||||||
//
|
//
|
||||||
txtMemoryStart.Location = new Point(300, 21);
|
txtMemoryStart.Location = new Point(375, 26);
|
||||||
txtMemoryStart.Margin = new Padding(2);
|
txtMemoryStart.Margin = new Padding(2);
|
||||||
txtMemoryStart.Name = "txtMemoryStart";
|
txtMemoryStart.Name = "txtMemoryStart";
|
||||||
txtMemoryStart.Size = new Size(121, 27);
|
txtMemoryStart.Size = new Size(150, 31);
|
||||||
txtMemoryStart.TabIndex = 9;
|
txtMemoryStart.TabIndex = 9;
|
||||||
txtMemoryStart.Text = "Memory Start";
|
txtMemoryStart.Text = "Memory Start";
|
||||||
txtMemoryStart.TextAlign = HorizontalAlignment.Center;
|
txtMemoryStart.TextAlign = HorizontalAlignment.Center;
|
||||||
@@ -153,10 +153,10 @@
|
|||||||
//
|
//
|
||||||
// btnRefreshMemory
|
// btnRefreshMemory
|
||||||
//
|
//
|
||||||
btnRefreshMemory.Location = new Point(425, 21);
|
btnRefreshMemory.Location = new Point(531, 26);
|
||||||
btnRefreshMemory.Margin = new Padding(2);
|
btnRefreshMemory.Margin = new Padding(2);
|
||||||
btnRefreshMemory.Name = "btnRefreshMemory";
|
btnRefreshMemory.Name = "btnRefreshMemory";
|
||||||
btnRefreshMemory.Size = new Size(90, 27);
|
btnRefreshMemory.Size = new Size(112, 34);
|
||||||
btnRefreshMemory.TabIndex = 14;
|
btnRefreshMemory.TabIndex = 14;
|
||||||
btnRefreshMemory.Text = "Refresh Memory";
|
btnRefreshMemory.Text = "Refresh Memory";
|
||||||
btnRefreshMemory.UseVisualStyleBackColor = true;
|
btnRefreshMemory.UseVisualStyleBackColor = true;
|
||||||
@@ -164,109 +164,117 @@
|
|||||||
//
|
//
|
||||||
// txtMemoryView
|
// txtMemoryView
|
||||||
//
|
//
|
||||||
txtMemoryView.Location = new Point(88, 80);
|
txtMemoryView.Location = new Point(110, 100);
|
||||||
txtMemoryView.Margin = new Padding(2);
|
txtMemoryView.Margin = new Padding(2);
|
||||||
txtMemoryView.Name = "txtMemoryView";
|
txtMemoryView.Name = "txtMemoryView";
|
||||||
txtMemoryView.Size = new Size(443, 895);
|
txtMemoryView.Size = new Size(553, 1118);
|
||||||
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.Location = new Point(567, 8);
|
lstDisassembly.ItemHeight = 25;
|
||||||
|
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(252, 264);
|
lstDisassembly.Size = new Size(314, 329);
|
||||||
lstDisassembly.TabIndex = 16;
|
lstDisassembly.TabIndex = 16;
|
||||||
//
|
//
|
||||||
// lstStack
|
// lstStack
|
||||||
//
|
//
|
||||||
lstStack.FormattingEnabled = true;
|
lstStack.FormattingEnabled = true;
|
||||||
lstStack.Location = new Point(823, 8);
|
lstStack.ItemHeight = 25;
|
||||||
|
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(130, 264);
|
lstStack.Size = new Size(162, 329);
|
||||||
lstStack.TabIndex = 17;
|
lstStack.TabIndex = 17;
|
||||||
//
|
//
|
||||||
// label1
|
// label1
|
||||||
//
|
//
|
||||||
label1.AutoSize = true;
|
label1.AutoSize = true;
|
||||||
label1.Location = new Point(568, 298);
|
label1.Location = new Point(710, 372);
|
||||||
|
label1.Margin = new Padding(4, 0, 4, 0);
|
||||||
label1.Name = "label1";
|
label1.Name = "label1";
|
||||||
label1.Size = new Size(81, 20);
|
label1.Size = new Size(97, 25);
|
||||||
label1.TabIndex = 19;
|
label1.TabIndex = 19;
|
||||||
label1.Text = "Breakpoint";
|
label1.Text = "Breakpoint";
|
||||||
//
|
//
|
||||||
// txtBreakpoint
|
// txtBreakpoint
|
||||||
//
|
//
|
||||||
txtBreakpoint.Location = new Point(655, 295);
|
txtBreakpoint.Location = new Point(819, 369);
|
||||||
|
txtBreakpoint.Margin = new Padding(4);
|
||||||
txtBreakpoint.Name = "txtBreakpoint";
|
txtBreakpoint.Name = "txtBreakpoint";
|
||||||
txtBreakpoint.Size = new Size(125, 27);
|
txtBreakpoint.Size = new Size(155, 31);
|
||||||
txtBreakpoint.TabIndex = 20;
|
txtBreakpoint.TabIndex = 20;
|
||||||
//
|
//
|
||||||
// label2
|
// label2
|
||||||
//
|
//
|
||||||
label2.AutoSize = true;
|
label2.AutoSize = true;
|
||||||
label2.Location = new Point(233, 21);
|
label2.Location = new Point(291, 26);
|
||||||
|
label2.Margin = new Padding(4, 0, 4, 0);
|
||||||
label2.Name = "label2";
|
label2.Name = "label2";
|
||||||
label2.Size = new Size(62, 20);
|
label2.Size = new Size(77, 25);
|
||||||
label2.TabIndex = 21;
|
label2.TabIndex = 21;
|
||||||
label2.Text = "Address";
|
label2.Text = "Address";
|
||||||
//
|
//
|
||||||
// lblIX
|
// lblIX
|
||||||
//
|
//
|
||||||
lblIX.AutoSize = true;
|
lblIX.AutoSize = true;
|
||||||
lblIX.Location = new Point(9, 298);
|
lblIX.Location = new Point(11, 372);
|
||||||
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(22, 20);
|
lblIX.Size = new Size(28, 25);
|
||||||
lblIX.TabIndex = 22;
|
lblIX.TabIndex = 22;
|
||||||
lblIX.Text = "IX";
|
lblIX.Text = "IX";
|
||||||
//
|
//
|
||||||
// lblIY
|
// lblIY
|
||||||
//
|
//
|
||||||
lblIY.AutoSize = true;
|
lblIY.AutoSize = true;
|
||||||
lblIY.Location = new Point(10, 344);
|
lblIY.Location = new Point(12, 430);
|
||||||
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(21, 20);
|
lblIY.Size = new Size(27, 25);
|
||||||
lblIY.TabIndex = 23;
|
lblIY.TabIndex = 23;
|
||||||
lblIY.Text = "IY";
|
lblIY.Text = "IY";
|
||||||
//
|
//
|
||||||
// lblIff1
|
// lblIff1
|
||||||
//
|
//
|
||||||
lblIff1.AutoSize = true;
|
lblIff1.AutoSize = true;
|
||||||
lblIff1.Location = new Point(567, 411);
|
lblIff1.Location = new Point(709, 514);
|
||||||
|
lblIff1.Margin = new Padding(4, 0, 4, 0);
|
||||||
lblIff1.Name = "lblIff1";
|
lblIff1.Name = "lblIff1";
|
||||||
lblIff1.Size = new Size(35, 20);
|
lblIff1.Size = new Size(45, 25);
|
||||||
lblIff1.TabIndex = 24;
|
lblIff1.TabIndex = 24;
|
||||||
lblIff1.Text = "IFF1";
|
lblIff1.Text = "IFF1";
|
||||||
//
|
//
|
||||||
// lblIff2
|
// lblIff2
|
||||||
//
|
//
|
||||||
lblIff2.AutoSize = true;
|
lblIff2.AutoSize = true;
|
||||||
lblIff2.Location = new Point(567, 458);
|
lblIff2.Location = new Point(709, 572);
|
||||||
|
lblIff2.Margin = new Padding(4, 0, 4, 0);
|
||||||
lblIff2.Name = "lblIff2";
|
lblIff2.Name = "lblIff2";
|
||||||
lblIff2.Size = new Size(35, 20);
|
lblIff2.Size = new Size(45, 25);
|
||||||
lblIff2.TabIndex = 25;
|
lblIff2.TabIndex = 25;
|
||||||
lblIff2.Text = "IFF2";
|
lblIff2.Text = "IFF2";
|
||||||
//
|
//
|
||||||
// lblIE
|
// lblIE
|
||||||
//
|
//
|
||||||
lblIE.AutoSize = true;
|
lblIE.AutoSize = true;
|
||||||
lblIE.Location = new Point(568, 370);
|
lblIE.Location = new Point(710, 462);
|
||||||
|
lblIE.Margin = new Padding(4, 0, 4, 0);
|
||||||
lblIE.Name = "lblIE";
|
lblIE.Name = "lblIE";
|
||||||
lblIE.Size = new Size(109, 20);
|
lblIE.Size = new Size(133, 25);
|
||||||
lblIE.TabIndex = 26;
|
lblIE.TabIndex = 26;
|
||||||
lblIE.Text = "Interrupt Mode";
|
lblIE.Text = "Interrupt Mode";
|
||||||
//
|
//
|
||||||
// btnReset
|
// btnReset
|
||||||
//
|
//
|
||||||
btnReset.Location = new Point(651, 327);
|
btnReset.Location = new Point(814, 409);
|
||||||
btnReset.Margin = new Padding(2);
|
btnReset.Margin = new Padding(2);
|
||||||
btnReset.Name = "btnReset";
|
btnReset.Name = "btnReset";
|
||||||
btnReset.Size = new Size(132, 27);
|
btnReset.Size = new Size(165, 34);
|
||||||
btnReset.TabIndex = 27;
|
btnReset.TabIndex = 27;
|
||||||
btnReset.Text = "Set Breakpoint";
|
btnReset.Text = "Set Breakpoint";
|
||||||
btnReset.UseVisualStyleBackColor = true;
|
btnReset.UseVisualStyleBackColor = true;
|
||||||
@@ -281,69 +289,72 @@
|
|||||||
// lblFrames
|
// lblFrames
|
||||||
//
|
//
|
||||||
lblFrames.AutoSize = true;
|
lblFrames.AutoSize = true;
|
||||||
lblFrames.Location = new Point(567, 682);
|
lblFrames.Location = new Point(709, 852);
|
||||||
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(124, 20);
|
lblFrames.Size = new Size(149, 25);
|
||||||
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(659, 759);
|
lblFPS.Location = new Point(824, 949);
|
||||||
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(32, 20);
|
lblFPS.Size = new Size(41, 25);
|
||||||
lblFPS.TabIndex = 29;
|
lblFPS.TabIndex = 29;
|
||||||
lblFPS.Text = "FPS";
|
lblFPS.Text = "FPS";
|
||||||
//
|
//
|
||||||
// lblFrameTime
|
// lblFrameTime
|
||||||
//
|
//
|
||||||
lblFrameTime.AutoSize = true;
|
lblFrameTime.AutoSize = true;
|
||||||
lblFrameTime.Location = new Point(604, 718);
|
lblFrameTime.Location = new Point(755, 898);
|
||||||
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(87, 20);
|
lblFrameTime.Size = new Size(104, 25);
|
||||||
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(567, 509);
|
richTextBox1.Location = new Point(709, 636);
|
||||||
|
richTextBox1.Margin = new Padding(4);
|
||||||
richTextBox1.Name = "richTextBox1";
|
richTextBox1.Name = "richTextBox1";
|
||||||
richTextBox1.ReadOnly = true;
|
richTextBox1.ReadOnly = true;
|
||||||
richTextBox1.Size = new Size(304, 128);
|
richTextBox1.Size = new Size(379, 159);
|
||||||
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
|
// button1
|
||||||
//
|
//
|
||||||
button1.Location = new Point(555, 824);
|
button1.Location = new Point(694, 1030);
|
||||||
|
button1.Margin = new Padding(4);
|
||||||
button1.Name = "button1";
|
button1.Name = "button1";
|
||||||
button1.Size = new Size(94, 29);
|
button1.Size = new Size(118, 36);
|
||||||
button1.TabIndex = 33;
|
button1.TabIndex = 33;
|
||||||
button1.Text = "CPU Step";
|
button1.Text = "CPU Step";
|
||||||
button1.UseVisualStyleBackColor = true;
|
button1.UseVisualStyleBackColor = true;
|
||||||
button1.Click += btnStep_Click;
|
button1.Click += btnStep_Click;
|
||||||
//
|
//
|
||||||
// button2
|
// CpuRun
|
||||||
//
|
//
|
||||||
button2.Location = new Point(555, 883);
|
CpuRun.Location = new Point(694, 1104);
|
||||||
button2.Name = "button2";
|
CpuRun.Margin = new Padding(4);
|
||||||
button2.Size = new Size(94, 29);
|
CpuRun.Name = "CpuRun";
|
||||||
button2.TabIndex = 34;
|
CpuRun.Size = new Size(118, 36);
|
||||||
button2.Text = "CPU Run";
|
CpuRun.TabIndex = 34;
|
||||||
button2.UseVisualStyleBackColor = true;
|
CpuRun.Text = "CPU Run";
|
||||||
button2.Click += btnStep_Click;
|
CpuRun.UseVisualStyleBackColor = true;
|
||||||
|
CpuRun.Click += CpuRun_Click;
|
||||||
//
|
//
|
||||||
// DebuggerForm
|
// DebuggerForm
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(8F, 20F);
|
AutoScaleDimensions = new SizeF(10F, 25F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
ClientSize = new Size(965, 990);
|
ClientSize = new Size(1206, 1238);
|
||||||
Controls.Add(button2);
|
Controls.Add(CpuRun);
|
||||||
Controls.Add(button1);
|
Controls.Add(button1);
|
||||||
Controls.Add(richTextBox1);
|
Controls.Add(richTextBox1);
|
||||||
Controls.Add(lblFrameTime);
|
Controls.Add(lblFrameTime);
|
||||||
@@ -402,13 +413,13 @@
|
|||||||
private Label lblIff2;
|
private Label lblIff2;
|
||||||
private Label lblIE;
|
private Label lblIE;
|
||||||
private Button btnReset;
|
private Button btnReset;
|
||||||
private System.Windows.Forms.Timer uiUpdateTimer;
|
|
||||||
private Label lblFrames;
|
private Label lblFrames;
|
||||||
private Label lblFPS;
|
private Label lblFPS;
|
||||||
private Label lblFrameTime;
|
private Label lblFrameTime;
|
||||||
private RichTextBox richTextBox1;
|
private RichTextBox richTextBox1;
|
||||||
private Button button1;
|
private Button button1;
|
||||||
private Button button2;
|
private Button CpuRun;
|
||||||
|
public System.Windows.Forms.Timer uiUpdateTimer;
|
||||||
//private TextBox textBox4;
|
//private TextBox textBox4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,11 +27,36 @@ namespace Desktop
|
|||||||
_mainForm = mainForm;
|
_mainForm = mainForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CpuRun_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_mainForm.IsRunning)
|
||||||
|
{
|
||||||
|
// Stop the machine
|
||||||
|
_mainForm.StopEmulator();
|
||||||
|
CpuRun.Text = "CPU Run";
|
||||||
|
|
||||||
|
// Stop the live UI updates and do one final manual refresh
|
||||||
|
uiUpdateTimer.Stop();
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Start the machine
|
||||||
|
_mainForm.StartEmulator();
|
||||||
|
CpuRun.Text = "CPU Stop";
|
||||||
|
|
||||||
|
// Start the timer so the debugger screen updates automatically
|
||||||
|
// (Make sure your uiUpdateTimer Interval in the designer is set to something like 100ms)
|
||||||
|
uiUpdateTimer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void btnStep_Click(object sender, EventArgs e)
|
private void btnStep_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_cpu.Step();
|
// Ask the main form to step the WHOLE machine, not just the Z80!
|
||||||
|
_mainForm.StepEmulator();
|
||||||
UpdateDisplay();
|
UpdateDisplay();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -57,7 +82,7 @@ namespace Desktop
|
|||||||
UpdateDisplay();
|
UpdateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uiUpdateTimer_Tick(object sender, EventArgs e)
|
public void uiUpdateTimer_Tick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
UpdateDisplay();
|
UpdateDisplay();
|
||||||
}
|
}
|
||||||
@@ -180,6 +205,9 @@ namespace Desktop
|
|||||||
case 0x02: mnemonic = "LD (BC), A"; break;
|
case 0x02: mnemonic = "LD (BC), A"; break;
|
||||||
// --- 16-Bit Increments ---
|
// --- 16-Bit Increments ---
|
||||||
case 0x03: mnemonic = "INC BC"; break;
|
case 0x03: mnemonic = "INC BC"; break;
|
||||||
|
case 0x07:
|
||||||
|
mnemonic = "RLCA";
|
||||||
|
break;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
mnemonic = "EX AF, AF'";
|
mnemonic = "EX AF, AF'";
|
||||||
break;
|
break;
|
||||||
|
|||||||
24
Desktop/Form1.Designer.cs
generated
24
Desktop/Form1.Designer.cs
generated
@@ -29,32 +29,48 @@
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
button1 = new Button();
|
button1 = new Button();
|
||||||
|
pbScreen = new PictureBox();
|
||||||
|
((System.ComponentModel.ISupportInitialize)pbScreen).BeginInit();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// button1
|
// button1
|
||||||
//
|
//
|
||||||
button1.Location = new Point(304, 268);
|
button1.Location = new Point(1294, 13);
|
||||||
|
button1.Margin = new Padding(4, 4, 4, 4);
|
||||||
button1.Name = "button1";
|
button1.Name = "button1";
|
||||||
button1.Size = new Size(94, 29);
|
button1.Size = new Size(118, 36);
|
||||||
button1.TabIndex = 0;
|
button1.TabIndex = 0;
|
||||||
button1.Text = "button1";
|
button1.Text = "button1";
|
||||||
button1.UseVisualStyleBackColor = true;
|
button1.UseVisualStyleBackColor = true;
|
||||||
button1.Click += button1_Click;
|
button1.Click += button1_Click;
|
||||||
//
|
//
|
||||||
|
// pbScreen
|
||||||
|
//
|
||||||
|
pbScreen.Location = new Point(23, 59);
|
||||||
|
pbScreen.Name = "pbScreen";
|
||||||
|
pbScreen.Size = new Size(1390, 760);
|
||||||
|
pbScreen.SizeMode = PictureBoxSizeMode.Zoom;
|
||||||
|
pbScreen.TabIndex = 1;
|
||||||
|
pbScreen.TabStop = false;
|
||||||
|
//
|
||||||
// Form1
|
// Form1
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(8F, 20F);
|
AutoScaleDimensions = new SizeF(10F, 25F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
ClientSize = new Size(800, 450);
|
ClientSize = new Size(1425, 842);
|
||||||
|
Controls.Add(pbScreen);
|
||||||
Controls.Add(button1);
|
Controls.Add(button1);
|
||||||
|
Margin = new Padding(4, 4, 4, 4);
|
||||||
Name = "Form1";
|
Name = "Form1";
|
||||||
Text = "Form1";
|
Text = "Form1";
|
||||||
Click += button1_Click;
|
Click += button1_Click;
|
||||||
|
((System.ComponentModel.ISupportInitialize)pbScreen).EndInit();
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private Button button1;
|
private Button button1;
|
||||||
|
private PictureBox pbScreen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,21 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.PortableExecutable;
|
using System.Reflection.PortableExecutable;
|
||||||
using Core;
|
using Core;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace Desktop
|
namespace Desktop
|
||||||
{
|
{
|
||||||
public partial class Form1 : Form
|
public partial class Form1 : Form
|
||||||
{
|
{
|
||||||
private SmsMachine _machine = null!;
|
private SmsMachine _machine = null!;
|
||||||
private DebuggerForm _debugger;
|
private DebuggerForm _debugger;
|
||||||
|
private Bitmap _screenBitmap = new Bitmap(256, 192, PixelFormat.Format32bppArgb);
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsRunning { get; private set; } = false;
|
||||||
|
|
||||||
public ushort? Breakpoint
|
public ushort? Breakpoint
|
||||||
{
|
{
|
||||||
@@ -20,23 +29,67 @@ namespace Desktop
|
|||||||
_machine = new SmsMachine();
|
_machine = new SmsMachine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawScreen()
|
||||||
|
{
|
||||||
|
// Rapidly copy our VDP FrameBuffer into the Windows Bitmap
|
||||||
|
var data = _screenBitmap.LockBits(new Rectangle(0, 0, 256, 192), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||||
|
Marshal.Copy(_machine.VideoProcessor.FrameBuffer, 0, data.Scan0, _machine.VideoProcessor.FrameBuffer.Length);
|
||||||
|
_screenBitmap.UnlockBits(data);
|
||||||
|
|
||||||
|
// Update the PictureBox
|
||||||
|
pbScreen.Image = _screenBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartEmulator()
|
||||||
|
{
|
||||||
|
if (IsRunning) return;
|
||||||
|
IsRunning = true;
|
||||||
|
|
||||||
|
// Fire off a background task so we don't freeze the Windows UI!
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
while (IsRunning)
|
||||||
|
{
|
||||||
|
_machine.RunFrame();
|
||||||
|
|
||||||
|
Invoke((System.Windows.Forms.MethodInvoker)delegate { DrawScreen(); });
|
||||||
|
|
||||||
|
// Safety catch: If we hit a breakpoint while running, stop the loop!
|
||||||
|
if (_machine.Breakpoint.HasValue && _machine.Cpu.PC == _machine.Breakpoint.Value)
|
||||||
|
{
|
||||||
|
IsRunning = false;
|
||||||
|
|
||||||
|
// Optional: Force the debugger UI to update immediately so you see it!
|
||||||
|
Invoke((System.Windows.Forms.MethodInvoker)delegate { _debugger?.uiUpdateTimer_Tick(null, EventArgs.Empty); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Only throttle the speed if we are actively running
|
||||||
|
Thread.Sleep(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopEmulator()
|
||||||
|
{
|
||||||
|
IsRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void StepEmulator()
|
||||||
|
{
|
||||||
|
_machine.StepMachine();
|
||||||
|
}
|
||||||
|
|
||||||
private void button1_Click(object sender, EventArgs e)
|
private void button1_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// 1. Load a commercial Master System ROM!
|
// 1. Load a commercial Master System ROM!
|
||||||
|
|
||||||
byte[] rom = File.ReadAllBytes(@"C:\Parsons\Local Code Projects\ParsonsMasterSystem2026\Desktop\ROMS\Golden Axe Warrior.sms");
|
byte[] rom = File.ReadAllBytes(@"C:\Parsons\Local Code Projects\ParsonsMasterSystem2026\Desktop\ROMS\Golden Axe Warrior.sms");
|
||||||
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
// 2. Jam it into the Sega Mapper
|
// 2. Jam it into the Sega Mapper
|
||||||
_machine.LoadCartridge(rom);
|
_machine.LoadCartridge(rom);
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show(ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Open the Debugger to look around
|
// 3. Open the Debugger to look around
|
||||||
if (_debugger == null || _debugger.IsDisposed)
|
if (_debugger == null || _debugger.IsDisposed)
|
||||||
|
|||||||
Reference in New Issue
Block a user