3 ZEXALL tests now pass. Removed timing to speed up (temp)
This commit is contained in:
261
Core/Cpu/Z80.cs
261
Core/Cpu/Z80.cs
@@ -445,6 +445,34 @@ namespace Core.Cpu
|
|||||||
if (result < 0) AF.Low |= 0x01;
|
if (result < 0) AF.Low |= 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SbcHl(ushort value)
|
||||||
|
{
|
||||||
|
int op1 = HL.Word;
|
||||||
|
int op2 = value;
|
||||||
|
int carry = AF.Low & 0x01; // Current C flag
|
||||||
|
int result = op1 - op2 - carry;
|
||||||
|
|
||||||
|
byte flags = 0x02; // N: Always 1 (Subtract)
|
||||||
|
|
||||||
|
if (((result >> 8) & 0x80) != 0) flags |= 0x80; // S: Sign flag (Bit 15)
|
||||||
|
if ((result & 0xFFFF) == 0) flags |= 0x40; // Z: Zero flag
|
||||||
|
|
||||||
|
// H: Half-borrow from Bit 12
|
||||||
|
if ((((op1 & 0x0FFF) - (op2 & 0x0FFF) - carry) & 0x1000) != 0) flags |= 0x10;
|
||||||
|
|
||||||
|
// P/V: 16-bit Overflow logic
|
||||||
|
if ((((op1 ^ op2) & (op1 ^ result)) & 0x8000) != 0) flags |= 0x04;
|
||||||
|
|
||||||
|
// C: Borrow from Bit 15
|
||||||
|
if (result < 0) flags |= 0x01;
|
||||||
|
|
||||||
|
// Undocumented bits 3 and 5 come from the High byte of the calculated result
|
||||||
|
flags |= (byte)((result >> 8) & 0x28);
|
||||||
|
|
||||||
|
AF.Low = flags;
|
||||||
|
HL.Word = (ushort)(result & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
private byte Dec8(byte value)
|
private byte Dec8(byte value)
|
||||||
{
|
{
|
||||||
byte result = (byte)(value - 1);
|
byte result = (byte)(value - 1);
|
||||||
@@ -702,10 +730,67 @@ namespace Core.Cpu
|
|||||||
HL.Word = (ushort)result;
|
HL.Word = (ushort)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AdcHl(ushort value)
|
||||||
|
{
|
||||||
|
int op1 = HL.Word;
|
||||||
|
int op2 = value;
|
||||||
|
int carry = AF.Low & 0x01; // Current C flag
|
||||||
|
int result = op1 + op2 + carry;
|
||||||
|
|
||||||
|
byte flags = 0;
|
||||||
|
|
||||||
|
if (((result >> 8) & 0x80) != 0) flags |= 0x80; // S: Sign flag (Bit 15)
|
||||||
|
if ((result & 0xFFFF) == 0) flags |= 0x40; // Z: Zero flag
|
||||||
|
|
||||||
|
// H: Half-carry from Bit 11
|
||||||
|
if ((((op1 & 0x0FFF) + (op2 & 0x0FFF) + carry) & 0x1000) != 0) flags |= 0x10;
|
||||||
|
|
||||||
|
// P/V: 16-bit Overflow logic
|
||||||
|
if ((((op1 ^ ~op2) & (op1 ^ result)) & 0x8000) != 0) flags |= 0x04;
|
||||||
|
|
||||||
|
// N: Always 0 for Add
|
||||||
|
|
||||||
|
// C: Carry from Bit 15
|
||||||
|
if ((result & 0x10000) != 0) flags |= 0x01;
|
||||||
|
|
||||||
|
// Undocumented bits 3 and 5 come from the High byte of the calculated result
|
||||||
|
flags |= (byte)((result >> 8) & 0x28);
|
||||||
|
|
||||||
|
AF.Low = flags;
|
||||||
|
HL.Word = (ushort)(result & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddHl(ushort value)
|
||||||
|
{
|
||||||
|
int result = HL.Word + value;
|
||||||
|
|
||||||
|
// 1. Preserve S (0x80), Z (0x40), and P/V (0x04) from the current flag register
|
||||||
|
byte flags = (byte)(AF.Low & 0xC4);
|
||||||
|
|
||||||
|
// 2. Calculate H (Half-carry from bit 11)
|
||||||
|
if (((HL.Word & 0x0FFF) + (value & 0x0FFF)) > 0x0FFF)
|
||||||
|
{
|
||||||
|
flags |= 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Calculate C (Carry from bit 15)
|
||||||
|
if (result > 0xFFFF)
|
||||||
|
{
|
||||||
|
flags |= 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Undocumented bits 3 and 5 come from the High byte of the calculated result
|
||||||
|
flags |= (byte)((result >> 8) & 0x28);
|
||||||
|
|
||||||
|
// N is naturally left as 0 because of our initial bitmask
|
||||||
|
AF.Low = flags;
|
||||||
|
HL.Word = (ushort)result;
|
||||||
|
}
|
||||||
|
|
||||||
private void AddA(byte operand)
|
private void AddA(byte operand)
|
||||||
{
|
{
|
||||||
byte a = AF.High;
|
byte a = AF.High;
|
||||||
result = a + operand;
|
int result = a + operand; // Use a local int to easily catch the carry
|
||||||
|
|
||||||
AF.High = (byte)result;
|
AF.High = (byte)result;
|
||||||
|
|
||||||
@@ -728,8 +813,49 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
// Carry Flag (Bit 0) - Check if the whole 8-bit addition overflowed
|
// Carry Flag (Bit 0) - Check if the whole 8-bit addition overflowed
|
||||||
if (result > 0xFF) AF.Low |= 0x01;
|
if (result > 0xFF) AF.Low |= 0x01;
|
||||||
|
|
||||||
|
// UNDOCUMENTED FLAGS (Bits 3 and 5) - Copied directly from the result
|
||||||
|
AF.Low |= (byte)(AF.High & 0x28);
|
||||||
|
}
|
||||||
|
private void AddIx(ushort value)
|
||||||
|
{
|
||||||
|
int result = IX.Word + value;
|
||||||
|
|
||||||
|
// Preserve S, Z, and P/V
|
||||||
|
byte flags = (byte)(AF.Low & 0xC4);
|
||||||
|
|
||||||
|
// Calculate H (Half-carry from bit 11)
|
||||||
|
if (((IX.Word & 0x0FFF) + (value & 0x0FFF)) > 0x0FFF) flags |= 0x10;
|
||||||
|
|
||||||
|
// Calculate C (Carry from bit 15)
|
||||||
|
if (result > 0xFFFF) flags |= 0x01;
|
||||||
|
|
||||||
|
// Undocumented bits 3 and 5 from the High byte of the result
|
||||||
|
flags |= (byte)((result >> 8) & 0x28);
|
||||||
|
|
||||||
|
AF.Low = flags;
|
||||||
|
IX.Word = (ushort)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddIy(ushort value)
|
||||||
|
{
|
||||||
|
int result = IY.Word + value;
|
||||||
|
|
||||||
|
// Preserve S, Z, and P/V
|
||||||
|
byte flags = (byte)(AF.Low & 0xC4);
|
||||||
|
|
||||||
|
// Calculate H (Half-carry from bit 11)
|
||||||
|
if (((IY.Word & 0x0FFF) + (value & 0x0FFF)) > 0x0FFF) flags |= 0x10;
|
||||||
|
|
||||||
|
// Calculate C (Carry from bit 15)
|
||||||
|
if (result > 0xFFFF) flags |= 0x01;
|
||||||
|
|
||||||
|
// Undocumented bits 3 and 5 from the High byte of the result
|
||||||
|
flags |= (byte)((result >> 8) & 0x28);
|
||||||
|
|
||||||
|
AF.Low = flags;
|
||||||
|
IY.Word = (ushort)result;
|
||||||
|
}
|
||||||
private bool HasEvenParity(byte value)
|
private bool HasEvenParity(byte value)
|
||||||
{
|
{
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
@@ -805,6 +931,8 @@ namespace Core.Cpu
|
|||||||
AF.Word = AF_Prime.Word;
|
AF.Word = AF_Prime.Word;
|
||||||
AF_Prime.Word = tempAF;
|
AF_Prime.Word = tempAF;
|
||||||
return 4;
|
return 4;
|
||||||
|
// Inside your base switch(opcode) statement:
|
||||||
|
case 0x09: AddHl(BC.Word); return 11;
|
||||||
case 0x0A: //LD A (BC)
|
case 0x0A: //LD A (BC)
|
||||||
AF.High = ReadMemory(BC.Word);
|
AF.High = ReadMemory(BC.Word);
|
||||||
return 7;
|
return 7;
|
||||||
@@ -813,9 +941,11 @@ namespace Core.Cpu
|
|||||||
WriteMemory(DE.Word, AF.High);
|
WriteMemory(DE.Word, AF.High);
|
||||||
return 7;
|
return 7;
|
||||||
case 0x14: DE.High = Inc8(DE.High); return 4; // INC D
|
case 0x14: DE.High = Inc8(DE.High); return 4; // INC D
|
||||||
|
case 0x19: AddHl(DE.Word); return 11;
|
||||||
case 0x1C: DE.Low = Inc8(DE.Low); return 4; // INC E
|
case 0x1C: DE.Low = Inc8(DE.Low); return 4; // INC E
|
||||||
case 0x1E: DE.Low = FetchByte(); // LD E, n
|
case 0x1E: DE.Low = FetchByte(); // LD E, n
|
||||||
return 7;
|
return 7;
|
||||||
|
case 0x29: AddHl(HL.Word); return 11;
|
||||||
case 0x24: HL.High = Inc8(HL.High); return 4; // INC H
|
case 0x24: HL.High = Inc8(HL.High); return 4; // INC H
|
||||||
case 0x2C: HL.Low = Inc8(HL.Low); return 4; // INC L
|
case 0x2C: HL.Low = Inc8(HL.Low); return 4; // INC L
|
||||||
case 0x2E: // LD L, n
|
case 0x2E: // LD L, n
|
||||||
@@ -824,6 +954,7 @@ namespace Core.Cpu
|
|||||||
case 0x34:
|
case 0x34:
|
||||||
WriteMemory(HL.Word, Inc8(ReadMemory(HL.Word)));
|
WriteMemory(HL.Word, Inc8(ReadMemory(HL.Word)));
|
||||||
return 11; // INC (HL) takes 11 T-States
|
return 11; // INC (HL) takes 11 T-States
|
||||||
|
case 0x39: AddHl(SP); return 11;
|
||||||
case 0x3C: AF.High = Inc8(AF.High); return 4; // INC A
|
case 0x3C: AF.High = Inc8(AF.High); return 4; // INC A
|
||||||
|
|
||||||
// --- 8-Bit Decrements ---
|
// --- 8-Bit Decrements ---
|
||||||
@@ -849,19 +980,6 @@ namespace Core.Cpu
|
|||||||
case 0x06: // LD B, n
|
case 0x06: // LD B, n
|
||||||
BC.High = FetchByte();
|
BC.High = FetchByte();
|
||||||
return 7;
|
return 7;
|
||||||
// --- ADD HL, rr (16-bit Addition) ---
|
|
||||||
case 0x09:
|
|
||||||
Add16(BC.Word);
|
|
||||||
return 11;
|
|
||||||
case 0x19:
|
|
||||||
Add16(DE.Word);
|
|
||||||
return 11;
|
|
||||||
case 0x29:
|
|
||||||
Add16(HL.Word); // This perfectly multiplies HL by 2!
|
|
||||||
return 11;
|
|
||||||
case 0x39:
|
|
||||||
Add16(SP);
|
|
||||||
return 11;
|
|
||||||
case 0x0B: // DEC BC
|
case 0x0B: // DEC BC
|
||||||
BC.Word--;
|
BC.Word--;
|
||||||
return 6;
|
return 6;
|
||||||
@@ -1588,9 +1706,6 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
switch (extendedOpcode)
|
switch (extendedOpcode)
|
||||||
{
|
{
|
||||||
case 0x42: // SBC HL, BC
|
|
||||||
Sbc16(BC.Word);
|
|
||||||
return 15;
|
|
||||||
case 0x43: // LD (nn), BC
|
case 0x43: // LD (nn), BC
|
||||||
ushort dest43 = FetchWord();
|
ushort dest43 = FetchWord();
|
||||||
WriteMemory(dest43, BC.Low);
|
WriteMemory(dest43, BC.Low);
|
||||||
@@ -1626,10 +1741,7 @@ namespace Core.Cpu
|
|||||||
return 8; // 8 T-States
|
return 8; // 8 T-States
|
||||||
case 0x47: // LD I, A
|
case 0x47: // LD I, A
|
||||||
I = AF.High;
|
I = AF.High;
|
||||||
return 9;
|
return 9;
|
||||||
case 0x4A: // ADC HL, BC
|
|
||||||
Adc16(BC.Word);
|
|
||||||
return 15;
|
|
||||||
case 0x4B: // LD BC, (nn)
|
case 0x4B: // LD BC, (nn)
|
||||||
ushort src4B = FetchWord();
|
ushort src4B = FetchWord();
|
||||||
BC.Low = ReadMemory(src4B);
|
BC.Low = ReadMemory(src4B);
|
||||||
@@ -1638,9 +1750,6 @@ namespace Core.Cpu
|
|||||||
case 0x4D: // RETI Does not affect IFF1 or IFF2
|
case 0x4D: // RETI Does not affect IFF1 or IFF2
|
||||||
PC = Pop();
|
PC = Pop();
|
||||||
return 14;
|
return 14;
|
||||||
case 0x52: // SBC HL, DE
|
|
||||||
Sbc16(DE.Word);
|
|
||||||
return 15;
|
|
||||||
case 0x53: // LD (nn), DE
|
case 0x53: // LD (nn), DE
|
||||||
ushort dest53 = FetchWord();
|
ushort dest53 = FetchWord();
|
||||||
WriteMemory(dest53, DE.Low);
|
WriteMemory(dest53, DE.Low);
|
||||||
@@ -1677,9 +1786,6 @@ namespace Core.Cpu
|
|||||||
AF.Low = flags58;
|
AF.Low = flags58;
|
||||||
|
|
||||||
return 12;
|
return 12;
|
||||||
case 0x5A: // ADC HL, DE
|
|
||||||
Adc16(DE.Word);
|
|
||||||
return 15;
|
|
||||||
case 0x5B: // LD DE, (nn)
|
case 0x5B: // LD DE, (nn)
|
||||||
ushort src5B = FetchWord();
|
ushort src5B = FetchWord();
|
||||||
DE.Low = ReadMemory(src5B);
|
DE.Low = ReadMemory(src5B);
|
||||||
@@ -1710,46 +1816,11 @@ namespace Core.Cpu
|
|||||||
AF.Low = newFlags;
|
AF.Low = newFlags;
|
||||||
|
|
||||||
return 9;
|
return 9;
|
||||||
case 0x62: // SBC HL, HL
|
// --- SBC HL, rr ---
|
||||||
Sbc16(HL.Word);
|
case 0x42: SbcHl(BC.Word); return 15;
|
||||||
return 15;
|
case 0x52: SbcHl(DE.Word); return 15;
|
||||||
case 0x6A: // ADC HL, HL
|
case 0x62: SbcHl(HL.Word); return 15;
|
||||||
Adc16(HL.Word);
|
case 0x72: SbcHl(SP); return 15;
|
||||||
return 15;
|
|
||||||
case 0x72: // SBC HL, SP
|
|
||||||
int carryIn = AF.Low & 0x01;
|
|
||||||
int hlVal = HL.Word;
|
|
||||||
int spVal = SP;
|
|
||||||
|
|
||||||
// Perform the full 16-bit subtraction including the carry flag
|
|
||||||
result = hlVal - spVal - carryIn;
|
|
||||||
|
|
||||||
newFlags = 0;
|
|
||||||
|
|
||||||
// S Flag (Bit 7): Set if the 16-bit result is negative (Bit 15 is 1)
|
|
||||||
if ((result & 0x8000) != 0) newFlags |= 0x80;
|
|
||||||
|
|
||||||
// Z Flag (Bit 6): Set if the full 16-bit result is exactly 0
|
|
||||||
if ((result & 0xFFFF) == 0) newFlags |= 0x40;
|
|
||||||
|
|
||||||
// H Flag (Bit 4): Set if there was a borrow from Bit 11
|
|
||||||
if (((hlVal & 0x0FFF) - (spVal & 0x0FFF) - carryIn) < 0) newFlags |= 0x10;
|
|
||||||
|
|
||||||
// P/V Flag (Bit 2): Set on Overflow
|
|
||||||
// Overflow happens if the signs of the operands are different,
|
|
||||||
// AND the sign of the result is different from the original HL
|
|
||||||
if ((((hlVal ^ spVal) & (hlVal ^ result)) & 0x8000) != 0) newFlags |= 0x04;
|
|
||||||
|
|
||||||
// N Flag (Bit 1): Always set to 1 for a subtraction
|
|
||||||
newFlags |= 0x02;
|
|
||||||
|
|
||||||
// C Flag (Bit 0): Set if the total result underflows 0 (Borrow from Bit 15)
|
|
||||||
if (result < 0) newFlags |= 0x01;
|
|
||||||
|
|
||||||
AF.Low = newFlags;
|
|
||||||
HL.Word = (ushort)result;
|
|
||||||
|
|
||||||
return 15; // 15 T-States
|
|
||||||
case 0x73: // LD (nn), SP
|
case 0x73: // LD (nn), SP
|
||||||
ushort dest73 = FetchWord();
|
ushort dest73 = FetchWord();
|
||||||
WriteMemory(dest73, (byte)SP);
|
WriteMemory(dest73, (byte)SP);
|
||||||
@@ -1777,9 +1848,11 @@ namespace Core.Cpu
|
|||||||
case 0x79: // OUT (C), A
|
case 0x79: // OUT (C), A
|
||||||
_simpleIoBus.WritePort(BC.Word, AF.High);
|
_simpleIoBus.WritePort(BC.Word, AF.High);
|
||||||
return 12;
|
return 12;
|
||||||
case 0x7A: // ADC HL, SP
|
// --- ADC HL, rr ---
|
||||||
Adc16(SP);
|
case 0x4A: AdcHl(BC.Word); return 15;
|
||||||
return 15;
|
case 0x5A: AdcHl(DE.Word); return 15;
|
||||||
|
case 0x6A: AdcHl(HL.Word); return 15;
|
||||||
|
case 0x7A: AdcHl(SP); return 15;
|
||||||
case 0x7B: // LD SP, (nn)
|
case 0x7B: // LD SP, (nn)
|
||||||
// 1. Fetch the absolute 16-bit memory address from the instruction stream
|
// 1. Fetch the absolute 16-bit memory address from the instruction stream
|
||||||
byte addrLow = FetchByte();
|
byte addrLow = FetchByte();
|
||||||
@@ -2386,6 +2459,15 @@ namespace Core.Cpu
|
|||||||
AF.High = ReadMemory(address7E);
|
AF.High = ReadMemory(address7E);
|
||||||
|
|
||||||
return 19;
|
return 19;
|
||||||
|
// Inside ExecuteDDPrefix():
|
||||||
|
|
||||||
|
case 0x84: // ADD A, IXH
|
||||||
|
AddA(IX.High); // Assuming your 16-bit register struct has a .High property
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
case 0x85: // ADD A, IXL
|
||||||
|
AddA(IX.Low);
|
||||||
|
return 8;
|
||||||
case 0x86: // ADD A, (IX+d)
|
case 0x86: // ADD A, (IX+d)
|
||||||
sbyte offset86 = (sbyte)FetchByte();
|
sbyte offset86 = (sbyte)FetchByte();
|
||||||
ushort address86 = (ushort)(IX.Word + offset86);
|
ushort address86 = (ushort)(IX.Word + offset86);
|
||||||
@@ -2517,36 +2599,9 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case 0x19: // ADD IY, DE
|
// Inside ExecuteFDPrefix()
|
||||||
// 1. Perform the 16-bit addition using a 32-bit integer to catch the carry
|
case 0x09: AddIy(BC.Word); return 15;
|
||||||
int result19 = IY.Word + DE.Word;
|
case 0x19: AddIy(DE.Word); return 15; // This is the exact instruction that crashed!
|
||||||
|
|
||||||
// 2. Update the Flags Register (F)
|
|
||||||
// We start by stripping out N, H, C, and bits 3/5, but strictly PRESERVING S, Z, and P/V (0xC4)
|
|
||||||
byte flags19 = (byte)(AF.Low & 0xC4);
|
|
||||||
|
|
||||||
// H: Set if there is a carry from bit 11
|
|
||||||
if (((IY.Word & 0x0FFF) + (DE.Word & 0x0FFF)) > 0x0FFF)
|
|
||||||
{
|
|
||||||
flags19 |= 0x10;
|
|
||||||
}
|
|
||||||
|
|
||||||
// C: Set if the result overflows 16 bits (carry from bit 15)
|
|
||||||
if (result19 > 0xFFFF)
|
|
||||||
{
|
|
||||||
flags19 |= 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Undocumented bits 3 and 5 are copied directly from the high byte of the result
|
|
||||||
flags19 |= (byte)((result19 >> 8) & 0x28);
|
|
||||||
|
|
||||||
// N (Subtract) is naturally left as 0 because of our initial bitmask
|
|
||||||
AF.Low = flags19;
|
|
||||||
|
|
||||||
// 3. Store the clean 16-bit result back into IY
|
|
||||||
IY.Word = (ushort)result19;
|
|
||||||
|
|
||||||
return 15;
|
|
||||||
case 0x21: // LD IY, nn
|
case 0x21: // LD IY, nn
|
||||||
IY.Word = FetchWord();
|
IY.Word = FetchWord();
|
||||||
return 14;
|
return 14;
|
||||||
@@ -2554,6 +2609,8 @@ namespace Core.Cpu
|
|||||||
// Increment the full 16-bit register. The F register remains completely untouched.
|
// Increment the full 16-bit register. The F register remains completely untouched.
|
||||||
IY.Word++;
|
IY.Word++;
|
||||||
return 10;
|
return 10;
|
||||||
|
|
||||||
|
case 0x29: AddIy(IY.Word); return 15;
|
||||||
case 0x34: // INC (IY+d)
|
case 0x34: // INC (IY+d)
|
||||||
// 1. Fetch displacement and calculate memory address
|
// 1. Fetch displacement and calculate memory address
|
||||||
sbyte offset34 = (sbyte)FetchByte();
|
sbyte offset34 = (sbyte)FetchByte();
|
||||||
@@ -2609,6 +2666,8 @@ namespace Core.Cpu
|
|||||||
WriteMemory(targetAddress, nValue);
|
WriteMemory(targetAddress, nValue);
|
||||||
return 19; // Takes 19 T-States
|
return 19; // Takes 19 T-States
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x39: AddIy(SP); return 15;
|
||||||
case 0x46: // LD B, (IY+d)
|
case 0x46: // LD B, (IY+d)
|
||||||
{
|
{
|
||||||
sbyte displacement = (sbyte)FetchByte();
|
sbyte displacement = (sbyte)FetchByte();
|
||||||
|
|||||||
@@ -1112,8 +1112,12 @@ namespace Desktop
|
|||||||
case 0xFD:
|
case 0xFD:
|
||||||
{
|
{
|
||||||
byte fdOpcode = _memoryBus.Read((ushort)(currentPc + 1));
|
byte fdOpcode = _memoryBus.Read((ushort)(currentPc + 1));
|
||||||
|
if (fdOpcode == 0x09) // ADD IY, BC
|
||||||
if (fdOpcode == 0x19) // ADD IY, DE
|
{
|
||||||
|
mnemonic = $"ADD IY, BC";
|
||||||
|
instructionLength = 2;
|
||||||
|
}
|
||||||
|
else if (fdOpcode == 0x19) // ADD IY, DE
|
||||||
{
|
{
|
||||||
mnemonic = $"ADD IY, DE";
|
mnemonic = $"ADD IY, DE";
|
||||||
instructionLength = 2;
|
instructionLength = 2;
|
||||||
@@ -1124,6 +1128,11 @@ namespace Desktop
|
|||||||
mnemonic = $"LD IY, 0x{iyVal:X4}";
|
mnemonic = $"LD IY, 0x{iyVal:X4}";
|
||||||
instructionLength = 4;
|
instructionLength = 4;
|
||||||
}
|
}
|
||||||
|
else if (fdOpcode == 0x29) //Add IY, IY
|
||||||
|
{
|
||||||
|
mnemonic = $"ADD IY, IY";
|
||||||
|
instructionLength = 2;
|
||||||
|
}
|
||||||
else if (fdOpcode == 0x34) // INC IY
|
else if (fdOpcode == 0x34) // INC IY
|
||||||
{
|
{
|
||||||
//sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
//sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
@@ -1290,7 +1299,7 @@ namespace Desktop
|
|||||||
mnemonic = "POP IY";
|
mnemonic = "POP IY";
|
||||||
instructionLength = 2;
|
instructionLength = 2;
|
||||||
}
|
}
|
||||||
else if(fdOpcode == 0xE5)
|
else if (fdOpcode == 0xE5)
|
||||||
{
|
{
|
||||||
mnemonic = "PUSH IY";
|
mnemonic = "PUSH IY";
|
||||||
instructionLength = 2;
|
instructionLength = 2;
|
||||||
|
|||||||
@@ -102,12 +102,12 @@ namespace Desktop
|
|||||||
_tapManager.Update(elapsedTStates);
|
_tapManager.Update(elapsedTStates);
|
||||||
|
|
||||||
//Process audio at the correct time
|
//Process audio at the correct time
|
||||||
while (_cpu.TotalTStates >= (long)(audioSampleCount * 79.365))
|
//while (_cpu.TotalTStates >= (long)(audioSampleCount * 79.365))
|
||||||
{
|
//{
|
||||||
bool finalAudioOutput = _simpleIoBus.BeeperState ^ _tapManager.EarBit;
|
// bool finalAudioOutput = _simpleIoBus.BeeperState ^ _tapManager.EarBit;
|
||||||
_beeper.AddSample(finalAudioOutput);
|
// _beeper.AddSample(finalAudioOutput);
|
||||||
audioSampleCount++;
|
// audioSampleCount++;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// --- Check for End of Frame ---
|
// --- Check for End of Frame ---
|
||||||
if (_cpu.TotalTStates >= nextScanlineTarget)
|
if (_cpu.TotalTStates >= nextScanlineTarget)
|
||||||
@@ -131,13 +131,13 @@ namespace Desktop
|
|||||||
TotalFrameCount++;
|
TotalFrameCount++;
|
||||||
|
|
||||||
// Throttle to real-time (50 FPS = 20ms)
|
// Throttle to real-time (50 FPS = 20ms)
|
||||||
long targetTimeMs = (scanlineCount / 312) * 20;
|
//long targetTimeMs = (scanlineCount / 312) * 20;
|
||||||
long elapsedMs = stopwatch.ElapsedMilliseconds;
|
//long elapsedMs = stopwatch.ElapsedMilliseconds;
|
||||||
|
|
||||||
if (elapsedMs < targetTimeMs)
|
//if (elapsedMs < targetTimeMs)
|
||||||
{
|
//{
|
||||||
//Thread.Sleep((int)(targetTimeMs - elapsedMs));
|
// Thread.Sleep((int)(targetTimeMs - elapsedMs));
|
||||||
}
|
//}
|
||||||
TotalFrameTime += fpsStopwatch.Elapsed.TotalMilliseconds;
|
TotalFrameTime += fpsStopwatch.Elapsed.TotalMilliseconds;
|
||||||
if (TotalFrameCount % 50 == 0)
|
if (TotalFrameCount % 50 == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user