More keys. Implemented Border. Completes LOAD readiness sequence

This commit is contained in:
2026-04-18 01:55:08 +01:00
parent 389df3780e
commit 47f3a76bb2
5 changed files with 188 additions and 34 deletions

View File

@@ -822,6 +822,11 @@ namespace Desktop
case 0xD8:
mnemonic = "RET C";
break;
case 0xDB: // IN A, (n)
n = _memoryBus.Read((ushort)(currentPc + 1));
mnemonic = $"IN A, (0x{n:X2})";
instructionLength = 2;
break;
case 0xDD:
{
byte ddOpcode = _memoryBus.Read((ushort)(currentPc + 1));
@@ -836,6 +841,39 @@ namespace Desktop
mnemonic = $"LD IX, 0x{ixVal:X4}";
instructionLength = 4;
}
else if (ddOpcode == 0x36) // LD (IX+d), n
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
n = _memoryBus.Read((ushort)(currentPc + 3));
string sign = d >= 0 ? "+" : "";
mnemonic = $"LD (IX{sign}{d}), 0x{n:X2}";
instructionLength = 4;
}
else if (ddOpcode == 0x74) // LD (IX+d), H
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
string sign = d >= 0 ? "+" : "";
mnemonic = $"LD (IX{sign}{d}), H";
instructionLength = 3;
}
else if (ddOpcode == 0x75) // LD (IX+d), L
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
string sign = d >= 0 ? "+" : "";
mnemonic = $"LD (IX{sign}{d}), L";
instructionLength = 3;
}
else if (ddOpcode == 0xE1) // POP IX
{
mnemonic = "POP IX";
instructionLength = 2;
}
else if (ddOpcode == 0xE5) // PUSH IX
{
mnemonic = "PUSH IX";
instructionLength = 2;
}
else if (ddOpcode == 0xE9) // JP (IX)
{
mnemonic = "JP (IX)";
@@ -1037,6 +1075,13 @@ namespace Desktop
mnemonic = $"LD L, (IY{signL}{offsetL})";
instructionLength = 3;
}
else if (fdOpcode == 0x72) // LD (IY+d), D
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
string sign = d >= 0 ? "+" : "";
mnemonic = $"LD (IY{sign}{d}), D";
instructionLength = 3;
}
else if (fdOpcode == 0x74) // LD (IY+d), H
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));

View File

