Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Game Boy (DMG-01) emulator project focused on building an accurate LR35902 CPU c

```bash
❯ ./utility_scripts/opcode_progress.py
- Base Opcodes: [██████████████████░░] 93.8% (240/256)
- Base Opcodes: [████████████████████] 100.0% (256/256)
- CB Opcodes: [████████████████████] 100.0% (256/256)
- Combined: [███████████████████░] 96.9% (496/512)
- Combined: [████████████████████] 100.0% (512/512)
```

## Current Focus
Expand Down
240 changes: 224 additions & 16 deletions src/core/cpu/instructions/opcodes/op_0D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,227 @@ constexpr int machine_cycles = 4;

#define DUMMY(name) int name(ProcessingUnit&, MMU&) { return totalMachineCycles(1); }

DUMMY(op_ret_nc) // 0xD0
DUMMY(op_pop_de) // 0xD1
DUMMY(op_jp_nc) // 0xD2
DUMMY(op_illegal_d3) // 0xD3
DUMMY(op_call_nc) // 0xD4
DUMMY(op_push_de) // 0xD5
DUMMY(op_sub_d8) // 0xD6
DUMMY(op_rst_10) // 0xD7
DUMMY(op_ret_c) // 0xD8
DUMMY(op_reti) // 0xD9
DUMMY(op_jp_c) // 0xDA
DUMMY(op_illegal_db) // 0xDB
DUMMY(op_call_c) // 0xDC
DUMMY(op_illegal_dd) // 0xDD
DUMMY(op_sbc_a_d8) // 0xDE
DUMMY(op_rst_18) // 0xDF
int op_ret_nc(ProcessingUnit& cpu, MMU& mmu) // 0xD0
{
if (cpu.get_flag_c()) {
return totalMachineCycles(2);
}

const u16 sp = cpu.get_sp();
const u8 lo = mmu.read(sp);
const u8 hi = mmu.read(sp + 1);

cpu.set_sp(sp + 2);
cpu.set_pc(static_cast<u16>((hi << 8) | lo));

return totalMachineCycles(5);
}

int op_pop_de(ProcessingUnit& cpu, MMU& mmu) // 0xD1
{
const u16 sp = cpu.get_sp();
const u8 lo = mmu.read(sp);
const u8 hi = mmu.read(sp + 1);

cpu.reg(ProcessingUnit::Register::E) = lo;
cpu.reg(ProcessingUnit::Register::D) = hi;
cpu.set_sp(sp + 2);

return totalMachineCycles(3);
}

int op_jp_nc(ProcessingUnit& cpu, MMU& mmu) // 0xD2
{
const u8 lo = mmu.read(cpu.inc_pc());
const u8 hi = mmu.read(cpu.inc_pc());
const u16 addr = static_cast<u16>((hi << 8) | lo);

if (!cpu.get_flag_c())
{
cpu.set_pc(addr);
return totalMachineCycles(4);
}

return totalMachineCycles(3);
}

int op_illegal_d3(ProcessingUnit& cpu, MMU& mmu) // 0xD3
{
return totalMachineCycles(1);
}

int op_call_nc(ProcessingUnit& cpu, MMU& mmu) // 0xD4
{
const u8 lo = mmu.read(cpu.inc_pc());
const u8 hi = mmu.read(cpu.inc_pc());
const u16 addr = static_cast<u16>((hi << 8) | lo);

if (!cpu.get_flag_c())
{
const u16 pc = cpu.get_pc();
const u16 sp = cpu.get_sp();

mmu.write(sp - 1, static_cast<u8>(pc >> 8));
mmu.write(sp - 2, static_cast<u8>(pc & 0xFF));
cpu.set_sp(sp - 2);
cpu.set_pc(addr);

return totalMachineCycles(6);
}

return totalMachineCycles(3);
}

int op_push_de(ProcessingUnit& cpu, MMU& mmu) // 0xD5
{
const u8 d = cpu.reg(ProcessingUnit::Register::D);
const u8 e = cpu.reg(ProcessingUnit::Register::E);
const u16 sp = cpu.get_sp();

mmu.write(sp - 1, d);
mmu.write(sp - 2, e);
cpu.set_sp(sp - 2);

return totalMachineCycles(4);
}

