-Separated the logging from the save state function.

-Made it so that the log only opens when logging is true and that the file closes upon destruction.
--Still, BizHawk says that it can't open the file again when I load a game again. This is because the emulator class gets recreated without deleting the original one every time you load a game.
---adelikat convinced me not to care about this.
-Fixed the initial state of the GB CPU:
--It was setting AF to 0x01, not A. This is effectively setting F to 0x01, which gets overwritten later anyway.
--Two BIOS flags were used in different places; merging them gets the PC to start in the right place.
-By fixing the initial state, most of the log now matches up.
--The only differences are the VBA has some repeated records (Where all of the registers, including PC, are the same as the previous record) whereas BizHawk doesn't.
--This very well might be an issue with how I'm logging it
--Alternatively, it could be some kind of lagging mechanism.
--I'm not sure which version is even correct...VBA is far from accruate.
--All in all, considering that the vast majority of the diff comes out as the same, I think I fixed the biggest CPU related bug. Will investigate more later.
This commit is contained in:
brandman211 2012-05-24 17:19:33 +00:00
parent db1bfcfdfc
commit b29c9835ff
3 changed files with 388 additions and 383 deletions

View File

@ -7,27 +7,27 @@ using System;
+ The following instructions were rewritten or substantially modified for Z80-GB. They should be
treated with caution and checked further when the emulator is farther along.
ADD
ADC
SUB
SBC
AND
OR
XOR
CP
SWAP
DAA
RLCA
RLA
RRCA
RRA
RLC
RL
RRC
RR
SLA
SRA
SRL
ADD
ADC
SUB
SBC
AND
OR
XOR
CP
SWAP
DAA
RLCA
RLA
RRCA
RRA
RLC
RL
RRC
RR
SLA
SRA
SRL
*/
namespace BizHawk.Emulation.CPUs.Z80GB
@ -42,7 +42,7 @@ namespace BizHawk.Emulation.CPUs.Z80GB
public void ExecuteInstruction()
{
LogCPU();
byte TB; byte TB2; sbyte TSB; ushort TUS; int TI1; int TI2; int TIR;
byte TB; byte TB2; sbyte TSB; ushort TUS; int TI1; int TI2; int TIR;
while (RegPC.Word == 0x031A)
break;
byte op = ReadMemory(RegPC.Word++);
@ -952,288 +952,288 @@ namespace BizHawk.Emulation.CPUs.Z80GB
switch (op)
{
case 0x00: // RLC B
RegAF.Low = (byte)((RegBC.High & 0x80) >> 3);
RegBC.High = (byte)((RegBC.High >> 7) | (RegBC.High << 1));
if (RegBC.High == 0) RegAF.Low |= 0x80;
RegAF.Low = (byte)((RegBC.High & 0x80) >> 3);
RegBC.High = (byte)((RegBC.High >> 7) | (RegBC.High << 1));
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
case 0x01: // RLC C
RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3);
RegBC.Low = (byte)((RegBC.Low >> 7) | (RegBC.Low << 1));
if (RegBC.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3);
RegBC.Low = (byte)((RegBC.Low >> 7) | (RegBC.Low << 1));
if (RegBC.Low == 0) RegAF.Low |= 0x80;
break;
case 0x02: // RLC D
RegAF.Low = (byte)((RegDE.High & 0x80) >> 3);
RegDE.High = (byte)((RegDE.High >> 7) | (RegDE.High << 1));
if (RegDE.High == 0) RegAF.Low |= 0x80;
RegAF.Low = (byte)((RegDE.High & 0x80) >> 3);
RegDE.High = (byte)((RegDE.High >> 7) | (RegDE.High << 1));
if (RegDE.High == 0) RegAF.Low |= 0x80;
break;
case 0x03: // RLC E
RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3);
RegDE.Low = (byte)((RegDE.Low >> 7) | (RegDE.Low << 1));
if (RegDE.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3);
RegDE.Low = (byte)((RegDE.Low >> 7) | (RegDE.Low << 1));
if (RegDE.Low == 0) RegAF.Low |= 0x80;
break;
case 0x04: // RLC H
RegAF.Low = (byte)((RegHL.High & 0x80) >> 3);
RegHL.High = (byte)((RegHL.High >> 7) | (RegHL.High << 1));
if (RegHL.High == 0) RegAF.Low |= 0x80;
RegAF.Low = (byte)((RegHL.High & 0x80) >> 3);
RegHL.High = (byte)((RegHL.High >> 7) | (RegHL.High << 1));
if (RegHL.High == 0) RegAF.Low |= 0x80;
break;
case 0x05: // RLC L
RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3);
RegHL.Low = (byte)((RegHL.Low >> 7) | (RegHL.Low << 1));
if (RegHL.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3);
RegHL.Low = (byte)((RegHL.Low >> 7) | (RegHL.Low << 1));
if (RegHL.Low == 0) RegAF.Low |= 0x80;
break;
case 0x06: // RLC (HL)
TB = ReadMemory(RegHL.Word);
RegAF.Low = (byte)((TB & 0x80) >> 3);
TB = (byte)((TB >> 7) | (TB << 1));
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
TB = ReadMemory(RegHL.Word);
RegAF.Low = (byte)((TB & 0x80) >> 3);
TB = (byte)((TB >> 7) | (TB << 1));
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
break;
case 0x07: // RLC A
RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
RegAF.High = (byte)((RegAF.High >> 7) | (RegAF.High << 1));
if (RegAF.High == 0) RegAF.Low |= 0x80;
RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
RegAF.High = (byte)((RegAF.High >> 7) | (RegAF.High << 1));
if (RegAF.High == 0) RegAF.Low |= 0x80;
break;
case 0x08: // RRC B
RegBC.High = (byte)((RegBC.High << 7) | (RegBC.High >> 1));
RegAF.Low = (byte)((RegBC.High & 0x80) >> 3);
if (RegBC.High == 0) RegAF.Low |= 0x80;
RegBC.High = (byte)((RegBC.High << 7) | (RegBC.High >> 1));
RegAF.Low = (byte)((RegBC.High & 0x80) >> 3);
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
case 0x09: // RRC C
RegBC.Low = (byte)((RegBC.Low << 7) | (RegBC.Low >> 1));
RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3);
if (RegBC.Low == 0) RegAF.Low |= 0x80;
RegBC.Low = (byte)((RegBC.Low << 7) | (RegBC.Low >> 1));
RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3);
if (RegBC.Low == 0) RegAF.Low |= 0x80;
break;
case 0x0A: // RRC D
RegDE.High = (byte)((RegDE.High << 7) | (RegDE.High >> 1));
RegAF.Low = (byte)((RegDE.High & 0x80) >> 3);
if (RegDE.High == 0) RegAF.Low |= 0x80;
RegDE.High = (byte)((RegDE.High << 7) | (RegDE.High >> 1));
RegAF.Low = (byte)((RegDE.High & 0x80) >> 3);
if (RegDE.High == 0) RegAF.Low |= 0x80;
break;
case 0x0B: // RRC E
RegDE.Low = (byte)((RegDE.Low << 7) | (RegDE.Low >> 1));
RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3);
if (RegDE.Low == 0) RegAF.Low |= 0x80;
RegDE.Low = (byte)((RegDE.Low << 7) | (RegDE.Low >> 1));
RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3);
if (RegDE.Low == 0) RegAF.Low |= 0x80;
break;
case 0x0C: // RRC H
RegHL.High = (byte)((RegHL.High << 7) | (RegHL.High >> 1));
RegAF.Low = (byte)((RegHL.High & 0x80) >> 3);
if (RegHL.High == 0) RegAF.Low |= 0x80;
RegHL.High = (byte)((RegHL.High << 7) | (RegHL.High >> 1));
RegAF.Low = (byte)((RegHL.High & 0x80) >> 3);
if (RegHL.High == 0) RegAF.Low |= 0x80;
break;
case 0x0D: // RRC L
RegHL.Low = (byte)((RegHL.Low << 7) | (RegHL.Low >> 1));
RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3);
if (RegHL.Low == 0) RegAF.Low |= 0x80;
RegHL.Low = (byte)((RegHL.Low << 7) | (RegHL.Low >> 1));
RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3);
if (RegHL.Low == 0) RegAF.Low |= 0x80;
break;
case 0x0E: // RRC (HL)
TB = ReadMemory(RegHL.Word);
TB = (byte)((TB << 7) | (TB >> 1));
RegAF.Low = (byte)((TB & 0x80) >> 3);
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
TB = ReadMemory(RegHL.Word);
TB = (byte)((TB << 7) | (TB >> 1));
RegAF.Low = (byte)((TB & 0x80) >> 3);
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
break;
case 0x0F: // RRC A
RegAF.High = (byte)((RegAF.High << 7) | (RegAF.High >> 1));
RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
if (RegAF.High == 0) RegAF.Low |= 0x80;
RegAF.High = (byte)((RegAF.High << 7) | (RegAF.High >> 1));
RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
if (RegAF.High == 0) RegAF.Low |= 0x80;
break;
case 0x10: // RL B
TB = (byte)((RegBC.High & 0x80) >> 3);
RegBC.High = (byte)((RegBC.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegBC.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegBC.High & 0x80) >> 3);
RegBC.High = (byte)((RegBC.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
case 0x11: // RL C
TB = (byte)((RegBC.Low & 0x80) >> 3);
RegBC.Low = (byte)((RegBC.Low << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
TB = (byte)((RegBC.Low & 0x80) >> 3);
RegBC.Low = (byte)((RegBC.Low << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
break;
case 0x12: // RL D
TB = (byte)((RegDE.High & 0x80) >> 3);
RegDE.High = (byte)((RegDE.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegDE.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegDE.High & 0x80) >> 3);
RegDE.High = (byte)((RegDE.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegDE.High == 0) RegAF.Low |= 0x80;
break;
case 0x13: // RL E
TB = (byte)((RegDE.Low & 0x80) >> 3);
RegDE.Low = (byte)((RegDE.Low << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
TB = (byte)((RegDE.Low & 0x80) >> 3);
RegDE.Low = (byte)((RegDE.Low << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
break;
case 0x14: // RL H
TB = (byte)((RegHL.High & 0x80) >> 3);
RegHL.High = (byte)((RegHL.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegHL.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegHL.High & 0x80) >> 3);
RegHL.High = (byte)((RegHL.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegHL.High == 0) RegAF.Low |= 0x80;
break;
case 0x15: // RL L
TB = (byte)((RegHL.Low & 0x80) >> 3);
RegHL.Low = (byte)((RegHL.Low << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
TB = (byte)((RegHL.Low & 0x80) >> 3);
RegHL.Low = (byte)((RegHL.Low << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
break;
case 0x16: // RL (HL)
TB2 = ReadMemory(RegHL.Word);
TB = (byte)((TB2 & 0x80) >> 3);
TB2 = (byte)((TB2 << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (TB2 == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB2);
TB2 = ReadMemory(RegHL.Word);
TB = (byte)((TB2 & 0x80) >> 3);
TB2 = (byte)((TB2 << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (TB2 == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB2);
break;
case 0x17: // RL A
TB = (byte)((RegAF.High & 0x80) >> 3);
RegAF.High = (byte)((RegAF.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegAF.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegAF.High & 0x80) >> 3);
RegAF.High = (byte)((RegAF.High << 1) | (FlagC ? 1 : 0));
RegAF.Low = TB;
if (RegAF.High == 0) RegAF.Low |= 0x80;
break;
case 0x18: // RR B
TB = (byte)((RegBC.High & 0x1) << 4);
RegBC.High = (byte)((RegBC.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegBC.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegBC.High & 0x1) << 4);
RegBC.High = (byte)((RegBC.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
case 0x19: // RR C
TB = (byte)((RegBC.Low & 0x1) << 4);
RegBC.Low = (byte)((RegBC.Low >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
TB = (byte)((RegBC.Low & 0x1) << 4);
RegBC.Low = (byte)((RegBC.Low >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
break;
case 0x1A: // RR D
TB = (byte)((RegDE.High & 0x1) << 4);
RegDE.High = (byte)((RegDE.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegDE.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegDE.High & 0x1) << 4);
RegDE.High = (byte)((RegDE.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegDE.High == 0) RegAF.Low |= 0x80;
break;
case 0x1B: // RR E
TB = (byte)((RegDE.Low & 0x1) << 4);
RegDE.Low = (byte)((RegDE.Low >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
TB = (byte)((RegDE.Low & 0x1) << 4);
RegDE.Low = (byte)((RegDE.Low >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
break;
case 0x1C: // RR H
TB = (byte)((RegHL.High & 0x1) << 4);
RegHL.High = (byte)((RegHL.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegHL.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegHL.High & 0x1) << 4);
RegHL.High = (byte)((RegHL.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegHL.High == 0) RegAF.Low |= 0x80;
break;
case 0x1D: // RR L
TB = (byte)((RegHL.Low & 0x1) << 4);
RegHL.Low = (byte)((RegHL.Low >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
TB = (byte)((RegHL.Low & 0x1) << 4);
RegHL.Low = (byte)((RegHL.Low >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
break;
case 0x1E: // RR (HL)
TB2 = ReadMemory(RegHL.Word);
TB = (byte)((TB2 & 0x1) << 4);
TB2 = (byte)((TB2 >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (TB2 == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB2);
TB2 = ReadMemory(RegHL.Word);
TB = (byte)((TB2 & 0x1) << 4);
TB2 = (byte)((TB2 >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (TB2 == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB2);
break;
case 0x1F: // RR A
TB = (byte)((RegAF.High & 0x1) << 4);
RegAF.High = (byte)((RegAF.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegAF.High == 0) RegAF.Low |= 0x80;
TB = (byte)((RegAF.High & 0x1) << 4);
RegAF.High = (byte)((RegAF.High >> 1) | (FlagC ? 0x80 : 0));
RegAF.Low = TB;
if (RegAF.High == 0) RegAF.Low |= 0x80;
break;
case 0x20: // SLA B
RegAF.Low = 0;
if ((RegBC.High & 0x80) != 0) RegAF.Low |= 0x10;
RegBC.High <<= 1;
if (RegBC.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegBC.High & 0x80) != 0) RegAF.Low |= 0x10;
RegBC.High <<= 1;
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
case 0x21: // SLA C
RegAF.Low = 0;
if ((RegBC.Low & 0x80) != 0) RegAF.Low |= 0x10;
RegBC.Low <<= 1;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegBC.Low & 0x80) != 0) RegAF.Low |= 0x10;
RegBC.Low <<= 1;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
break;
case 0x22: // SLA D
RegAF.Low = 0;
if ((RegDE.High & 0x80) != 0) RegAF.Low |= 0x10;
RegDE.High <<= 1;
if (RegDE.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegDE.High & 0x80) != 0) RegAF.Low |= 0x10;
RegDE.High <<= 1;
if (RegDE.High == 0) RegAF.Low |= 0x80;
break;
case 0x23: // SLA E
RegAF.Low = 0;
if ((RegDE.Low & 0x80) != 0) RegAF.Low |= 0x10;
RegDE.Low <<= 1;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegDE.Low & 0x80) != 0) RegAF.Low |= 0x10;
RegDE.Low <<= 1;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
break;
case 0x24: // SLA H
RegAF.Low = 0;
if ((RegHL.High & 0x80) != 0) RegAF.Low |= 0x10;
RegHL.High <<= 1;
if (RegHL.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegHL.High & 0x80) != 0) RegAF.Low |= 0x10;
RegHL.High <<= 1;
if (RegHL.High == 0) RegAF.Low |= 0x80;
break;
case 0x25: // SLA L
RegAF.Low = 0;
if ((RegHL.Low & 0x80) != 0) RegAF.Low |= 0x10;
RegHL.Low <<= 1;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegHL.Low & 0x80) != 0) RegAF.Low |= 0x10;
RegHL.Low <<= 1;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
break;
case 0x26: // SLA (HL)
TB = ReadMemory(RegHL.Word);
RegAF.Low = 0;
if ((TB & 0x80) != 0) RegAF.Low |= 0x10;
TB <<= 1;
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
TB = ReadMemory(RegHL.Word);
RegAF.Low = 0;
if ((TB & 0x80) != 0) RegAF.Low |= 0x10;
TB <<= 1;
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
break;
case 0x27: // SLA A
RegAF.Low = 0;
if ((RegAF.High & 0x80) != 0) RegAF.Low |= 0x10;
RegAF.High <<= 1;
if (RegAF.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegAF.High & 0x80) != 0) RegAF.Low |= 0x10;
RegAF.High <<= 1;
if (RegAF.High == 0) RegAF.Low |= 0x80;
break;
case 0x28: // SRA B
RegAF.Low = 0;
if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10;
RegBC.High = (byte) ((RegBC.High >> 1) | (RegBC.High & 0x80));
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
RegAF.Low = 0;
if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10;
RegBC.High = (byte)((RegBC.High >> 1) | (RegBC.High & 0x80));
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
case 0x29: // SRA C
RegAF.Low = 0;
if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10;
RegBC.Low = (byte)((RegBC.Low >> 1) | (RegBC.Low & 0x80));
if (RegBC.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10;
RegBC.Low = (byte)((RegBC.Low >> 1) | (RegBC.Low & 0x80));
if (RegBC.Low == 0) RegAF.Low |= 0x80;
break;
case 0x2A: // SRA D
RegAF.Low = 0;
if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10;
RegDE.High = (byte)((RegDE.High >> 1) | (RegDE.High & 0x80));
if (RegDE.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10;
RegDE.High = (byte)((RegDE.High >> 1) | (RegDE.High & 0x80));
if (RegDE.High == 0) RegAF.Low |= 0x80;
break;
case 0x2B: // SRA E
RegAF.Low = 0;
if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10;
RegDE.Low = (byte)((RegDE.Low >> 1) | (RegDE.Low & 0x80));
if (RegDE.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10;
RegDE.Low = (byte)((RegDE.Low >> 1) | (RegDE.Low & 0x80));
if (RegDE.Low == 0) RegAF.Low |= 0x80;
break;
case 0x2C: // SRA H
RegAF.Low = 0;
if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10;
RegHL.High = (byte)((RegHL.High >> 1) | (RegHL.High & 0x80));
if (RegHL.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10;
RegHL.High = (byte)((RegHL.High >> 1) | (RegHL.High & 0x80));
if (RegHL.High == 0) RegAF.Low |= 0x80;
break;
case 0x2D: // SRA L
RegAF.Low = 0;
if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10;
RegHL.Low = (byte)((RegHL.Low >> 1) | (RegHL.Low & 0x80));
if (RegHL.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10;
RegHL.Low = (byte)((RegHL.Low >> 1) | (RegHL.Low & 0x80));
if (RegHL.Low == 0) RegAF.Low |= 0x80;
break;
case 0x2E: // SRA (HL)
TB = ReadMemory(RegHL.Word);
RegAF.Low = 0;
if ((TB & 1) != 0) RegAF.Low |= 0x10;
TB = (byte)((TB >> 1) | (TB & 0x80));
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
TB = ReadMemory(RegHL.Word);
RegAF.Low = 0;
if ((TB & 1) != 0) RegAF.Low |= 0x10;
TB = (byte)((TB >> 1) | (TB & 0x80));
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
break;
case 0x2F: // SRA A
RegAF.Low = 0;
if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10;
RegAF.High = (byte)((RegAF.High >> 1) | (RegAF.High & 0x80));
if (RegAF.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10;
RegAF.High = (byte)((RegAF.High >> 1) | (RegAF.High & 0x80));
if (RegAF.High == 0) RegAF.Low |= 0x80;
break;
case 0x30: // SWAP B
RegBC.High = SwapTable[RegBC.High];
@ -1269,54 +1269,54 @@ namespace BizHawk.Emulation.CPUs.Z80GB
FlagZ = (RegAF.High == 0);
break;
case 0x38: // SRL B
RegAF.Low = 0;
if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10;
RegBC.High >>= 1;
if (RegBC.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10;
RegBC.High >>= 1;
if (RegBC.High == 0) RegAF.Low |= 0x80;
break;
case 0x39: // SRL C
RegAF.Low = 0;
if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10;
RegBC.Low >>= 1;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10;
RegBC.Low >>= 1;
if (RegBC.Low == 0) RegAF.Low |= 0x80;
break;
case 0x3A: // SRL D
RegAF.Low = 0;
if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10;
RegDE.High >>= 1;
if (RegDE.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10;
RegDE.High >>= 1;
if (RegDE.High == 0) RegAF.Low |= 0x80;
break;
case 0x3B: // SRL E
RegAF.Low = 0;
if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10;
RegDE.Low >>= 1;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10;
RegDE.Low >>= 1;
if (RegDE.Low == 0) RegAF.Low |= 0x80;
break;
case 0x3C: // SRL H
RegAF.Low = 0;
if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10;
RegHL.High >>= 1;
if (RegHL.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10;
RegHL.High >>= 1;
if (RegHL.High == 0) RegAF.Low |= 0x80;
break;
case 0x3D: // SRL L
RegAF.Low = 0;
if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10;
RegHL.Low >>= 1;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10;
RegHL.Low >>= 1;
if (RegHL.Low == 0) RegAF.Low |= 0x80;
break;
case 0x3E: // SRL (HL)
TB = ReadMemory(RegHL.Word);
RegAF.Low = 0;
if ((TB & 1) != 0) RegAF.Low |= 0x10;
TB >>= 1;
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
TB = ReadMemory(RegHL.Word);
RegAF.Low = 0;
if ((TB & 1) != 0) RegAF.Low |= 0x10;
TB >>= 1;
if (TB == 0) RegAF.Low |= 0x80;
WriteMemory(RegHL.Word, TB);
break;
case 0x3F: // SRL A
RegAF.Low = 0;
if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10;
RegAF.High >>= 1;
if (RegAF.High == 0) RegAF.Low |= 0x80;
RegAF.Low = 0;
if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10;
RegAF.High >>= 1;
if (RegAF.High == 0) RegAF.Low |= 0x80;
break;
case 0x40: // BIT 0, B
FlagZ = (RegBC.High & 0x01) == 0;
@ -2247,7 +2247,7 @@ namespace BizHawk.Emulation.CPUs.Z80GB
void CheckIrq()
{
if (nonMaskableInterruptPending)
if (nonMaskableInterruptPending)
{
halted = false;

View File

@ -7,150 +7,157 @@ using System.IO;
namespace BizHawk.Emulation.CPUs.Z80GB
{
public sealed partial class Z80
{
public Z80()
{
public sealed partial class Z80
{
public Z80()
{
InitializeTables();
Reset();
}
public void Reset()
{
public void Reset()
{
ResetRegisters();
ResetInterrupts();
PendingCycles = 0;
TotalExecutedCycles = 0;
}
// Memory Access
// Memory Access
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
private bool logging = false;
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
private bool logging = true;
private TextWriter log = File.CreateText("log.txt");
public void UnregisterMemoryMapper()
{
ReadMemory = null;
WriteMemory = null;
}
public void UnregisterMemoryMapper()
{
ReadMemory = null;
WriteMemory = null;
}
// State Save/Load
// State Save/Load
public void SaveStateText(TextWriter writer)
{
writer.WriteLine("[Z80]");
writer.WriteLine("AF {0:X4}", RegAF.Word);
writer.WriteLine("BC {0:X4}", RegBC.Word);
writer.WriteLine("DE {0:X4}", RegDE.Word);
writer.WriteLine("HL {0:X4}", RegHL.Word);
writer.WriteLine("I {0:X2}", RegI);
writer.WriteLine("SP {0:X4}", RegSP.Word);
writer.WriteLine("PC {0:X4}", RegPC.Word);
writer.WriteLine("IRQ {0}", interrupt);
writer.WriteLine("NMI {0}", nonMaskableInterrupt);
writer.WriteLine("NMIPending {0}", nonMaskableInterruptPending);
writer.WriteLine("IM {0}", InterruptMode);
writer.WriteLine("IFF1 {0}", IFF1);
writer.WriteLine("IFF2 {0}", IFF2);
writer.WriteLine("Halted {0}", Halted);
writer.WriteLine("ExecutedCycles {0}", TotalExecutedCycles);
writer.WriteLine("PendingCycles {0}", PendingCycles);
writer.WriteLine("[/Z80]");
writer.WriteLine();
}
public void SaveStateText(TextWriter writer)
{
writer.WriteLine("[Z80]");
writer.WriteLine("AF {0:X4}", RegAF.Word);
writer.WriteLine("BC {0:X4}", RegBC.Word);
writer.WriteLine("DE {0:X4}", RegDE.Word);
writer.WriteLine("HL {0:X4}", RegHL.Word);
writer.WriteLine("I {0:X2}", RegI);
writer.WriteLine("SP {0:X4}", RegSP.Word);
writer.WriteLine("PC {0:X4}", RegPC.Word);
writer.WriteLine("IRQ {0}", interrupt);
writer.WriteLine("NMI {0}", nonMaskableInterrupt);
writer.WriteLine("NMIPending {0}", nonMaskableInterruptPending);
writer.WriteLine("IM {0}", InterruptMode);
writer.WriteLine("IFF1 {0}", IFF1);
writer.WriteLine("IFF2 {0}", IFF2);
writer.WriteLine("Halted {0}", Halted);
writer.WriteLine("ExecutedCycles {0}", TotalExecutedCycles);
writer.WriteLine("PendingCycles {0}", PendingCycles);
writer.WriteLine("[/Z80]");
writer.WriteLine();
}
public void LoadStateText(TextReader reader)
{
while (true)
{
string[] args = reader.ReadLine().Split(' ');
if (args[0].Trim() == "") continue;
if (args[0] == "[/Z80]") break;
if (args[0] == "AF")
RegAF.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "BC")
RegBC.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "DE")
RegDE.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "HL")
RegHL.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "I")
RegI = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "SP")
RegSP.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "PC")
RegPC.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "IRQ")
interrupt = bool.Parse(args[1]);
else if (args[0] == "NMI")
nonMaskableInterrupt = bool.Parse(args[1]);
else if (args[0] == "NMIPending")
nonMaskableInterruptPending = bool.Parse(args[1]);
else if (args[0] == "IM")
InterruptMode = int.Parse(args[1]);
else if (args[0] == "IFF1")
IFF1 = bool.Parse(args[1]);
else if (args[0] == "IFF2")
IFF2 = bool.Parse(args[1]);
else if (args[0] == "Halted")
Halted = bool.Parse(args[1]);
else if (args[0] == "ExecutedCycles")
TotalExecutedCycles = int.Parse(args[1]);
else if (args[0] == "PendingCycles")
PendingCycles = int.Parse(args[1]);
public void LoadStateText(TextReader reader)
{
while (true)
{
string[] args = reader.ReadLine().Split(' ');
if (args[0].Trim() == "") continue;
if (args[0] == "[/Z80]") break;
if (args[0] == "AF")
RegAF.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "BC")
RegBC.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "DE")
RegDE.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "HL")
RegHL.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "I")
RegI = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "SP")
RegSP.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "PC")
RegPC.Word = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "IRQ")
interrupt = bool.Parse(args[1]);
else if (args[0] == "NMI")
nonMaskableInterrupt = bool.Parse(args[1]);
else if (args[0] == "NMIPending")
nonMaskableInterruptPending = bool.Parse(args[1]);
else if (args[0] == "IM")
InterruptMode = int.Parse(args[1]);
else if (args[0] == "IFF1")
IFF1 = bool.Parse(args[1]);
else if (args[0] == "IFF2")
IFF2 = bool.Parse(args[1]);
else if (args[0] == "Halted")
Halted = bool.Parse(args[1]);
else if (args[0] == "ExecutedCycles")
TotalExecutedCycles = int.Parse(args[1]);
else if (args[0] == "PendingCycles")
PendingCycles = int.Parse(args[1]);
else
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
}
}
else
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
}
}
public void SaveStateBinary(BinaryWriter writer)
{
writer.Write(RegAF.Word);
writer.Write(RegBC.Word);
writer.Write(RegDE.Word);
writer.Write(RegHL.Word);
writer.Write(RegI);
writer.Write(RegSP.Word);
writer.Write(RegPC.Word);
writer.Write(interrupt);
writer.Write(nonMaskableInterrupt);
writer.Write(nonMaskableInterruptPending);
writer.Write(InterruptMode);
writer.Write(IFF1);
writer.Write(IFF2);
writer.Write(Halted);
writer.Write(TotalExecutedCycles);
writer.Write(PendingCycles);
}
public void SaveStateBinary(BinaryWriter writer)
{
writer.Write(RegAF.Word);
writer.Write(RegBC.Word);
writer.Write(RegDE.Word);
writer.Write(RegHL.Word);
writer.Write(RegI);
writer.Write(RegSP.Word);
writer.Write(RegPC.Word);
writer.Write(interrupt);
writer.Write(nonMaskableInterrupt);
writer.Write(nonMaskableInterruptPending);
writer.Write(InterruptMode);
writer.Write(IFF1);
writer.Write(IFF2);
writer.Write(Halted);
writer.Write(TotalExecutedCycles);
writer.Write(PendingCycles);
}
public void LoadStateBinary(BinaryReader reader)
{
RegAF.Word = reader.ReadUInt16();
RegBC.Word = reader.ReadUInt16();
RegDE.Word = reader.ReadUInt16();
RegHL.Word = reader.ReadUInt16();
RegI = reader.ReadByte();
RegSP.Word = reader.ReadUInt16();
RegPC.Word = reader.ReadUInt16();
interrupt = reader.ReadBoolean();
nonMaskableInterrupt = reader.ReadBoolean();
nonMaskableInterruptPending = reader.ReadBoolean();
InterruptMode = reader.ReadInt32();
IFF1 = reader.ReadBoolean();
IFF2 = reader.ReadBoolean();
Halted = reader.ReadBoolean();
TotalExecutedCycles = reader.ReadInt32();
PendingCycles = reader.ReadInt32();
}
public void LoadStateBinary(BinaryReader reader)
{
RegAF.Word = reader.ReadUInt16();
RegBC.Word = reader.ReadUInt16();
RegDE.Word = reader.ReadUInt16();
RegHL.Word = reader.ReadUInt16();
RegI = reader.ReadByte();
RegSP.Word = reader.ReadUInt16();
RegPC.Word = reader.ReadUInt16();
interrupt = reader.ReadBoolean();
nonMaskableInterrupt = reader.ReadBoolean();
nonMaskableInterruptPending = reader.ReadBoolean();
InterruptMode = reader.ReadInt32();
IFF1 = reader.ReadBoolean();
IFF2 = reader.ReadBoolean();
Halted = reader.ReadBoolean();
TotalExecutedCycles = reader.ReadInt32();
PendingCycles = reader.ReadInt32();
}
private void LogCPU()
{
if (!logging)
return;
SaveStateText(log);
log.WriteLine("AF {0:X4}", RegAF.Word);
log.WriteLine("BC {0:X4}", RegBC.Word);
log.WriteLine("DE {0:X4}", RegDE.Word);
log.WriteLine("HL {0:X4}", RegHL.Word);
log.WriteLine("SP {0:X4}", RegSP.Word);
log.WriteLine("PC {0:X4}", RegPC.Word);
log.WriteLine("------");
log.WriteLine();
}
}
}
}

View File

@ -277,8 +277,6 @@ namespace BizHawk.Emulation.Consoles.Gameboy
HardReset();
}
public bool BootFromBios = true;
public void HardReset()
{
Cpu = new CPUs.Z80GB.Z80();
@ -296,13 +294,13 @@ namespace BizHawk.Emulation.Consoles.Gameboy
{
case ESystemType.GB:
case ESystemType.SGB:
Cpu.RegisterAF = 0x01;
Cpu.RegisterA = 0x01;
break;
case ESystemType.GBP:
Cpu.RegisterAF = 0xFF;
Cpu.RegisterA = 0xFF;
break;
case ESystemType.GBC:
Cpu.RegisterAF = 0x11;
Cpu.RegisterA = 0x11;
break;
case ESystemType.GBA:
throw new NotImplementedException(); //decide what to do
@ -315,8 +313,8 @@ namespace BizHawk.Emulation.Consoles.Gameboy
Cpu.RegisterDE = 0x00D8;
Cpu.RegisterHL = 0x014D;
Cpu.RegisterSP = 0xFFFE;
if (BootFromBios) Cpu.RegisterPC = 0x0000;
else Cpu.RegisterPC = 0x0100;
if (skipBIOS) Cpu.RegisterPC = 0x0100;
else Cpu.RegisterPC = 0x0000;
WRam = new byte[32 * 1024]; //GB has 4KB of WRam; GBC has 32KB of WRam
SRam = new byte[8 * 1024]; //different carts may have different amounts of this
@ -336,11 +334,11 @@ namespace BizHawk.Emulation.Consoles.Gameboy
private void SetupMemoryDomains()
{
var domains = new List<MemoryDomain>(1);
var SystemBusDomain = new MemoryDomain("System Bus", 0x10000, Endian.Little,
addr => Cpu.ReadMemory((ushort)addr),
(addr, value) => Cpu.WriteMemory((ushort)addr, value));
var WRAM0Domain = new MemoryDomain("WRAM Bank 0", 0x2000, Endian.Little,
addr => WRam[addr & 0x1FFF],
(addr, value) => WRam[addr & 0x1FFF] = value);
@ -377,7 +375,7 @@ namespace BizHawk.Emulation.Consoles.Gameboy
domains.Add(OAMDomain);
domains.Add(HRAMDomain);
domains.Add(SystemBusDomain);
memoryDomains = domains.AsReadOnly();
}
@ -450,7 +448,7 @@ namespace BizHawk.Emulation.Consoles.Gameboy
{
switch (addr)
{
case 0xFF00: //REG_P1 - Register for reading joy pad info and determining system type. (R/W)
case 0xFF00: //REG_P1 - Register for reading joy pad info and determining system type. (R/W)
return Registers.Input.Read();
case 0xFF01: //REG_SB - Serial transfer data (R/W)
return 0xFF;
@ -565,7 +563,7 @@ namespace BizHawk.Emulation.Consoles.Gameboy
{
switch (addr)
{
case 0xFF00: //REG_P1 - Register for reading joy pad info and determining system type. (R/W)
case 0xFF00: //REG_P1 - Register for reading joy pad info and determining system type. (R/W)
Registers.Input.Write(value);
break;
case 0xFF01: //REG_SB - Serial transfer data (R/W)
@ -724,7 +722,7 @@ namespace BizHawk.Emulation.Consoles.Gameboy
get { return this; }
}
public int[] GetVideoBuffer()
public int[] GetVideoBuffer()
{
//TODO - these need to be run once per scanline and accumulated into a 160*144 byte buffer held by the core
//then, in the call to GetVideoBuffer(), it gets adapted to gray according to the palette and returned
@ -757,9 +755,9 @@ namespace BizHawk.Emulation.Consoles.Gameboy
return buf;
}
public int BufferWidth { get { return 160; } }
public int BufferHeight { get { return 144; } }
public int BackgroundColor { get { return 0; } }
public int BufferWidth { get { return 160; } }
public int BufferHeight { get { return 144; } }
public int BackgroundColor { get { return 0; } }
public ISoundProvider SoundProvider
{