I'm developing a Gameboy emulator and one of the tasks is to set the flags after each statement:
...
//Representa pares de registradores do gameboy
union RegPair {
std::uint16_t reg;
struct pair
{
std::uint8_t lo;
std::uint8_t hi;
}p;
};
struct Registers{
RegPair AF, BC, DE, HL;
std::uint16_t SP, PC;
};
...
Gameboy flagset
...
//Define as flags do processador
#define FLAG_ZERO_FLAG 7
#define FLAG_SUBSTRCAT_FLAG 6
#define FLAG_HALF_CARRY 5
#define FLAG_CARRY_FLAG 4
#define FLAG_NONE 0
...
Loggers initialization:
...
reg.AF.reg = 0x01B0;
reg.BC.reg = 0x0013;
reg.DE.reg = 0x00D8;
reg.HL.reg = 0x014D;
reg.SP = 0xFFFE;
reg.PC = 0x0000; //Ponto de entrada também pode ser 0x100
...
I'm going to use the example of opcode 0xD
that sends Decrement register C, opcodes table can be found here :
void CPU::DEC8(std::uint8_t& target, int cyclesToUpdate)
{
cycles += cyclesToUpdate;
target--;
if (target == 0) {
wxLogDebug("ZERO FLAG OCORREU");
reg.AF.p.lo |= FLAG_ZERO_FLAG;
}
reg.PC++;
}
It turns out that if a zero flag does not occur I have to specifically reset the flag zero, and it may also occur to add the half carry flag, and if it does not reset its position, I found that response at stackoverflow but I found it a bit confusing, for example, when passing a parameter to fstream:
("filename", std::ios::in | std::ios::binary)
It seems to be something simpler than the way it is in the answer.