Added flash attribute. Implemented more OpCodes

This commit is contained in:
2026-04-17 02:34:11 +01:00
parent c74d2cc764
commit 389df3780e
3 changed files with 349 additions and 12 deletions

View File

@@ -582,7 +582,18 @@ namespace Desktop
case 0x85: mnemonic = "ADD A, L"; break;
case 0x86: mnemonic = "ADD A, (HL)"; break;
case 0x87: mnemonic = "ADD A, A"; break;
case 0x88:
case 0x89:
case 0x8A:
case 0x8B:
case 0x8C:
case 0x8D:
case 0x8E:
case 0x8F:
string[] registers = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
mnemonic = $"ADC A, {registers[opcode - 0x88]}";
instructionLength = 1;
break;
// --- SUB r ---
case 0x90: mnemonic = "SUB B"; break;
case 0x91: mnemonic = "SUB C"; break;
@@ -779,10 +790,15 @@ namespace Desktop
instructionLength = 2;
break;
case 0xCD:
ushort callDest = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
mnemonic = $"CALL 0x{callDest:X4}";
instructionLength = 3;
break;
ushort callDest = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
mnemonic = $"CALL 0x{callDest:X4}";
instructionLength = 3;
break;
case 0xCE: // ADC A, n
byte n = _memoryBus.Read((ushort)(currentPc + 1));
mnemonic = $"ADC A, 0x{n:X2}";
instructionLength = 2;
break;
case 0xD0:
mnemonic = "RET NC";
break;
@@ -809,13 +825,22 @@ namespace Desktop
case 0xDD:
{
byte ddOpcode = _memoryBus.Read((ushort)(currentPc + 1));
if (ddOpcode == 0x21) // LD IX, nn
if (ddOpcode == 0x09) // ADD IX, BC
{
mnemonic = "ADD IX, BC";
instructionLength = 2;
}
else if (ddOpcode == 0x21) // LD IX, nn
{
ushort ixVal = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
mnemonic = $"LD IX, 0x{ixVal:X4}";
instructionLength = 4;
}
else if (ddOpcode == 0xE9) // JP (IX)
{
mnemonic = "JP (IX)";
instructionLength = 2;
}
else
{
mnemonic = $"DD PREFIX UNKNOWN (0x{ddOpcode:X2})";
@@ -856,6 +881,10 @@ namespace Desktop
mnemonic = $"LD (0x{bcAddr:X4}), BC";
instructionLength = 4;
break;
case 0x44: // NEG
mnemonic = "NEG";
instructionLength = 2;
break;
case 0x47:
mnemonic = "LD I, A";
instructionLength = 2; // 0xED + 0x47
@@ -888,10 +917,19 @@ namespace Desktop
mnemonic = $"LD (0x{addr73:X4}), SP";
instructionLength = 4;
break;
case 0x72: // SBC HL, SP
mnemonic = "SBC HL, SP";
instructionLength = 2;
break;
case 0x78:
mnemonic = "IN A, (C)";
instructionLength = 2;
break;
case 0x7B: // LD SP, (nn)
ushort nn = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
mnemonic = $"LD SP, (0x{nn:X4})";
instructionLength = 4;
break;
case 0xB0:
mnemonic = "LDIR";
instructionLength = 2;
@@ -907,6 +945,11 @@ namespace Desktop
break;
}
break;
case 0xEE:
byte xorVal = _memoryBus.Read((ushort)(currentPc + 1));
mnemonic = $"XOR 0x{xorVal:X2}";
instructionLength = 2;
break;
case 0xF1: mnemonic = "POP AF"; break;
case 0xF3:
mnemonic = "DI";
@@ -935,6 +978,13 @@ namespace Desktop
mnemonic = $"LD IY, 0x{iyVal:X4}";
instructionLength = 4;
}
else if (fdOpcode == 0x34) // INC (IY+d)
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
string sign = d >= 0 ? "+" : "";
mnemonic = $"INC (IY{sign}{d})";
instructionLength = 3;
}
else if (fdOpcode == 0x35) // DEC (IY+d)
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
@@ -945,7 +995,7 @@ namespace Desktop
else if (fdOpcode == 0x36) // LD (IY+d), n
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
byte n = _memoryBus.Read((ushort)(currentPc + 3));
n = _memoryBus.Read((ushort)(currentPc + 3));
string sign = d >= 0 ? "+" : "";
mnemonic = $"LD (IY{sign}{d}), 0x{n:X2}";
instructionLength = 4;
@@ -987,6 +1037,13 @@ namespace Desktop
mnemonic = $"LD L, (IY{signL}{offsetL})";
instructionLength = 3;
}
else if (fdOpcode == 0x74) // LD (IY+d), H
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
string sign = d >= 0 ? "+" : "";
mnemonic = $"LD (IY{sign}{d}), H";
instructionLength = 3;
}
else if (fdOpcode == 0x86) // ADD A, (IY+d)
{
sbyte dAdd = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
@@ -995,6 +1052,13 @@ namespace Desktop
mnemonic = $"ADD A, (IY{signAdd}{dAdd})";
instructionLength = 3;
}
else if (fdOpcode == 0x96) // SUB (IY+d)
{
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
string sign = d >= 0 ? "+" : "";
mnemonic = $"SUB (IY{sign}{d})";
instructionLength = 3;
}
else if (fdOpcode == 0xCB) // FD CB prefix
{
cbOp = _memoryBus.Read((ushort)(currentPc + 1));

View File

@@ -14,6 +14,7 @@ namespace Desktop
private Z80 _cpu = null!;
private MemoryBus _memoryBus = null!;
private IO_Bus _simpleIoBus = null!;
private int _ulaFrameCount = 0;
// The 16 physical colors of the ZX Spectrum (ARGB format)
private readonly int[] SpectrumColors = new int[]
@@ -71,6 +72,10 @@ namespace Desktop
// Public so the Debugger's background thread can call it 50 times a second
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];
// Loop through the 6144 bytes of Pixel RAM
@@ -95,10 +100,18 @@ namespace Desktop
int ink = attr & 0x07;
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;
}
// Draw the 8 pixels
for (int bit = 0; bit < 8; bit++)
{