@@ -34,21 +34,24 @@
//
// picScreen
//
picScreen.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
picScreen.BackColor = Color.Black;
picScreen.Location = new Point(12, 12);
picScreen.Location = new Point(13, 13);
picScreen.Margin = new Padding(4);
picScreen.Name = "picScreen";
picScreen.Size = new Size(768, 576);
picScreen.Size = new Size(960, 768);
picScreen.SizeMode = PictureBoxSizeMode.Zoom;
picScreen.TabIndex = 0;
picScreen.TabStop = false;
//
// Form1
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleDimensions = new SizeF(10F, 25F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(791, 596);
ClientSize = new Size(987, 791);
Controls.Add(picScreen);
KeyPreview = true;
Margin = new Padding(4);
Name = "Form1";
Text = "Parsons Sinclair ZX Spectrum 48K - 2026";
((System.ComponentModel.ISupportInitialize)picScreen).EndInit();

View File

@@ -73,10 +73,19 @@ namespace Desktop
public void RenderScreen()
{
_ulaFrameCount++;
// The Spectrum flashes every 16 frames.
// This boolean flips between true and false every 16 frames.
bool invertFlashPhase = (_ulaFrameCount % 32) >= 16;
int[] pixelData = new int[256 * 192];
// --- NEW: Expanded screen size (32px border on all sides) ---
const int screenWidth = 320;
const int screenHeight = 256;
const int borderSize = 32;
int[] pixelData = new int[screenWidth * screenHeight];
// --- NEW: Fill the background with the Border Color ---
// (Note: The hardware border always uses standard brightness, never bright)
int currentBorderColor = SpectrumColors[_simpleIoBus.BorderColorIndex];
Array.Fill(pixelData, currentBorderColor);
// Loop through the 6144 bytes of Pixel RAM
for (int offset = 0; offset < 6144; offset++)
@@ -84,14 +93,12 @@ namespace Desktop
ushort address = (ushort)(0x4000 + offset);
byte pixels = _memoryBus.Read(address);
// Unwind the Sinclair interlace
int y = ((offset & 0x0700) >> 8) |
((offset & 0x00E0) >> 2) |
((offset & 0x1800) >> 5);
int x = (offset & 0x001F) * 8;
// Fetch Color Attributes
int attrRow = y / 8;
int attrCol = x / 8;
ushort attrAddress = (ushort)(0x5800 + (attrRow * 32) + attrCol);
@@ -101,12 +108,12 @@ namespace Desktop
int paper = (attr >> 3) & 0x07;
int brightOffset = (attr & 0x40) != 0 ? 8 : 0;
bool isFlashSet = (attr & 0x80) != 0;
int inkColor = SpectrumColors[ink + brightOffset];
int paperColor = SpectrumColors[paper + brightOffset];
if (isFlashSet && invertFlashPhase)
{
// Swap the ink and paper colors for this character block!
int temp = inkColor;
inkColor = paperColor;
paperColor = temp;
@@ -116,14 +123,20 @@ namespace Desktop
for (int bit = 0; bit < 8; bit++)
{
bool isPixelSet = (pixels & (1 << (7 - bit))) != 0;
pixelData[(y * 256) + (x + bit)] = isPixelSet ? inkColor : paperColor;
// --- NEW: Add the 32px border offset to our X and Y calculations! ---
int renderY = y + borderSize;
int renderX = x + borderSize + bit;
// Map it to our new, wider pixel array
pixelData[(renderY * screenWidth) + renderX] = isPixelSet ? inkColor : paperColor;
}
}
// Blast it to the PictureBox
Bitmap bmp = new Bitmap(256, 192, PixelFormat.Format32bppArgb);
// --- NEW: Update Bitmap dimensions to match the new 320x256 array ---
Bitmap bmp = new Bitmap(screenWidth, screenHeight, PixelFormat.Format32bppArgb);
BitmapData bmpData = bmp.LockBits(
new Rectangle(0, 0, 256, 192),
new Rectangle(0, 0, screenWidth, screenHeight),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
@@ -133,8 +146,6 @@ namespace Desktop
if (picScreen.Image != null) picScreen.Image.Dispose();
picScreen.Image = bmp;
}
// Helper method to update the IO Bus state
private void UpdateMatrix(int row, int col, bool isPressed)
{
if (isPressed)
@@ -167,6 +178,16 @@ namespace Desktop
{
switch (key)
{
// Row 1: A, S, D, F, G
case Keys.A: UpdateMatrix(1, 0, isPressed); break;
case Keys.S: UpdateMatrix(1, 1, isPressed); break;
case Keys.D: UpdateMatrix(1, 2, isPressed); break;
case Keys.F: UpdateMatrix(1, 3, isPressed); break;
case Keys.G: UpdateMatrix(1, 4, isPressed); break;
// Row 5:
case Keys.P: UpdateMatrix(5, 0, isPressed); break;
// Row 6: ENTER, L, K, J, H
case Keys.Enter: UpdateMatrix(6, 0, isPressed); break;
case Keys.L: UpdateMatrix(6, 1, isPressed); break;
@@ -179,21 +200,12 @@ namespace Desktop
case Keys.M: UpdateMatrix(7, 2, isPressed); break;
case Keys.N: UpdateMatrix(7, 3, isPressed); break;
case Keys.B: UpdateMatrix(7, 4, isPressed); break;
case Keys.ControlKey: UpdateMatrix(7, 1, isPressed); break; // Symbol Shift
// Row 1: A, S, D, F, G
case Keys.A: UpdateMatrix(1, 0, isPressed); break;
case Keys.S: UpdateMatrix(1, 1, isPressed); break;
case Keys.D: UpdateMatrix(1, 2, isPressed); break;
case Keys.F: UpdateMatrix(1, 3, isPressed); break;
case Keys.G: UpdateMatrix(1, 4, isPressed); break;
// Map the rest of the alphabet and numbers here as you need them!
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
}
}
}
}