int op_sub_d8(ProcessingUnit& cpu, MMU& mmu) // 0xD6
{
const u8 a = cpu.reg(ProcessingUnit::Register::A);
const u8 d8 = mmu.read(cpu.inc_pc());
const int result = a - d8;
const int half_carry = (a & 0x0F) - (d8 & 0x0F);

cpu.setFlag(ProcessingUnit::Flag::Z, (result & 0xFF) == 0);
cpu.setFlag(ProcessingUnit::Flag::N, true);
cpu.setFlag(ProcessingUnit::Flag::H, half_carry < 0);
cpu.setFlag(ProcessingUnit::Flag::C, result < 0);

cpu.reg(ProcessingUnit::Register::A) = static_cast<u8>(result);

return totalMachineCycles(2);
}

int op_rst_10(ProcessingUnit& cpu, MMU& mmu) // 0xD7
{
const u16 pc = cpu.get_pc();

cpu.set_sp(cpu.get_sp() - 1);
mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);

cpu.set_sp(cpu.get_sp() - 1);
mmu.write(cpu.get_sp(), pc & 0xFF);

cpu.set_pc(0x10);

return totalMachineCycles(4);
}

int op_ret_c(ProcessingUnit& cpu, MMU& mmu) // 0xD8
{
if (!cpu.get_flag_c()) {
return totalMachineCycles(2);
}

const u16 sp = cpu.get_sp();
const u8 lo = mmu.read(sp);
const u8 hi = mmu.read(sp + 1);

cpu.set_sp(sp + 2);
cpu.set_pc(static_cast<u16>((hi << 8) | lo));

return totalMachineCycles(5);
}

int op_reti(ProcessingUnit& cpu, MMU& mmu) // 0xD9
{
const u16 sp = cpu.get_sp();
const u8 lo = mmu.read(sp);
const u8 hi = mmu.read(sp + 1);

cpu.set_sp(sp + 2);
cpu.set_pc(static_cast<u16>((hi << 8) | lo));
cpu.setIME(true);

return totalMachineCycles(4);
}

int op_jp_c(ProcessingUnit& cpu, MMU& mmu) // 0xDA
{
const u8 lo = mmu.read(cpu.inc_pc());
const u8 hi = mmu.read(cpu.inc_pc());
const u16 addr = static_cast<u16>((hi << 8) | lo);

if (cpu.get_flag_c())
{
cpu.set_pc(addr);
return totalMachineCycles(4);
}

return totalMachineCycles(3);
}

int op_illegal_db(ProcessingUnit& cpu, MMU& mmu) // 0xDB
{
return totalMachineCycles(1);
}

int op_call_c(ProcessingUnit& cpu, MMU& mmu) // 0xDC
{
const u8 lo = mmu.read(cpu.inc_pc());
const u8 hi = mmu.read(cpu.inc_pc());
const u16 addr = static_cast<u16>((hi << 8) | lo);

if (cpu.get_flag_c())
{
const u16 pc = cpu.get_pc();
const u16 sp = cpu.get_sp();

mmu.write(sp - 1, static_cast<u8>(pc >> 8));
mmu.write(sp - 2, static_cast<u8>(pc & 0xFF));
cpu.set_sp(sp - 2);
cpu.set_pc(addr);

return totalMachineCycles(6);
}

return totalMachineCycles(3);
}

int op_illegal_dd(ProcessingUnit& cpu, MMU& mmu) // 0xDD
{
return totalMachineCycles(1);
}

int op_sbc_a_d8(ProcessingUnit& cpu, MMU& mmu) // 0xDE
{
const u8 a = cpu.reg(ProcessingUnit::Register::A);
const u8 d8 = mmu.read(cpu.inc_pc());
const u8 carry = cpu.get_flag_c() ? 1 : 0;
const int result = a - d8 - carry;
const int half_carry = (a & 0x0F) - (d8 & 0x0F) - carry;

cpu.setFlag(ProcessingUnit::Flag::Z, (result & 0xFF) == 0);
cpu.setFlag(ProcessingUnit::Flag::N, true);
cpu.setFlag(ProcessingUnit::Flag::H, half_carry < 0);
cpu.setFlag(ProcessingUnit::Flag::C, result < 0);

cpu.reg(ProcessingUnit::Register::A) = static_cast<u8>(result);

return totalMachineCycles(2);
}

int op_rst_18(ProcessingUnit& cpu, MMU& mmu) // 0xDF
{
const u16 pc = cpu.get_pc();

cpu.set_sp(cpu.get_sp() - 1);
mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);

cpu.set_sp(cpu.get_sp() - 1);
mmu.write(cpu.get_sp(), pc & 0xFF);

cpu.set_pc(0x18);

return totalMachineCycles(4);
}
Loading
Loading