Aplicando formato default de jetbrains :c
This commit is contained in:
18
.idea/editor.xml
generated
18
.idea/editor.xml
generated
@@ -244,23 +244,5 @@
|
|||||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALLOW_COMMENT_AFTER_LBRACE/@EntryValue" value="true" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/DISABLE_SPACE_CHANGES_BEFORE_TRAILING_COMMENT/@EntryValue" value="true" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/EMPTY_BLOCK_STYLE/@EntryValue" value="TOGETHER" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/EXPORT_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_COMMENTS/@EntryValue" value="true" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_ENUM_INITIALIZERS/@EntryValue" value="true" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/REQUIRES_EXPRESSION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
|
||||||
<option name="/Default/CodeStyle/CppIncludeDirective/SortIncludeDirectives/@EntryValue" value="true" type="bool" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -2,12 +2,15 @@
|
|||||||
#define COLOR_H
|
#define COLOR_H
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
struct Color {
|
struct Color
|
||||||
|
{
|
||||||
uint8_t r;
|
uint8_t r;
|
||||||
uint8_t g;
|
uint8_t g;
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
|
|
||||||
Color(const uint8_t r, const uint8_t g, const uint8_t b) : r(r), g(g), b(b) {}
|
Color(const uint8_t r, const uint8_t g, const uint8_t b) : r(r), g(g), b(b)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //COLOR_H
|
#endif //COLOR_H
|
||||||
@@ -8,15 +8,18 @@
|
|||||||
#include "imgui_impl_sdl3.h"
|
#include "imgui_impl_sdl3.h"
|
||||||
#include "imgui_impl_sdlrenderer3.h"
|
#include "imgui_impl_sdlrenderer3.h"
|
||||||
|
|
||||||
Graphics::Graphics(): window_width{1366}, window_height{768}, main_scale{1.0f} {
|
Graphics::Graphics() : window_width{1366}, window_height{768}, main_scale{1.0f}
|
||||||
|
{
|
||||||
create_sdl();
|
create_sdl();
|
||||||
create_imgui();
|
create_imgui();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::create_sdl() {
|
void Graphics::create_sdl()
|
||||||
|
{
|
||||||
SDL_SetAppMetadata("CHIP-8 Emulator", "0.0.1", "fun.skrd.chip8");
|
SDL_SetAppMetadata("CHIP-8 Emulator", "0.0.1", "fun.skrd.chip8");
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
if (!SDL_Init(SDL_INIT_VIDEO))
|
||||||
|
{
|
||||||
throw std::runtime_error(std::format("Couldn't initialize SDL: {}", SDL_GetError()));
|
throw std::runtime_error(std::format("Couldn't initialize SDL: {}", SDL_GetError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +36,8 @@ void Graphics::create_sdl() {
|
|||||||
window_flags,
|
window_flags,
|
||||||
&raw_window,
|
&raw_window,
|
||||||
&raw_renderer
|
&raw_renderer
|
||||||
)) {
|
))
|
||||||
|
{
|
||||||
throw std::runtime_error(std::format("Couldn't create window/renderer: {}", SDL_GetError()));
|
throw std::runtime_error(std::format("Couldn't create window/renderer: {}", SDL_GetError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +49,8 @@ void Graphics::create_sdl() {
|
|||||||
SDL_ShowWindow(this->window.get());
|
SDL_ShowWindow(this->window.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::create_imgui() const {
|
void Graphics::create_imgui() const
|
||||||
|
{
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
|
|
||||||
@@ -62,21 +67,26 @@ void Graphics::create_imgui() const {
|
|||||||
ImGui_ImplSDLRenderer3_Init(this->renderer.get());
|
ImGui_ImplSDLRenderer3_Init(this->renderer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SDL_Renderer> Graphics::get_renderer() {
|
std::shared_ptr<SDL_Renderer> Graphics::get_renderer()
|
||||||
|
{
|
||||||
return this->renderer;
|
return this->renderer;
|
||||||
}
|
}
|
||||||
std::shared_ptr<SDL_Window> Graphics::get_window() {
|
|
||||||
|
std::shared_ptr<SDL_Window> Graphics::get_window()
|
||||||
|
{
|
||||||
return this->window;
|
return this->window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::start() const {
|
void Graphics::start() const
|
||||||
|
{
|
||||||
ImGui_ImplSDLRenderer3_NewFrame();
|
ImGui_ImplSDLRenderer3_NewFrame();
|
||||||
ImGui_ImplSDL3_NewFrame();
|
ImGui_ImplSDL3_NewFrame();
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());
|
ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::end() const {
|
void Graphics::end() const
|
||||||
|
{
|
||||||
const ImGuiIO& io = ImGui::GetIO();
|
const ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "SDL3/SDL.h"
|
#include "SDL3/SDL.h"
|
||||||
|
|
||||||
struct SDLWindowDestroyer {
|
struct SDLWindowDestroyer
|
||||||
|
{
|
||||||
void operator()(SDL_Window* window) const;
|
void operator()(SDL_Window* window) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Graphics {
|
class Graphics
|
||||||
|
{
|
||||||
int window_width;
|
int window_width;
|
||||||
int window_height;
|
int window_height;
|
||||||
float main_scale;
|
float main_scale;
|
||||||
@@ -18,6 +20,7 @@ class Graphics {
|
|||||||
|
|
||||||
void create_sdl();
|
void create_sdl();
|
||||||
void create_imgui() const;
|
void create_imgui() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Graphics();
|
Graphics();
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
#include "OpCode.h"
|
#include "OpCode.h"
|
||||||
|
|
||||||
struct Instruction {
|
struct Instruction
|
||||||
|
{
|
||||||
OpCode op_code;
|
OpCode op_code;
|
||||||
uint8_t operation;
|
uint8_t operation;
|
||||||
uint16_t instruction;
|
uint16_t instruction;
|
||||||
|
|||||||
@@ -3,16 +3,19 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
Interpreter::Interpreter(std::shared_ptr<MachineState> machine_state):
|
Interpreter::Interpreter(std::shared_ptr<MachineState> machine_state) :
|
||||||
machine_state{std::move(machine_state)},
|
machine_state{std::move(machine_state)},
|
||||||
random_generator{std::random_device{}()} {
|
random_generator{std::random_device{}()}
|
||||||
|
{
|
||||||
srand(time(nullptr));
|
srand(time(nullptr));
|
||||||
for (bool& display : this->machine_state->display) {
|
for (bool& display : this->machine_state->display)
|
||||||
|
{
|
||||||
display = rand() % 100 > 50;
|
display = rand() % 100 > 50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::tick() {
|
void Interpreter::tick()
|
||||||
|
{
|
||||||
const uint8_t high_word = this->machine_state->memory[this->machine_state->pc];
|
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 uint8_t low_word = this->machine_state->memory[this->machine_state->pc + 1];
|
||||||
const uint16_t word = high_word << 8 | low_word;
|
const uint16_t word = high_word << 8 | low_word;
|
||||||
@@ -21,13 +24,15 @@ void Interpreter::tick() {
|
|||||||
this->machine_state->pc += 2;
|
this->machine_state->pc += 2;
|
||||||
this->execute_instruction(instruction);
|
this->execute_instruction(instruction);
|
||||||
|
|
||||||
if (this->machine_state->pc >= 0xFFF) {
|
if (this->machine_state->pc >= 0xFFF)
|
||||||
|
{
|
||||||
std::cout << "PC Outside of memory, going back 0x200" << std::endl;
|
std::cout << "PC Outside of memory, going back 0x200" << std::endl;
|
||||||
this->machine_state->pc = 0x200;
|
this->machine_state->pc = 0x200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Interpreter::decode(const uint16_t word) const {
|
Instruction Interpreter::decode(const uint16_t word) const
|
||||||
|
{
|
||||||
const uint8_t operation = (word & 0xF000) >> 12;
|
const uint8_t operation = (word & 0xF000) >> 12;
|
||||||
const uint8_t x = (word & 0x0F00) >> 8;
|
const uint8_t x = (word & 0x0F00) >> 8;
|
||||||
const uint8_t y = (word & 0x00F0) >> 4;
|
const uint8_t y = (word & 0x00F0) >> 4;
|
||||||
@@ -37,82 +42,155 @@ Instruction Interpreter::decode(const uint16_t word) const {
|
|||||||
|
|
||||||
auto op_code = OpCode::NOP;
|
auto op_code = OpCode::NOP;
|
||||||
|
|
||||||
if (operation == 0) {
|
if (operation == 0)
|
||||||
if (kk == 0xE0) {
|
{
|
||||||
|
if (kk == 0xE0)
|
||||||
|
{
|
||||||
op_code = OpCode::CLS;
|
op_code = OpCode::CLS;
|
||||||
} else if (kk == 0xEE) {
|
}
|
||||||
|
else if (kk == 0xEE)
|
||||||
|
{
|
||||||
op_code = OpCode::RET;
|
op_code = OpCode::RET;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
op_code = OpCode::SYS_ADDR;
|
op_code = OpCode::SYS_ADDR;
|
||||||
}
|
}
|
||||||
} else if (operation == 1) {
|
}
|
||||||
|
else if (operation == 1)
|
||||||
|
{
|
||||||
op_code = OpCode::JP_ADDR;
|
op_code = OpCode::JP_ADDR;
|
||||||
} else if (operation == 2) {
|
}
|
||||||
|
else if (operation == 2)
|
||||||
|
{
|
||||||
op_code = OpCode::CALL_ADDR;
|
op_code = OpCode::CALL_ADDR;
|
||||||
} else if (operation == 3) {
|
}
|
||||||
|
else if (operation == 3)
|
||||||
|
{
|
||||||
op_code = OpCode::SE_VX_BYTE;
|
op_code = OpCode::SE_VX_BYTE;
|
||||||
} else if (operation == 4) {
|
}
|
||||||
|
else if (operation == 4)
|
||||||
|
{
|
||||||
op_code = OpCode::SNE_VX_BYTE;
|
op_code = OpCode::SNE_VX_BYTE;
|
||||||
} else if (operation == 5) {
|
}
|
||||||
|
else if (operation == 5)
|
||||||
|
{
|
||||||
op_code = OpCode::SE_VX_VY;
|
op_code = OpCode::SE_VX_VY;
|
||||||
} else if (operation == 6) {
|
}
|
||||||
|
else if (operation == 6)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_VX_BYTE;
|
op_code = OpCode::LD_VX_BYTE;
|
||||||
} else if (operation == 7) {
|
}
|
||||||
|
else if (operation == 7)
|
||||||
|
{
|
||||||
op_code = OpCode::ADD_VX_BYTE;
|
op_code = OpCode::ADD_VX_BYTE;
|
||||||
} else if (operation == 8) {
|
}
|
||||||
if (n == 0) {
|
else if (operation == 8)
|
||||||
|
{
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_VX_VY;
|
op_code = OpCode::LD_VX_VY;
|
||||||
} else if (n == 1) {
|
}
|
||||||
|
else if (n == 1)
|
||||||
|
{
|
||||||
op_code = OpCode::OR_VX_VY;
|
op_code = OpCode::OR_VX_VY;
|
||||||
} else if (n == 2) {
|
}
|
||||||
|
else if (n == 2)
|
||||||
|
{
|
||||||
op_code = OpCode::AND_VX_VY;
|
op_code = OpCode::AND_VX_VY;
|
||||||
} else if (n == 3) {
|
}
|
||||||
|
else if (n == 3)
|
||||||
|
{
|
||||||
op_code = OpCode::XOR_VX_VY;
|
op_code = OpCode::XOR_VX_VY;
|
||||||
} else if (n == 4) {
|
}
|
||||||
|
else if (n == 4)
|
||||||
|
{
|
||||||
op_code = OpCode::ADD_VX_VY;
|
op_code = OpCode::ADD_VX_VY;
|
||||||
} else if (n == 5) {
|
}
|
||||||
|
else if (n == 5)
|
||||||
|
{
|
||||||
op_code = OpCode::SUB_VX_VY;
|
op_code = OpCode::SUB_VX_VY;
|
||||||
} else if (n == 6) {
|
}
|
||||||
|
else if (n == 6)
|
||||||
|
{
|
||||||
op_code = OpCode::SHR_VX_VY;
|
op_code = OpCode::SHR_VX_VY;
|
||||||
} else if (n == 7) {
|
}
|
||||||
|
else if (n == 7)
|
||||||
|
{
|
||||||
op_code = OpCode::SUBN_VX_VY;
|
op_code = OpCode::SUBN_VX_VY;
|
||||||
} else if (n == 0xE) {
|
}
|
||||||
|
else if (n == 0xE)
|
||||||
|
{
|
||||||
op_code = OpCode::SHL_VX_VY;
|
op_code = OpCode::SHL_VX_VY;
|
||||||
}
|
}
|
||||||
} else if (operation == 9) {
|
}
|
||||||
|
else if (operation == 9)
|
||||||
|
{
|
||||||
op_code = OpCode::SNE_VX_VY;
|
op_code = OpCode::SNE_VX_VY;
|
||||||
} else if (operation == 0xA) {
|
}
|
||||||
|
else if (operation == 0xA)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_I_ADDR;
|
op_code = OpCode::LD_I_ADDR;
|
||||||
} else if (operation == 0xB) {
|
}
|
||||||
|
else if (operation == 0xB)
|
||||||
|
{
|
||||||
op_code = OpCode::JP_V0_ADDR;
|
op_code = OpCode::JP_V0_ADDR;
|
||||||
} else if (operation == 0xC) {
|
}
|
||||||
|
else if (operation == 0xC)
|
||||||
|
{
|
||||||
op_code = OpCode::RND_VX_BYTE;
|
op_code = OpCode::RND_VX_BYTE;
|
||||||
} else if (operation == 0xD) {
|
}
|
||||||
|
else if (operation == 0xD)
|
||||||
|
{
|
||||||
op_code = OpCode::DRW_VX_VY_NIBBLE;
|
op_code = OpCode::DRW_VX_VY_NIBBLE;
|
||||||
} else if (operation == 0xE) {
|
}
|
||||||
if (kk == 0x9E) {
|
else if (operation == 0xE)
|
||||||
|
{
|
||||||
|
if (kk == 0x9E)
|
||||||
|
{
|
||||||
op_code = OpCode::SKP_VX;
|
op_code = OpCode::SKP_VX;
|
||||||
} else if (kk == 0xA1) {
|
}
|
||||||
|
else if (kk == 0xA1)
|
||||||
|
{
|
||||||
op_code = OpCode::SKNP_VX;
|
op_code = OpCode::SKNP_VX;
|
||||||
}
|
}
|
||||||
} else if (operation == 0xF) {
|
}
|
||||||
if (kk == 0x07) {
|
else if (operation == 0xF)
|
||||||
|
{
|
||||||
|
if (kk == 0x07)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_VX_DT;
|
op_code = OpCode::LD_VX_DT;
|
||||||
} else if (kk == 0x0A) {
|
}
|
||||||
|
else if (kk == 0x0A)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_VX_K;
|
op_code = OpCode::LD_VX_K;
|
||||||
} else if (kk == 0x15) {
|
}
|
||||||
|
else if (kk == 0x15)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_DT_VX;
|
op_code = OpCode::LD_DT_VX;
|
||||||
} else if (kk == 0x18) {
|
}
|
||||||
|
else if (kk == 0x18)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_ST_VX;
|
op_code = OpCode::LD_ST_VX;
|
||||||
} else if (kk == 0x1E) {
|
}
|
||||||
|
else if (kk == 0x1E)
|
||||||
|
{
|
||||||
op_code = OpCode::ADD_I_VX;
|
op_code = OpCode::ADD_I_VX;
|
||||||
} else if (kk == 0x29) {
|
}
|
||||||
|
else if (kk == 0x29)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_F_VX;
|
op_code = OpCode::LD_F_VX;
|
||||||
} else if (kk == 0x33) {
|
}
|
||||||
|
else if (kk == 0x33)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_B_VX;
|
op_code = OpCode::LD_B_VX;
|
||||||
} else if (kk == 0x55) {
|
}
|
||||||
|
else if (kk == 0x55)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_I_VX;
|
op_code = OpCode::LD_I_VX;
|
||||||
} else if (kk == 0x65) {
|
}
|
||||||
|
else if (kk == 0x65)
|
||||||
|
{
|
||||||
op_code = OpCode::LD_VX_I;
|
op_code = OpCode::LD_VX_I;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +207,8 @@ Instruction Interpreter::decode(const uint16_t word) const {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::execute_instruction(const Instruction& instruction) {
|
void Interpreter::execute_instruction(const Instruction& instruction)
|
||||||
|
{
|
||||||
if (instruction.op_code == OpCode::CLS) this->cls();
|
if (instruction.op_code == OpCode::CLS) this->cls();
|
||||||
else if (instruction.op_code == OpCode::RET) this->ret();
|
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::SYS_ADDR) this->sys_addr();
|
||||||
@@ -168,179 +247,228 @@ void Interpreter::execute_instruction(const Instruction& instruction) {
|
|||||||
else if (instruction.op_code == OpCode::NOP) this->nop();
|
else if (instruction.op_code == OpCode::NOP) this->nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sys_addr() const {
|
void Interpreter::sys_addr() const
|
||||||
|
{
|
||||||
// NOP
|
// NOP
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::nop() const {
|
void Interpreter::nop() const
|
||||||
|
{
|
||||||
// NOP
|
// NOP
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::cls() const {
|
void Interpreter::cls() const
|
||||||
|
{
|
||||||
this->machine_state->display.fill(false);
|
this->machine_state->display.fill(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ret() const {
|
void Interpreter::ret() const
|
||||||
|
{
|
||||||
this->machine_state->sp -= 1;
|
this->machine_state->sp -= 1;
|
||||||
this->machine_state->pc = this->machine_state->stack[this->machine_state->sp];
|
this->machine_state->pc = this->machine_state->stack[this->machine_state->sp];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::jp_addr(const Instruction& instruction) const {
|
void Interpreter::jp_addr(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->pc = instruction.nnn;
|
this->machine_state->pc = instruction.nnn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::call_addr(const Instruction& instruction) const {
|
void Interpreter::call_addr(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->stack[this->machine_state->sp] = this->machine_state->pc;
|
this->machine_state->stack[this->machine_state->sp] = this->machine_state->pc;
|
||||||
this->machine_state->sp += 1;
|
this->machine_state->sp += 1;
|
||||||
this->machine_state->pc = instruction.nnn;
|
this->machine_state->pc = instruction.nnn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::se_vx_byte(const Instruction& instruction) const {
|
void Interpreter::se_vx_byte(const Instruction& instruction) const
|
||||||
if (this->machine_state->v[instruction.x] == instruction.kk) {
|
{
|
||||||
|
if (this->machine_state->v[instruction.x] == instruction.kk)
|
||||||
|
{
|
||||||
this->machine_state->pc += 2;
|
this->machine_state->pc += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sne_vx_byte(const Instruction& instruction) const {
|
void Interpreter::sne_vx_byte(const Instruction& instruction) const
|
||||||
if (this->machine_state->v[instruction.x] != instruction.kk) {
|
{
|
||||||
|
if (this->machine_state->v[instruction.x] != instruction.kk)
|
||||||
|
{
|
||||||
this->machine_state->pc += 2;
|
this->machine_state->pc += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::se_vx_vy(const Instruction& instruction) const {
|
void Interpreter::se_vx_vy(const Instruction& instruction) const
|
||||||
if (this->machine_state->v[instruction.x] == this->machine_state->v[instruction.y]) {
|
{
|
||||||
|
if (this->machine_state->v[instruction.x] == this->machine_state->v[instruction.y])
|
||||||
|
{
|
||||||
this->machine_state->pc += 2;
|
this->machine_state->pc += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_vx_byte(const Instruction& instruction) const {
|
void Interpreter::ld_vx_byte(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] = instruction.kk;
|
this->machine_state->v[instruction.x] = instruction.kk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::add_vx_byte(const Instruction& instruction) const {
|
void Interpreter::add_vx_byte(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] += instruction.kk;
|
this->machine_state->v[instruction.x] += instruction.kk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_vx_vy(const Instruction& instruction) const {
|
void Interpreter::ld_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] = this->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 {
|
void Interpreter::or_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] |= this->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 {
|
void Interpreter::and_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] &= this->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 {
|
void Interpreter::xor_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] ^= this->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 {
|
void Interpreter::add_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
auto& vx = this->machine_state->v[instruction.x];
|
auto& vx = this->machine_state->v[instruction.x];
|
||||||
const auto& vy = this->machine_state->v[instruction.y];
|
const auto& vy = this->machine_state->v[instruction.y];
|
||||||
auto& vf = this->machine_state->v[0xF];
|
auto& vf = this->machine_state->v[0xF];
|
||||||
|
|
||||||
if (vx + vy > 0xFF) {
|
if (vx + vy > 0xFF)
|
||||||
|
{
|
||||||
vf = 1;
|
vf = 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vf = 0;
|
vf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vx += vy;
|
vx += vy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sub_vx_vy(const Instruction& instruction) const {
|
void Interpreter::sub_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
auto& vx = this->machine_state->v[instruction.x];
|
auto& vx = this->machine_state->v[instruction.x];
|
||||||
const auto& vy = this->machine_state->v[instruction.y];
|
const auto& vy = this->machine_state->v[instruction.y];
|
||||||
auto& vf = this->machine_state->v[0xF];
|
auto& vf = this->machine_state->v[0xF];
|
||||||
|
|
||||||
if (vx > vy) {
|
if (vx > vy)
|
||||||
|
{
|
||||||
vf = 1;
|
vf = 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vf = 0;
|
vf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vx -= vy;
|
vx -= vy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::shr_vx_vy(const Instruction& instruction) const {
|
void Interpreter::shr_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
auto& vx = this->machine_state->v[instruction.x];
|
auto& vx = this->machine_state->v[instruction.x];
|
||||||
const auto& vy = this->machine_state->v[instruction.y];
|
const auto& vy = this->machine_state->v[instruction.y];
|
||||||
auto& vf = this->machine_state->v[0xF];
|
auto& vf = this->machine_state->v[0xF];
|
||||||
|
|
||||||
if (quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_SHIFT)) {
|
if (quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_SHIFT))
|
||||||
|
{
|
||||||
vx = vy;
|
vx = vy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vx & 0x01) {
|
if (vx & 0x01)
|
||||||
|
{
|
||||||
vf = 1;
|
vf = 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vf = 0;
|
vf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vx = vx >> 1;
|
vx = vx >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::subn_vx_vy(const Instruction& instruction) const {
|
void Interpreter::subn_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
auto& vx = this->machine_state->v[instruction.x];
|
auto& vx = this->machine_state->v[instruction.x];
|
||||||
const auto& vy = this->machine_state->v[instruction.y];
|
const auto& vy = this->machine_state->v[instruction.y];
|
||||||
auto& vf = this->machine_state->v[0xF];
|
auto& vf = this->machine_state->v[0xF];
|
||||||
|
|
||||||
if (vy > vx) {
|
if (vy > vx)
|
||||||
|
{
|
||||||
vf = 1;
|
vf = 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vf = 0;
|
vf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vx = vy - vx;
|
vx = vy - vx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::shl_vx_vy(const Instruction& instruction) const {
|
void Interpreter::shl_vx_vy(const Instruction& instruction) const
|
||||||
|
{
|
||||||
auto& vx = this->machine_state->v[instruction.x];
|
auto& vx = this->machine_state->v[instruction.x];
|
||||||
const auto& vy = this->machine_state->v[instruction.y];
|
const auto& vy = this->machine_state->v[instruction.y];
|
||||||
auto& vf = this->machine_state->v[0xF];
|
auto& vf = this->machine_state->v[0xF];
|
||||||
|
|
||||||
if (this->quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_SHIFT)) {
|
if (this->quirks & static_cast<uint8_t>(InterpreterQuirks::COSMAC_SHIFT))
|
||||||
|
{
|
||||||
vx = vy;
|
vx = vy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vx & 0x80) {
|
if (vx & 0x80)
|
||||||
|
{
|
||||||
vf = 1;
|
vf = 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vf = 0;
|
vf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vx = vx << 1;
|
vx = vx << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sne_vx_vy(const Instruction& instruction) const {
|
void Interpreter::sne_vx_vy(const Instruction& instruction) const
|
||||||
if (this->machine_state->v[instruction.x] != this->machine_state->v[instruction.y]) {
|
{
|
||||||
|
if (this->machine_state->v[instruction.x] != this->machine_state->v[instruction.y])
|
||||||
|
{
|
||||||
this->machine_state->pc += 2;
|
this->machine_state->pc += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_i_addr(const Instruction& instruction) const {
|
void Interpreter::ld_i_addr(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->i = instruction.nnn;
|
this->machine_state->i = instruction.nnn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::jp_v0_addr(const Instruction& instruction) const {
|
void Interpreter::jp_v0_addr(const Instruction& instruction) const
|
||||||
if (this->quirks & static_cast<uint8_t>(InterpreterQuirks::SUPER_CHIP_JUMP)) {
|
{
|
||||||
|
if (this->quirks & static_cast<uint8_t>(InterpreterQuirks::SUPER_CHIP_JUMP))
|
||||||
|
{
|
||||||
this->machine_state->pc = instruction.nnn + this->machine_state->v[instruction.x];
|
this->machine_state->pc = instruction.nnn + this->machine_state->v[instruction.x];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
this->machine_state->pc = instruction.nnn + this->machine_state->v[0];
|
this->machine_state->pc = instruction.nnn + this->machine_state->v[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::rnd_vx_byte(const Instruction& instruction) {
|
void Interpreter::rnd_vx_byte(const Instruction& instruction)
|
||||||
|
{
|
||||||
auto distribution = std::uniform_int_distribution<uint8_t>(0, 0xFF);
|
auto distribution = std::uniform_int_distribution<uint8_t>(0, 0xFF);
|
||||||
const auto value = distribution(this->random_generator);
|
const auto value = distribution(this->random_generator);
|
||||||
|
|
||||||
this->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 {
|
void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const
|
||||||
|
{
|
||||||
const auto& memory = this->machine_state->memory;
|
const auto& memory = this->machine_state->memory;
|
||||||
auto& display = this->machine_state->display;
|
auto& display = this->machine_state->display;
|
||||||
const auto& vx = this->machine_state->v[instruction.x];
|
const auto& vx = this->machine_state->v[instruction.x];
|
||||||
@@ -352,30 +480,38 @@ void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const {
|
|||||||
const uint8_t start_y = vy & 31;
|
const uint8_t start_y = vy & 31;
|
||||||
vf = 0;
|
vf = 0;
|
||||||
|
|
||||||
for (auto row = 0; row < instruction.n; row++) {
|
for (auto row = 0; row < instruction.n; row++)
|
||||||
|
{
|
||||||
const auto current_y = start_y + row;
|
const auto current_y = start_y + row;
|
||||||
|
|
||||||
if (current_y > 31) {
|
if (current_y > 31)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto sprite_byte = memory[i + row];
|
const auto sprite_byte = memory[i + row];
|
||||||
|
|
||||||
for (auto bit = 0; bit < 8; bit++) {
|
for (auto bit = 0; bit < 8; bit++)
|
||||||
|
{
|
||||||
const auto current_x = start_x + bit;
|
const auto current_x = start_x + bit;
|
||||||
|
|
||||||
if (current_x > 63) {
|
if (current_x > 63)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto pixel = sprite_byte >> (7 - bit) & 0x01;
|
const auto pixel = sprite_byte >> (7 - bit) & 0x01;
|
||||||
const auto index = current_y * 64 + current_x;
|
const auto index = current_y * 64 + current_x;
|
||||||
|
|
||||||
if (pixel) {
|
if (pixel)
|
||||||
if (display[index]) {
|
{
|
||||||
|
if (display[index])
|
||||||
|
{
|
||||||
display[index] = false;
|
display[index] = false;
|
||||||
vf = 1;
|
vf = 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
display[index] = true;
|
display[index] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,80 +519,106 @@ void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::skp_vx(const Instruction& instruction) const {
|
void Interpreter::skp_vx(const Instruction& instruction) const
|
||||||
if (this->machine_state->keyboard & 1 << instruction.x) {
|
{
|
||||||
|
if (this->machine_state->keyboard & 1 << instruction.x)
|
||||||
|
{
|
||||||
this->machine_state->pc += 2;
|
this->machine_state->pc += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sknp_vx(const Instruction& instruction) const {
|
void Interpreter::sknp_vx(const Instruction& instruction) const
|
||||||
if (!(this->machine_state->keyboard & 1 << instruction.x)) {
|
{
|
||||||
|
if (!(this->machine_state->keyboard & 1 << instruction.x))
|
||||||
|
{
|
||||||
this->machine_state->pc += 2;
|
this->machine_state->pc += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_vx_dt(const Instruction& instruction) const {
|
void Interpreter::ld_vx_dt(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] = this->machine_state->dt;
|
this->machine_state->v[instruction.x] = this->machine_state->dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_vx_k(const Instruction& instruction) const {
|
void Interpreter::ld_vx_k(const Instruction& instruction) const
|
||||||
if (this->machine_state->keyboard == 0) {
|
{
|
||||||
|
if (this->machine_state->keyboard == 0)
|
||||||
|
{
|
||||||
this->machine_state->pc -= 2;
|
this->machine_state->pc -= 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto key = 0; key < 16; key++) {
|
for (auto key = 0; key < 16; key++)
|
||||||
if (this->machine_state->keyboard & 1 << key) {
|
{
|
||||||
|
if (this->machine_state->keyboard & 1 << key)
|
||||||
|
{
|
||||||
this->machine_state->v[instruction.x] = key;
|
this->machine_state->v[instruction.x] = key;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_dt_vx(const Instruction& instruction) const {
|
void Interpreter::ld_dt_vx(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->dt = this->machine_state->v[instruction.x];
|
this->machine_state->dt = this->machine_state->v[instruction.x];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_st_vx(const Instruction& instruction) const {
|
void Interpreter::ld_st_vx(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->st = this->machine_state->v[instruction.x];
|
this->machine_state->st = this->machine_state->v[instruction.x];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::add_i_vx(const Instruction& instruction) const {
|
void Interpreter::add_i_vx(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->i += this->machine_state->v[instruction.x];
|
this->machine_state->i += this->machine_state->v[instruction.x];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld_f_vx(const Instruction& instruction) const {
|
void Interpreter::ld_f_vx(const Instruction& instruction) const
|
||||||
|
{
|
||||||
this->machine_state->i = (this->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 {
|
void Interpreter::ld_b_vx(const Instruction& instruction) const
|
||||||
|
{
|
||||||
const auto number = this->machine_state->v[instruction.x];
|
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] = 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 + 1] = (number - this->machine_state->memory[this->machine_state
|
||||||
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;
|
->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 {
|
void Interpreter::ld_i_vx(const Instruction& instruction) const
|
||||||
|
{
|
||||||
const bool use_quirk = this->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++) {
|
for (auto reg = 0; reg <= instruction.x; reg++)
|
||||||
if (use_quirk) {
|
{
|
||||||
|
if (use_quirk)
|
||||||
|
{
|
||||||
this->machine_state->memory[this->machine_state->i] = this->machine_state->v[reg];
|
this->machine_state->memory[this->machine_state->i] = this->machine_state->v[reg];
|
||||||
this->machine_state->i++;
|
this->machine_state->i++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
this->machine_state->memory[this->machine_state->i + reg] = this->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 {
|
void Interpreter::ld_vx_i(const Instruction& instruction) const
|
||||||
|
{
|
||||||
const bool use_quirk = this->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++) {
|
for (auto reg = 0; reg <= instruction.x; reg++)
|
||||||
if (use_quirk) {
|
{
|
||||||
|
if (use_quirk)
|
||||||
|
{
|
||||||
this->machine_state->v[reg] = this->machine_state->memory[this->machine_state->i];
|
this->machine_state->v[reg] = this->machine_state->memory[this->machine_state->i];
|
||||||
this->machine_state->i++;
|
this->machine_state->i++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
this->machine_state->v[reg] = this->machine_state->memory[this->machine_state->i + reg];
|
this->machine_state->v[reg] = this->machine_state->memory[this->machine_state->i + reg];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,15 @@
|
|||||||
#include "Instruction.h"
|
#include "Instruction.h"
|
||||||
#include "MachineState.h"
|
#include "MachineState.h"
|
||||||
|
|
||||||
enum class InterpreterQuirks {
|
enum class InterpreterQuirks
|
||||||
|
{
|
||||||
COSMAC_SHIFT = 1 << 0,
|
COSMAC_SHIFT = 1 << 0,
|
||||||
SUPER_CHIP_JUMP = 1 << 1,
|
SUPER_CHIP_JUMP = 1 << 1,
|
||||||
COSMAC_STORE_AND_LOAD = 1 << 2,
|
COSMAC_STORE_AND_LOAD = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Interpreter {
|
class Interpreter
|
||||||
|
{
|
||||||
std::shared_ptr<MachineState> machine_state;
|
std::shared_ptr<MachineState> machine_state;
|
||||||
std::mt19937 random_generator;
|
std::mt19937 random_generator;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MachineState.h"
|
#include "MachineState.h"
|
||||||
|
|
||||||
MachineState::MachineState():
|
MachineState::MachineState() :
|
||||||
memory{},
|
memory{},
|
||||||
v{},
|
v{},
|
||||||
stack{},
|
stack{},
|
||||||
@@ -11,9 +11,11 @@ MachineState::MachineState():
|
|||||||
i{0},
|
i{0},
|
||||||
dt{0},
|
dt{0},
|
||||||
st{0}
|
st{0}
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void MachineState::reset() {
|
void MachineState::reset()
|
||||||
|
{
|
||||||
this->memory.fill(0);
|
this->memory.fill(0);
|
||||||
this->v.fill(0);
|
this->v.fill(0);
|
||||||
this->stack.fill(0);
|
this->stack.fill(0);
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
struct MachineState {
|
struct MachineState
|
||||||
|
{
|
||||||
std::array<uint8_t, 4096> memory;
|
std::array<uint8_t, 4096> memory;
|
||||||
std::array<uint16_t, 16> v;
|
std::array<uint16_t, 16> v;
|
||||||
std::array<uint16_t, 16> stack;
|
std::array<uint16_t, 16> stack;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#ifndef OPCODE_H
|
#ifndef OPCODE_H
|
||||||
#define OPCODE_H
|
#define OPCODE_H
|
||||||
|
|
||||||
enum class OpCode {
|
enum class OpCode
|
||||||
|
{
|
||||||
CLS, // 00E0 - CLS
|
CLS, // 00E0 - CLS
|
||||||
RET, // 00EE - RET
|
RET, // 00EE - RET
|
||||||
SYS_ADDR, // 0nnn - SYS addr
|
SYS_ADDR, // 0nnn - SYS addr
|
||||||
|
|||||||
@@ -20,15 +20,16 @@ Machine::Machine() :
|
|||||||
|
|
||||||
interpreter{std::make_unique<Interpreter>(this->machine_state)},
|
interpreter{std::make_unique<Interpreter>(this->machine_state)},
|
||||||
ui_manager{std::make_unique<UIManager>(this->graphics, this->machine_state, this->callback_manager)},
|
ui_manager{std::make_unique<UIManager>(this->graphics, this->machine_state, this->callback_manager)},
|
||||||
|
|
||||||
ips{700},
|
ips{700},
|
||||||
last_update_time{0},
|
last_update_time{0},
|
||||||
accumulator{0},
|
accumulator{0},
|
||||||
target_cycle_time{1.0 / this->ips} {
|
target_cycle_time{1.0 / this->ips}
|
||||||
|
{
|
||||||
this->register_callbacks();
|
this->register_callbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::iterate() {
|
void Machine::iterate()
|
||||||
|
{
|
||||||
this->execute_interpreter();
|
this->execute_interpreter();
|
||||||
|
|
||||||
this->graphics->start();
|
this->graphics->start();
|
||||||
@@ -36,29 +37,34 @@ void Machine::iterate() {
|
|||||||
this->graphics->end();
|
this->graphics->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Machine::on_event(const SDL_Event* event) const {
|
bool Machine::on_event(const SDL_Event* event) const
|
||||||
|
{
|
||||||
ImGui_ImplSDL3_ProcessEvent(event);
|
ImGui_ImplSDL3_ProcessEvent(event);
|
||||||
|
|
||||||
if (event->type == SDL_EVENT_QUIT) {
|
if (event->type == SDL_EVENT_QUIT)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::execute_interpreter() {
|
void Machine::execute_interpreter()
|
||||||
|
{
|
||||||
const auto current_time = SDL_GetTicks();
|
const auto current_time = SDL_GetTicks();
|
||||||
const auto delta_time = static_cast<double>(current_time - this->last_update_time) / 1000.0;
|
const auto delta_time = static_cast<double>(current_time - this->last_update_time) / 1000.0;
|
||||||
this->last_update_time = current_time;
|
this->last_update_time = current_time;
|
||||||
this->accumulator += delta_time;
|
this->accumulator += delta_time;
|
||||||
|
|
||||||
while (this->accumulator >= this->target_cycle_time) {
|
while (this->accumulator >= this->target_cycle_time)
|
||||||
|
{
|
||||||
this->interpreter->tick();
|
this->interpreter->tick();
|
||||||
this->accumulator -= this->target_cycle_time;
|
this->accumulator -= this->target_cycle_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::register_callbacks() {
|
void Machine::register_callbacks()
|
||||||
|
{
|
||||||
callback_manager->set_rom_load_callback(std::bind(
|
callback_manager->set_rom_load_callback(std::bind(
|
||||||
&Machine::on_rom_load,
|
&Machine::on_rom_load,
|
||||||
this,
|
this,
|
||||||
@@ -70,7 +76,8 @@ void Machine::register_callbacks() {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::on_rom_load(const std::string& path) const {
|
void Machine::on_rom_load(const std::string& path) const
|
||||||
|
{
|
||||||
std::ifstream file(path, std::ios::binary);
|
std::ifstream file(path, std::ios::binary);
|
||||||
file.unsetf(std::ios::skipws);
|
file.unsetf(std::ios::skipws);
|
||||||
|
|
||||||
@@ -80,7 +87,8 @@ void Machine::on_rom_load(const std::string& path) const {
|
|||||||
|
|
||||||
// La memoria para los rom es desde 0x200 hasta el final de 0x1000
|
// La memoria para los rom es desde 0x200 hasta el final de 0x1000
|
||||||
// Por lo que un rom sería muy grande si sobrepasa este tamaño
|
// Por lo que un rom sería muy grande si sobrepasa este tamaño
|
||||||
if (file_size >= 0x1000 - 0x200 ) {
|
if (file_size >= 0x1000 - 0x200)
|
||||||
|
{
|
||||||
std::cout << "File too large!" << std::endl;
|
std::cout << "File too large!" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,6 +103,7 @@ void Machine::on_rom_load(const std::string& path) const {
|
|||||||
std::cout << "Cargado rom: " << path << std::endl;
|
std::cout << "Cargado rom: " << path << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::on_reset() const {
|
void Machine::on_reset() const
|
||||||
|
{
|
||||||
this->machine_state->reset();
|
this->machine_state->reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
#include "UI/Display.h"
|
#include "UI/Display.h"
|
||||||
#include "UI/UIManager.h"
|
#include "UI/UIManager.h"
|
||||||
|
|
||||||
class Machine {
|
class Machine
|
||||||
|
{
|
||||||
std::shared_ptr<MachineState> machine_state;
|
std::shared_ptr<MachineState> machine_state;
|
||||||
std::shared_ptr<Graphics> graphics;
|
std::shared_ptr<Graphics> graphics;
|
||||||
std::shared_ptr<CallbackManager> callback_manager;
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
|
|||||||
@@ -1,19 +1,27 @@
|
|||||||
#include "CallbackManager.h"
|
#include "CallbackManager.h"
|
||||||
|
|
||||||
void CallbackManager::set_rom_load_callback(const RomLoadCallback& callback) {
|
void CallbackManager::set_rom_load_callback(const RomLoadCallback& callback)
|
||||||
|
{
|
||||||
this->rom_load_callback = callback;
|
this->rom_load_callback = callback;
|
||||||
}
|
}
|
||||||
void CallbackManager::set_reset_callback(const ResetCallback& callback) {
|
|
||||||
|
void CallbackManager::set_reset_callback(const ResetCallback& callback)
|
||||||
|
{
|
||||||
this->reset_callback = callback;
|
this->reset_callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallbackManager::trigger_rom_load(const std::string& path) {
|
void CallbackManager::trigger_rom_load(const std::string& path)
|
||||||
if (this->rom_load_callback) {
|
{
|
||||||
|
if (this->rom_load_callback)
|
||||||
|
{
|
||||||
this->rom_load_callback(path);
|
this->rom_load_callback(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void CallbackManager::trigger_reset() {
|
|
||||||
if (this->reset_callback) {
|
void CallbackManager::trigger_reset()
|
||||||
|
{
|
||||||
|
if (this->reset_callback)
|
||||||
|
{
|
||||||
this->reset_callback();
|
this->reset_callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
struct CallbackManager {
|
struct CallbackManager
|
||||||
using RomLoadCallback = std::function<void(const std::string&)>;
|
{
|
||||||
|
using RomLoadCallback = std::function<void(const std::string &)>;
|
||||||
using ResetCallback = std::function<void()>;
|
using ResetCallback = std::function<void()>;
|
||||||
|
|
||||||
void set_rom_load_callback(const RomLoadCallback& callback);
|
void set_rom_load_callback(const RomLoadCallback& callback);
|
||||||
|
|||||||
@@ -12,17 +12,23 @@ ControlPanel::ControlPanel(
|
|||||||
std::shared_ptr<CallbackManager> callback_manager
|
std::shared_ptr<CallbackManager> callback_manager
|
||||||
) : graphics{std::move(graphics)},
|
) : graphics{std::move(graphics)},
|
||||||
machine_state{std::move(machine_state)},
|
machine_state{std::move(machine_state)},
|
||||||
callback_manager{std::move(callback_manager)} {}
|
callback_manager{std::move(callback_manager)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ControlPanel::render() {
|
void ControlPanel::render()
|
||||||
|
{
|
||||||
constexpr auto full_width = ImVec2(-FLT_MIN, 0.0f);
|
constexpr auto full_width = ImVec2(-FLT_MIN, 0.0f);
|
||||||
|
|
||||||
if (ImGui::Begin("Chip-8 - Controls")) {
|
if (ImGui::Begin("Chip-8 - Controls"))
|
||||||
if (ImGui::Button("Load Rom", full_width)) {
|
{
|
||||||
|
if (ImGui::Button("Load Rom", full_width))
|
||||||
|
{
|
||||||
this->on_click_load_rom();
|
this->on_click_load_rom();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button(run ? "Pause" : "Run", full_width)) {
|
if (ImGui::Button(run ? "Pause" : "Run", full_width))
|
||||||
|
{
|
||||||
this->run = !run;
|
this->run = !run;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +51,8 @@ void ControlPanel::render() {
|
|||||||
|
|
||||||
ImGui::SeparatorText("");
|
ImGui::SeparatorText("");
|
||||||
|
|
||||||
if (ImGui::Button("Reset", full_width)) {
|
if (ImGui::Button("Reset", full_width))
|
||||||
|
{
|
||||||
this->callback_manager->trigger_reset();
|
this->callback_manager->trigger_reset();
|
||||||
}
|
}
|
||||||
ImGui::Button("Reload ROM", full_width);
|
ImGui::Button("Reload ROM", full_width);
|
||||||
@@ -54,7 +61,8 @@ void ControlPanel::render() {
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlPanel::on_click_load_rom() {
|
void ControlPanel::on_click_load_rom()
|
||||||
|
{
|
||||||
constexpr SDL_DialogFileFilter filters[] = {
|
constexpr SDL_DialogFileFilter filters[] = {
|
||||||
{"CHIP8 ROMs", "ch8"},
|
{"CHIP8 ROMs", "ch8"},
|
||||||
{"All files", "*"}
|
{"All files", "*"}
|
||||||
@@ -71,10 +79,12 @@ void ControlPanel::on_click_load_rom() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlPanel::on_callback_load_rom(void* self, const char* const* filelist, int filter) {
|
void ControlPanel::on_callback_load_rom(void* self, const char* const* filelist, int filter)
|
||||||
|
{
|
||||||
const auto control_panel = static_cast<ControlPanel*>(self);
|
const auto control_panel = static_cast<ControlPanel*>(self);
|
||||||
|
|
||||||
if (!filelist || !*filelist) {
|
if (!filelist || !*filelist)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
#include "../Interpreter/MachineState.h"
|
#include "../Interpreter/MachineState.h"
|
||||||
|
|
||||||
|
|
||||||
class ControlPanel {
|
class ControlPanel
|
||||||
|
{
|
||||||
std::shared_ptr<Graphics> graphics;
|
std::shared_ptr<Graphics> graphics;
|
||||||
std::shared_ptr<MachineState> machine_state;
|
std::shared_ptr<MachineState> machine_state;
|
||||||
std::shared_ptr<CallbackManager> callback_manager;
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
|
|||||||
@@ -8,23 +8,29 @@
|
|||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "SDL3/SDL.h"
|
#include "SDL3/SDL.h"
|
||||||
|
|
||||||
void SDLTextureDestroyer::operator()(SDL_Texture* texture) const {
|
void SDLTextureDestroyer::operator()(SDL_Texture* texture) const
|
||||||
|
{
|
||||||
SDL_DestroyTexture(texture);
|
SDL_DestroyTexture(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
Display::Display(std::shared_ptr<Graphics> graphics, std::shared_ptr<MachineState> machine_state):
|
Display::Display(std::shared_ptr<Graphics> graphics, std::shared_ptr<MachineState> machine_state) :
|
||||||
graphics{std::move(graphics)},
|
graphics{std::move(graphics)},
|
||||||
machine_state{std::move(machine_state)},
|
machine_state{std::move(machine_state)},
|
||||||
width(64),
|
width(64),
|
||||||
height(32),
|
height(32),
|
||||||
background_color{0x00, 0x2b, 0x59},
|
background_color{0x00, 0x2b, 0x59},
|
||||||
foreground_color(0x00, 0xb9, 0xbe),
|
foreground_color(0x00, 0xb9, 0xbe),
|
||||||
texture{create_texture()} {}
|
texture{create_texture()}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<SDL_Texture, SDLTextureDestroyer> Display::create_texture() const {
|
std::unique_ptr<SDL_Texture, SDLTextureDestroyer> Display::create_texture() const
|
||||||
SDL_Texture* raw_texture = SDL_CreateTexture(this->graphics->get_renderer().get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
{
|
||||||
|
SDL_Texture* raw_texture = SDL_CreateTexture(this->graphics->get_renderer().get(), SDL_PIXELFORMAT_RGBA8888,
|
||||||
|
SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||||
|
|
||||||
if (!raw_texture) {
|
if (!raw_texture)
|
||||||
|
{
|
||||||
throw std::runtime_error(std::format("Couldn't create texture: {}", SDL_GetError()));
|
throw std::runtime_error(std::format("Couldn't create texture: {}", SDL_GetError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,16 +39,19 @@ std::unique_ptr<SDL_Texture, SDLTextureDestroyer> Display::create_texture() cons
|
|||||||
return std::unique_ptr<SDL_Texture, SDLTextureDestroyer>(raw_texture);
|
return std::unique_ptr<SDL_Texture, SDLTextureDestroyer>(raw_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::render() const {
|
void Display::render() const
|
||||||
|
{
|
||||||
update_texture();
|
update_texture();
|
||||||
display_widget();
|
display_widget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::update_texture() const {
|
void Display::update_texture() const
|
||||||
|
{
|
||||||
SDL_Surface* surface = nullptr;
|
SDL_Surface* surface = nullptr;
|
||||||
const auto& display = machine_state->display;
|
const auto& display = machine_state->display;
|
||||||
|
|
||||||
if (SDL_LockTextureToSurface(this->texture.get(), nullptr, &surface)) {
|
if (SDL_LockTextureToSurface(this->texture.get(), nullptr, &surface))
|
||||||
|
{
|
||||||
SDL_FillSurfaceRect(
|
SDL_FillSurfaceRect(
|
||||||
surface,
|
surface,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -55,8 +64,10 @@ void Display::update_texture() const {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
for (int i = 0; i < display.size(); i++) {
|
for (int i = 0; i < display.size(); i++)
|
||||||
if (display[i]) {
|
{
|
||||||
|
if (display[i])
|
||||||
|
{
|
||||||
const int x = (i % this->width);
|
const int x = (i % this->width);
|
||||||
const int y = (i / this->width);
|
const int y = (i / this->width);
|
||||||
|
|
||||||
@@ -73,12 +84,15 @@ void Display::update_texture() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SDL_UnlockTexture(this->texture.get());
|
SDL_UnlockTexture(this->texture.get());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
throw std::runtime_error(std::format("Couldn't get texture lock onto surface: {}", SDL_GetError()));
|
throw std::runtime_error(std::format("Couldn't get texture lock onto surface: {}", SDL_GetError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::display_widget() const {
|
void Display::display_widget() const
|
||||||
|
{
|
||||||
ImGui::Begin("CHIP-8 - Display");
|
ImGui::Begin("CHIP-8 - Display");
|
||||||
|
|
||||||
const ImVec2 available_size = ImGui::GetContentRegionAvail();
|
const ImVec2 available_size = ImGui::GetContentRegionAvail();
|
||||||
|
|||||||
@@ -7,11 +7,13 @@
|
|||||||
#include "../Interpreter/MachineState.h"
|
#include "../Interpreter/MachineState.h"
|
||||||
#include "SDL3/SDL.h"
|
#include "SDL3/SDL.h"
|
||||||
|
|
||||||
struct SDLTextureDestroyer {
|
struct SDLTextureDestroyer
|
||||||
|
{
|
||||||
void operator()(SDL_Texture* texture) const;
|
void operator()(SDL_Texture* texture) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Display {
|
class Display
|
||||||
|
{
|
||||||
std::shared_ptr<Graphics> graphics;
|
std::shared_ptr<Graphics> graphics;
|
||||||
std::shared_ptr<MachineState> machine_state;
|
std::shared_ptr<MachineState> machine_state;
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ UIManager::UIManager(
|
|||||||
machine_state{std::move(machine_state)},
|
machine_state{std::move(machine_state)},
|
||||||
callback_manager{std::move(callback_manager)},
|
callback_manager{std::move(callback_manager)},
|
||||||
display{std::make_unique<Display>(this->graphics, this->machine_state)},
|
display{std::make_unique<Display>(this->graphics, this->machine_state)},
|
||||||
control_panel{std::make_unique<ControlPanel>(this->graphics, this->machine_state, this->callback_manager)} {}
|
control_panel{std::make_unique<ControlPanel>(this->graphics, this->machine_state, this->callback_manager)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void UIManager::render() {
|
void UIManager::render()
|
||||||
|
{
|
||||||
this->display->render();
|
this->display->render();
|
||||||
this->control_panel->render();
|
this->control_panel->render();
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,8 @@
|
|||||||
#include "Display.h"
|
#include "Display.h"
|
||||||
#include "../Graphics/Graphics.h"
|
#include "../Graphics/Graphics.h"
|
||||||
|
|
||||||
class UIManager {
|
class UIManager
|
||||||
|
{
|
||||||
std::shared_ptr<Graphics> graphics;
|
std::shared_ptr<Graphics> graphics;
|
||||||
std::shared_ptr<MachineState> machine_state;
|
std::shared_ptr<MachineState> machine_state;
|
||||||
std::shared_ptr<CallbackManager> callback_manager;
|
std::shared_ptr<CallbackManager> callback_manager;
|
||||||
@@ -22,7 +23,7 @@ public:
|
|||||||
std::shared_ptr<CallbackManager> callback_manager
|
std::shared_ptr<CallbackManager> callback_manager
|
||||||
);
|
);
|
||||||
|
|
||||||
void render() ;
|
void render();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //UIMANAGER_H
|
#endif //UIMANAGER_H
|
||||||
15
src/main.cpp
15
src/main.cpp
@@ -4,14 +4,16 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Machine.h"
|
#include "Machine.h"
|
||||||
|
|
||||||
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[])
|
||||||
|
{
|
||||||
auto machine = std::make_unique<Machine>();
|
auto machine = std::make_unique<Machine>();
|
||||||
*appstate = machine.release();
|
*appstate = machine.release();
|
||||||
|
|
||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_AppResult SDL_AppIterate(void* appstate) {
|
SDL_AppResult SDL_AppIterate(void* appstate)
|
||||||
|
{
|
||||||
const auto machine = static_cast<Machine*>(appstate);
|
const auto machine = static_cast<Machine*>(appstate);
|
||||||
|
|
||||||
machine->iterate();
|
machine->iterate();
|
||||||
@@ -19,16 +21,19 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
|||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
|
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
||||||
|
{
|
||||||
const auto machine = static_cast<Machine*>(appstate);
|
const auto machine = static_cast<Machine*>(appstate);
|
||||||
|
|
||||||
if (!machine->on_event(event)) {
|
if (!machine->on_event(event))
|
||||||
|
{
|
||||||
return SDL_APP_SUCCESS;
|
return SDL_APP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_AppQuit(void* appstate, SDL_AppResult result) {
|
void SDL_AppQuit(void* appstate, SDL_AppResult result)
|
||||||
|
{
|
||||||
std::unique_ptr<Machine> chip8(static_cast<Machine*>(appstate));
|
std::unique_ptr<Machine> chip8(static_cast<Machine*>(appstate));
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user