Usando this en todas partes :p

This commit is contained in:
2025-06-23 21:35:12 -04:00
parent b0d8e6135d
commit ae863ee4e9
16 changed files with 332 additions and 221 deletions

View File

@@ -5,24 +5,29 @@
Interpreter::Interpreter(std::shared_ptr<MachineState> machine_state):
machine_state{std::move(machine_state)},
random_generator{std::random_device{}()} {}
void Interpreter::tick() {
const uint8_t high_word = machine_state->memory[machine_state->pc];
const uint8_t low_word = machine_state->memory[machine_state->pc + 1];
const uint16_t word = high_word << 8 | low_word;
const auto instruction = decode(word);
machine_state->pc += 2;
execute_instruction(instruction);
if (machine_state->pc >= 0xFFF) {
std::cout << "PC Outside of memory, going back 0x200" << std::endl;
machine_state->pc = 0x200;
random_generator{std::random_device{}()} {
srand(time(nullptr));
for (bool& display : this->machine_state->display) {
display = rand() % 100 > 50;
}
}
Instruction Interpreter::decode(const uint16_t word) {
void Interpreter::tick() {
const uint8_t high_word = this->machine_state->memory[this->machine_state->pc];
const uint8_t low_word = this->machine_state->memory[this->machine_state->pc + 1];
const uint16_t word = high_word << 8 | low_word;
const auto instruction = this->decode(word);
this->machine_state->pc += 2;
this->execute_instruction(instruction);
if (this->machine_state->pc >= 0xFFF) {
std::cout << "PC Outside of memory, going back 0x200" << std::endl;
this->machine_state->pc = 0x200;
}
}
Instruction Interpreter::decode(const uint16_t word) const {
const uint8_t operation = (word & 0xF000) >> 12;
const uint8_t x = (word & 0x0F00) >> 8;
const uint8_t y = (word & 0x00F0) >> 4;
@@ -125,118 +130,117 @@ Instruction Interpreter::decode(const uint16_t word) {
}
void Interpreter::execute_instruction(const Instruction& instruction) {
if (instruction.op_code == OpCode::CLS) cls();
else if (instruction.op_code == OpCode::RET) ret();
else if (instruction.op_code == OpCode::SYS_ADDR) sys_addr();
else if (instruction.op_code == OpCode::JP_ADDR) jp_addr(instruction);
else if (instruction.op_code == OpCode::CALL_ADDR) call_addr(instruction);
else if (instruction.op_code == OpCode::SE_VX_BYTE) se_vx_byte(instruction);
else if (instruction.op_code == OpCode::SNE_VX_BYTE) sne_vx_byte(instruction);
else if (instruction.op_code == OpCode::SE_VX_VY) se_vx_vy(instruction);
else if (instruction.op_code == OpCode::LD_VX_BYTE) ld_vx_byte(instruction);
else if (instruction.op_code == OpCode::ADD_VX_BYTE) add_vx_byte(instruction);
else if (instruction.op_code == OpCode::LD_VX_VY) ld_vx_vy(instruction);
else if (instruction.op_code == OpCode::OR_VX_VY) or_vx_vy(instruction);
else if (instruction.op_code == OpCode::AND_VX_VY) and_vx_vy(instruction);
else if (instruction.op_code == OpCode::XOR_VX_VY) xor_vx_vy(instruction);
else if (instruction.op_code == OpCode::ADD_VX_VY) add_vx_vy(instruction);
else if (instruction.op_code == OpCode::SUB_VX_VY) sub_vx_vy(instruction);
else if (instruction.op_code == OpCode::SHR_VX_VY) shr_vx_vy(instruction);
else if (instruction.op_code == OpCode::SUBN_VX_VY) subn_vx_vy(instruction);
else if (instruction.op_code == OpCode::SHL_VX_VY) shl_vx_vy(instruction);
else if (instruction.op_code == OpCode::SNE_VX_VY) sne_vx_vy(instruction);
else if (instruction.op_code == OpCode::LD_I_ADDR) ld_i_addr(instruction);
else if (instruction.op_code == OpCode::JP_V0_ADDR) jp_v0_addr(instruction);
else if (instruction.op_code == OpCode::RND_VX_BYTE) rnd_vx_byte(instruction);
else if (instruction.op_code == OpCode::DRW_VX_VY_NIBBLE) drw_vx_vy_nibble(instruction);
else if (instruction.op_code == OpCode::SKP_VX) skp_vx(instruction);
else if (instruction.op_code == OpCode::SKNP_VX) sknp_vx(instruction);
else if (instruction.op_code == OpCode::LD_VX_DT) ld_vx_dt(instruction);
else if (instruction.op_code == OpCode::LD_VX_K) ld_vx_k(instruction);
else if (instruction.op_code == OpCode::LD_DT_VX) ld_dt_vx(instruction);
else if (instruction.op_code == OpCode::LD_ST_VX) ld_st_vx(instruction);
else if (instruction.op_code == OpCode::ADD_I_VX) add_i_vx(instruction);
else if (instruction.op_code == OpCode::LD_F_VX) ld_f_vx(instruction);
else if (instruction.op_code == OpCode::LD_B_VX) ld_b_vx(instruction);
else if (instruction.op_code == OpCode::LD_I_VX) ld_i_vx(instruction);
else if (instruction.op_code == OpCode::LD_VX_I) ld_vx_i(instruction);
else if (instruction.op_code == OpCode::NOP) nop();
if (instruction.op_code == OpCode::CLS) this->cls();
else if (instruction.op_code == OpCode::RET) this->ret();
else if (instruction.op_code == OpCode::SYS_ADDR) this->sys_addr();
else if (instruction.op_code == OpCode::JP_ADDR) this->jp_addr(instruction);
else if (instruction.op_code == OpCode::CALL_ADDR) this->call_addr(instruction);
else if (instruction.op_code == OpCode::SE_VX_BYTE) this->se_vx_byte(instruction);
else if (instruction.op_code == OpCode::SNE_VX_BYTE) this->sne_vx_byte(instruction);
else if (instruction.op_code == OpCode::SE_VX_VY) this->se_vx_vy(instruction);
else if (instruction.op_code == OpCode::LD_VX_BYTE) this->ld_vx_byte(instruction);
else if (instruction.op_code == OpCode::ADD_VX_BYTE) this->add_vx_byte(instruction);
else if (instruction.op_code == OpCode::LD_VX_VY) this->ld_vx_vy(instruction);
else if (instruction.op_code == OpCode::OR_VX_VY) this->or_vx_vy(instruction);
else if (instruction.op_code == OpCode::AND_VX_VY) this->and_vx_vy(instruction);
else if (instruction.op_code == OpCode::XOR_VX_VY) this->xor_vx_vy(instruction);
else if (instruction.op_code == OpCode::ADD_VX_VY) this->add_vx_vy(instruction);
else if (instruction.op_code == OpCode::SUB_VX_VY) this->sub_vx_vy(instruction);
else if (instruction.op_code == OpCode::SHR_VX_VY) this->shr_vx_vy(instruction);
else if (instruction.op_code == OpCode::SUBN_VX_VY) this->subn_vx_vy(instruction);
else if (instruction.op_code == OpCode::SHL_VX_VY) this->shl_vx_vy(instruction);
else if (instruction.op_code == OpCode::SNE_VX_VY) this->sne_vx_vy(instruction);
else if (instruction.op_code == OpCode::LD_I_ADDR) this->ld_i_addr(instruction);
else if (instruction.op_code == OpCode::JP_V0_ADDR) this->jp_v0_addr(instruction);
else if (instruction.op_code == OpCode::RND_VX_BYTE) this->rnd_vx_byte(instruction);
else if (instruction.op_code == OpCode::DRW_VX_VY_NIBBLE) this->drw_vx_vy_nibble(instruction);
else if (instruction.op_code == OpCode::SKP_VX) this->skp_vx(instruction);
else if (instruction.op_code == OpCode::SKNP_VX) this->sknp_vx(instruction);
else if (instruction.op_code == OpCode::LD_VX_DT) this->ld_vx_dt(instruction);
else if (instruction.op_code == OpCode::LD_VX_K) this->ld_vx_k(instruction);
else if (instruction.op_code == OpCode::LD_DT_VX) this->ld_dt_vx(instruction);
else if (instruction.op_code == OpCode::LD_ST_VX) this->ld_st_vx(instruction);
else if (instruction.op_code == OpCode::ADD_I_VX) this->add_i_vx(instruction);
else if (instruction.op_code == OpCode::LD_F_VX) this->ld_f_vx(instruction);
else if (instruction.op_code == OpCode::LD_B_VX) this->ld_b_vx(instruction);
else if (instruction.op_code == OpCode::LD_I_VX) this->ld_i_vx(instruction);
else if (instruction.op_code == OpCode::LD_VX_I) this->ld_vx_i(instruction);
else if (instruction.op_code == OpCode::NOP) this->nop();
}
void Interpreter::sys_addr() {
void Interpreter::sys_addr() const {
// NOP
}
void Interpreter::nop() {
void Interpreter::nop() const {
// NOP
}
void Interpreter::cls() const {
machine_state->display.fill(false);
this->machine_state->display.fill(false);
}
void Interpreter::ret() const {
machine_state->sp -= 1;
machine_state->pc = machine_state->stack[machine_state->sp];
this->machine_state->sp -= 1;
this->machine_state->pc = this->machine_state->stack[this->machine_state->sp];
}
void Interpreter::jp_addr(const Instruction& instruction) const {
machine_state->pc = instruction.nnn;
this->machine_state->pc = instruction.nnn;
}
void Interpreter::call_addr(const Instruction& instruction) const {
machine_state->stack[machine_state->sp] = machine_state->pc;
machine_state->sp += 1;
machine_state->pc = instruction.nnn;
this->machine_state->stack[this->machine_state->sp] = this->machine_state->pc;
this->machine_state->sp += 1;
this->machine_state->pc = instruction.nnn;
}
void Interpreter::se_vx_byte(const Instruction& instruction) const {
if (machine_state->v[instruction.x] == instruction.kk) {
machine_state->pc += 2;
if (this->machine_state->v[instruction.x] == instruction.kk) {
this->machine_state->pc += 2;
}
}
void Interpreter::sne_vx_byte(const Instruction& instruction) const {
if (machine_state->v[instruction.x] != instruction.kk) {
machine_state->pc += 2;
if (this->machine_state->v[instruction.x] != instruction.kk) {
this->machine_state->pc += 2;
}
}
void Interpreter::se_vx_vy(const Instruction& instruction) const {
if (machine_state->v[instruction.x] == machine_state->v[instruction.y]) {
machine_state->pc += 2;
if (this->machine_state->v[instruction.x] == this->machine_state->v[instruction.y]) {
this->machine_state->pc += 2;
}
}
void Interpreter::ld_vx_byte(const Instruction& instruction) const {
machine_state->v[instruction.x] = instruction.kk;
this->machine_state->v[instruction.x] = instruction.kk;
}
void Interpreter::add_vx_byte(const Instruction& instruction) const {
machine_state->v[instruction.x] += instruction.kk;
this->machine_state->v[instruction.x] += instruction.kk;
}
void Interpreter::ld_vx_vy(const Instruction& instruction) const {
machine_state->v[instruction.x] = machine_state->v[instruction.y];
this->machine_state->v[instruction.x] = this->machine_state->v[instruction.y];
}
void Interpreter::or_vx_vy(const Instruction& instruction) const {
machine_state->v[instruction.x] |= machine_state->v[instruction.y];
this->machine_state->v[instruction.x] |= this->machine_state->v[instruction.y];
}
void Interpreter::and_vx_vy(const Instruction& instruction) const {
machine_state->v[instruction.x] &= machine_state->v[instruction.y];
this->machine_state->v[instruction.x] &= this->machine_state->v[instruction.y];
}
void Interpreter::xor_vx_vy(const Instruction& instruction) const {
machine_state->v[instruction.x] ^= machine_state->v[instruction.y];
this->machine_state->v[instruction.x] ^= this->machine_state->v[instruction.y];
}
void Interpreter::add_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF];
auto& vx = this->machine_state->v[instruction.x];
const auto& vy = this->machine_state->v[instruction.y];
auto& vf = this->machine_state->v[0xF];
if (vx + vy > 0xFF) {
vf = 1;
@@ -248,9 +252,9 @@ void Interpreter::add_vx_vy(const Instruction& instruction) const {
}
void Interpreter::sub_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF];
auto& vx = this->machine_state->v[instruction.x];
const auto& vy = this->machine_state->v[instruction.y];
auto& vf = this->machine_state->v[0xF];
if (vx > vy) {
vf = 1;
@@ -262,9 +266,9 @@ void Interpreter::sub_vx_vy(const Instruction& instruction) const {
}
void Interpreter::shr_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF];
auto& vx = this->machine_state->v[instruction.x];
const auto& vy = this->machine_state->v[instruction.y];
auto& vf = this->machine_state->v[0xF];
if (quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_SHIFT)) {
vx = vy;
@@ -280,9 +284,9 @@ void Interpreter::shr_vx_vy(const Instruction& instruction) const {
}
void Interpreter::subn_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF];
auto& vx = this->machine_state->v[instruction.x];
const auto& vy = this->machine_state->v[instruction.y];
auto& vf = this->machine_state->v[0xF];
if (vy > vx) {
vf = 1;
@@ -294,11 +298,11 @@ void Interpreter::subn_vx_vy(const Instruction& instruction) const {
}
void Interpreter::shl_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF];
auto& vx = this->machine_state->v[instruction.x];
const auto& vy = this->machine_state->v[instruction.y];
auto& vf = this->machine_state->v[0xF];
if (quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_SHIFT)) {
if (this->quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_SHIFT)) {
vx = vy;
}
@@ -312,36 +316,37 @@ void Interpreter::shl_vx_vy(const Instruction& instruction) const {
}
void Interpreter::sne_vx_vy(const Instruction& instruction) const {
if (machine_state->v[instruction.x] != machine_state->v[instruction.y]) {
machine_state->pc += 2;
if (this->machine_state->v[instruction.x] != this->machine_state->v[instruction.y]) {
this->machine_state->pc += 2;
}
}
void Interpreter::ld_i_addr(const Instruction& instruction) const {
machine_state->i = instruction.nnn;
this->machine_state->i = instruction.nnn;
}
void Interpreter::jp_v0_addr(const Instruction& instruction) const {
if (quirks & static_cast<uint8_t>(InterpreterQuirks::SUPER_CHIP_JUMP)) {
machine_state->pc = instruction.nnn + machine_state->v[instruction.x];
if (this->quirks & static_cast<uint8_t>(InterpreterQuirks::SUPER_CHIP_JUMP)) {
this->machine_state->pc = instruction.nnn + this->machine_state->v[instruction.x];
} else {
machine_state->pc = instruction.nnn + machine_state->v[0];
this->machine_state->pc = instruction.nnn + this->machine_state->v[0];
}
}
void Interpreter::rnd_vx_byte(const Instruction& instruction) {
auto random = std::uniform_int_distribution<uint8_t>(0, 0xFF);
const auto value = random(random_generator);
auto distribution = std::uniform_int_distribution<uint8_t>(0, 0xFF);
const auto value = distribution(this->random_generator);
machine_state->v[instruction.x] = value & instruction.kk;
this->machine_state->v[instruction.x] = value & instruction.kk;
}
void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const {
const auto& memory = machine_state->memory;
auto& display = machine_state->display;
const auto& vx = machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF];
const auto& memory = this->machine_state->memory;
auto& display = this->machine_state->display;
const auto& vx = this->machine_state->v[instruction.x];
const auto& vy = this->machine_state->v[instruction.y];
auto& vf = this->machine_state->v[0xF];
auto& i = this->machine_state->i;
const uint8_t start_x = vx & 63;
const uint8_t start_y = vy & 31;
@@ -354,7 +359,7 @@ void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const {
break;
}
const auto sprite_byte = memory[machine_state->i + row];
const auto sprite_byte = memory[i + row];
for (auto bit = 0; bit < 8; bit++) {
const auto current_x = start_x + bit;
@@ -379,80 +384,80 @@ void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const {
}
void Interpreter::skp_vx(const Instruction& instruction) const {
if (machine_state->keyboard & 1 << instruction.x) {
machine_state->pc += 2;
if (this->machine_state->keyboard & 1 << instruction.x) {
this->machine_state->pc += 2;
}
}
void Interpreter::sknp_vx(const Instruction& instruction) const {
if (!(machine_state->keyboard & 1 << instruction.x)) {
machine_state->pc += 2;
if (!(this->machine_state->keyboard & 1 << instruction.x)) {
this->machine_state->pc += 2;
}
}
void Interpreter::ld_vx_dt(const Instruction& instruction) const {
machine_state->v[instruction.x] = machine_state->dt;
this->machine_state->v[instruction.x] = this->machine_state->dt;
}
void Interpreter::ld_vx_k(const Instruction& instruction) const {
if (machine_state->keyboard == 0) {
machine_state->pc -= 2;
if (this->machine_state->keyboard == 0) {
this->machine_state->pc -= 2;
return;
}
for (auto key = 0; key < 16; key++) {
if (machine_state->keyboard & 1 << key) {
machine_state->v[instruction.x] = key;
if (this->machine_state->keyboard & 1 << key) {
this->machine_state->v[instruction.x] = key;
break;
}
}
}
void Interpreter::ld_dt_vx(const Instruction& instruction) const {
machine_state->dt = machine_state->v[instruction.x];
this->machine_state->dt = this->machine_state->v[instruction.x];
}
void Interpreter::ld_st_vx(const Instruction& instruction) const {
machine_state->st = machine_state->v[instruction.x];
this->machine_state->st = this->machine_state->v[instruction.x];
}
void Interpreter::add_i_vx(const Instruction& instruction) const {
machine_state->i += machine_state->v[instruction.x];
this->machine_state->i += this->machine_state->v[instruction.x];
}
void Interpreter::ld_f_vx(const Instruction& instruction) const {
machine_state->i = (machine_state->v[instruction.x] & 0xF) * 5 + 0x50;
this->machine_state->i = (this->machine_state->v[instruction.x] & 0xF) * 5 + 0x50;
}
void Interpreter::ld_b_vx(const Instruction& instruction) const {
const auto number = machine_state->v[instruction.x];
machine_state->memory[machine_state->i] = number / 100;
machine_state->memory[machine_state->i + 1] = (number - machine_state->memory[machine_state->i] * 100) / 10;
machine_state->memory[machine_state->i + 2] = number - machine_state->memory[machine_state->i] * 100 - machine_state->memory[machine_state->i + 1] * 10;
const auto number = this->machine_state->v[instruction.x];
this->machine_state->memory[this->machine_state->i] = number / 100;
this->machine_state->memory[this->machine_state->i + 1] = (number - this->machine_state->memory[this->machine_state->i] * 100) / 10;
this->machine_state->memory[this->machine_state->i + 2] = number - this->machine_state->memory[this->machine_state->i] * 100 - this->machine_state->memory[this->machine_state->i + 1] * 10;
}
void Interpreter::ld_i_vx(const Instruction& instruction) const {
const bool use_quirk = quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_STORE_AND_LOAD);
const bool use_quirk = this->quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_STORE_AND_LOAD);
for (auto reg = 0; reg <= instruction.x; reg++) {
if (use_quirk) {
machine_state->memory[machine_state->i] = machine_state->v[reg];
machine_state->i++;
this->machine_state->memory[this->machine_state->i] = this->machine_state->v[reg];
this->machine_state->i++;
} else {
machine_state->memory[machine_state->i + reg] = machine_state->v[reg];
this->machine_state->memory[this->machine_state->i + reg] = this->machine_state->v[reg];
}
}
}
void Interpreter::ld_vx_i(const Instruction& instruction) const {
const bool use_quirk = quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_STORE_AND_LOAD);
const bool use_quirk = this->quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_STORE_AND_LOAD);
for (auto reg = 0; reg <= instruction.x; reg++) {
if (use_quirk) {
machine_state->v[reg] = machine_state->memory[machine_state->i];
machine_state->i++;
this->machine_state->v[reg] = this->machine_state->memory[this->machine_state->i];
this->machine_state->i++;
} else {
machine_state->v[reg] = machine_state->memory[machine_state->i + reg];
this->machine_state->v[reg] = this->machine_state->memory[this->machine_state->i + reg];
}
}
}