More keys. Implemented Border. Completes LOAD readiness sequence
This commit is contained in:
@@ -1009,6 +1009,17 @@ namespace Core.Cpu
|
||||
if ((AF.Low & 0x01) != 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xDB: // IN A, (n)
|
||||
// 1. Fetch the immediate port offset byte
|
||||
byte portOffsetDB = FetchByte();
|
||||
|
||||
// 2. The Z80 puts 'A' on the top 8 bits, and 'n' on the bottom 8 bits
|
||||
ushort portAddressDB = (ushort)((AF.High << 8) | portOffsetDB);
|
||||
|
||||
// 3. Read from the I/O bus and store the result straight into the Accumulator
|
||||
AF.High = _simpleIoBus.ReadPort(portAddressDB);
|
||||
|
||||
return 11;
|
||||
case 0xE2: // JP PO, nn (Parity Odd / No Overflow)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
@@ -1251,7 +1262,7 @@ namespace Core.Cpu
|
||||
throw new NotImplementedException($"Opcode 0x{opcode:X2} at PC 0x{(PC - 1):X4} is not implemented.");
|
||||
}
|
||||
}
|
||||
private int ExecuteExtendedPrefix()
|
||||
private int ExecuteExtendedPrefix() //ED
|
||||
{
|
||||
// Fetch the actual extended instruction
|
||||
byte extendedOpcode = _memory.Read(PC++);
|
||||
@@ -1376,6 +1387,9 @@ namespace Core.Cpu
|
||||
AF.Low = newFlags;
|
||||
|
||||
return 12;
|
||||
case 0x79: // OUT (C), A
|
||||
_simpleIoBus.WritePort(BC.Word, AF.High);
|
||||
return 12; // 12 T-States
|
||||
case 0x7B: // LD SP, (nn)
|
||||
// 1. Fetch the absolute 16-bit memory address from the instruction stream
|
||||
byte addrLow = FetchByte();
|
||||
@@ -1596,6 +1610,65 @@ namespace Core.Cpu
|
||||
IX.Word = (ushort)((high << 8) | low);
|
||||
|
||||
return 14;
|
||||
case 0x36: // LD (IX+d), n
|
||||
// 1. Fetch the displacement byte first
|
||||
sbyte offset36 = (sbyte)FetchByte();
|
||||
|
||||
// 2. Fetch the immediate 8-bit value second
|
||||
byte n36 = FetchByte();
|
||||
|
||||
// 3. Calculate the exact memory address (IX + offset)
|
||||
ushort address36 = (ushort)(IX.Word + offset36);
|
||||
|
||||
// 4. Write the immediate value directly into memory
|
||||
_memory.Write(address36, n36);
|
||||
|
||||
return 19;
|
||||
case 0x74: // LD (IX+d), H
|
||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||
sbyte offset74 = (sbyte)FetchByte();
|
||||
|
||||
// 2. Calculate the exact memory address (IX + offset)
|
||||
ushort address74 = (ushort)(IX.Word + offset74);
|
||||
|
||||
// 3. Write the contents of the L register (Low byte of HL) into memory
|
||||
_memory.Write(address74, HL.High);
|
||||
|
||||
return 19;
|
||||
case 0x75: // LD (IX+d), L
|
||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||
sbyte offset75 = (sbyte)FetchByte();
|
||||
|
||||
// 2. Calculate the exact memory address (IX + offset)
|
||||
ushort address75 = (ushort)(IX.Word + offset75);
|
||||
|
||||
// 3. Write the contents of the L register (Low byte of HL) into memory
|
||||
_memory.Write(address75, HL.Low);
|
||||
|
||||
return 19;
|
||||
case 0xE1: // POP IX
|
||||
// 1. Read the low byte from the top of the stack
|
||||
byte popLow = _memory.Read(SP);
|
||||
SP++; // Move stack pointer up
|
||||
|
||||
// 2. Read the high byte
|
||||
byte popHigh = _memory.Read(SP);
|
||||
SP++; // Move stack pointer up again
|
||||
|
||||
// 3. Combine them and store in IX
|
||||
IX.Word = (ushort)((popHigh << 8) | popLow);
|
||||
|
||||
return 14;
|
||||
case 0xE5: // PUSH IX
|
||||
// 1. Decrement the stack pointer and write the HIGH byte
|
||||
SP--;
|
||||
_memory.Write(SP, IX.High);
|
||||
|
||||
// 2. Decrement the stack pointer again and write the LOW byte
|
||||
SP--;
|
||||
_memory.Write(SP, IX.Low);
|
||||
|
||||
return 15;
|
||||
case 0xE9: // JP (IX)
|
||||
PC = IX.Word;
|
||||
return 8;
|
||||
@@ -1727,6 +1800,17 @@ namespace Core.Cpu
|
||||
_memory.Write(targetAddress, BC.Low);
|
||||
return 19; // Takes 19 T-States
|
||||
}
|
||||
case 0x72: // LD (IY+d), D
|
||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||
sbyte offset72 = (sbyte)FetchByte();
|
||||
|
||||
// 2. Calculate the exact memory address (IY + offset)
|
||||
ushort address72 = (ushort)(IY.Word + offset72);
|
||||
|
||||
// 3. Write the contents of the D register (High byte of DE) into memory
|
||||
_memory.Write(address72, DE.High);
|
||||
|
||||
return 19; // 19 T-States
|
||||
case 0x74: // LD (IY+d), H
|
||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||
sbyte offset74 = (sbyte)FetchByte();
|
||||
|
||||
@@ -5,8 +5,10 @@ namespace Core.Io
|
||||
{
|
||||
public class IO_Bus
|
||||
{
|
||||
// 8 rows representing the Spectrum keyboard matrix. Default to 0xFF (unpressed).
|
||||
public byte[] KeyboardRows = new byte[8] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
public byte BorderColorIndex { get; private set; } = 7; // 7 is White
|
||||
|
||||
// 8 rows representing the Spectrum keyboard matrix. Default to 0xFF (unpressed).
|
||||
public byte[] KeyboardRows = new byte[8] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
public byte ReadPort(ushort portAddress)
|
||||
{
|
||||
@@ -35,9 +37,17 @@ namespace Core.Io
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
public void WritePort(ushort portAddress, byte portValue)
|
||||
public void WritePort(ushort portAddress, byte portValue)
|
||||
{
|
||||
// The ULA intercepts any write to an even port address
|
||||
if ((portAddress & 0x01) == 0)
|
||||
{
|
||||
// The bottom 3 bits (0-2) define the border color!
|
||||
BorderColorIndex = (byte)(portValue & 0x07);
|
||||
|
||||
// (Bits 3 and 4 handle the cassette MIC output and the internal speaker,
|
||||
// which we will need when we start playing audio!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user