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

2
.gitignore vendored
View File

@@ -13,4 +13,4 @@ _deps
CMakeUserPresets.json CMakeUserPresets.json
cmake-build-debug cmake-build-debug
imgui.ini imgui.ini
cmake-build*/

8
.idea/dictionaries/project.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<component name="ProjectDictionaryState">
<dictionary name="project">
<words>
<w>cosmac</w>
<w>skrd</w>
</words>
</dictionary>
</component>

2
.idea/editor.xml generated
View File

@@ -112,7 +112,7 @@
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />

View File

@@ -0,0 +1,9 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ClangTidy" enabled="true" level="WARNING" enabled_by_default="true">
<option name="clangTidyChecks" value="-*,bugprone-argument-comment,bugprone-assert-side-effect,bugprone-bad-signal-to-kill-thread,bugprone-branch-clone,bugprone-copy-constructor-init,bugprone-dangling-handle,bugprone-dynamic-static-initializers,bugprone-fold-init-type,bugprone-forward-declaration-namespace,bugprone-forwarding-reference-overload,bugprone-inaccurate-erase,bugprone-incorrect-roundings,bugprone-integer-division,bugprone-lambda-function-name,bugprone-macro-parentheses,bugprone-macro-repeated-side-effects,bugprone-misplaced-operator-in-strlen-in-alloc,bugprone-misplaced-pointer-arithmetic-in-alloc,bugprone-misplaced-widening-cast,bugprone-move-forwarding-reference,bugprone-multiple-statement-macro,bugprone-no-escape,bugprone-parent-virtual-call,bugprone-posix-return,bugprone-reserved-identifier,bugprone-sizeof-container,bugprone-sizeof-expression,bugprone-spuriously-wake-up-functions,bugprone-string-constructor,bugprone-string-integer-assignment,bugprone-string-literal-with-embedded-nul,bugprone-suspicious-enum-usage,bugprone-suspicious-include,bugprone-suspicious-memset-usage,bugprone-suspicious-missing-comma,bugprone-suspicious-semicolon,bugprone-suspicious-string-compare,bugprone-suspicious-memory-comparison,bugprone-suspicious-realloc-usage,bugprone-swapped-arguments,bugprone-terminating-continue,bugprone-throw-keyword-missing,bugprone-too-small-loop-variable,bugprone-undefined-memory-manipulation,bugprone-undelegated-constructor,bugprone-unhandled-self-assignment,bugprone-unused-raii,bugprone-unused-return-value,bugprone-use-after-move,bugprone-virtual-near-miss,cert-dcl21-cpp,cert-dcl58-cpp,cert-err34-c,cert-err52-cpp,cert-err60-cpp,cert-flp30-c,cert-msc50-cpp,cert-msc51-cpp,cert-str34-c,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-narrowing-conversions,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-pro-type-static-cast-downcast,cppcoreguidelines-slicing,google-default-arguments,google-explicit-constructor,google-runtime-operator,hicpp-exception-baseclass,hicpp-multiway-paths-covered,misc-misplaced-const,misc-new-delete-overloads,misc-no-recursion,misc-non-copyable-objects,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,misc-uniqueptr-reset-release,modernize-avoid-bind,modernize-concat-nested-namespaces,modernize-deprecated-headers,modernize-deprecated-ios-base-aliases,modernize-loop-convert,modernize-make-shared,modernize-make-unique,modernize-pass-by-value,modernize-raw-string-literal,modernize-redundant-void-arg,modernize-replace-auto-ptr,modernize-replace-disallow-copy-and-assign-macro,modernize-replace-random-shuffle,modernize-return-braced-init-list,modernize-shrink-to-fit,modernize-unary-static-assert,modernize-use-auto,modernize-use-bool-literals,modernize-use-emplace,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-nodiscard,modernize-use-noexcept,modernize-use-nullptr,modernize-use-override,modernize-use-transparent-functors,modernize-use-uncaught-exceptions,mpi-buffer-deref,mpi-type-mismatch,openmp-use-default-none,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-string-concatenation,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-trivially-destructible,performance-type-promotion-in-math-fn,performance-unnecessary-copy-initialization,performance-unnecessary-value-param,portability-simd-intrinsics,readability-avoid-const-params-in-decls,readability-const-return-type,readability-container-size-empty,readability-delete-null-pointer,readability-deleted-default,readability-inconsistent-declaration-parameter-name,readability-make-member-function-const,readability-misleading-indentation,readability-misplaced-array-index,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-use-anyofallof" />
</inspection_tool>
<inspection_tool class="CppMemberFunctionMayBeStatic" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
</profile>
</component>

1
.idea/misc.xml generated
View File

@@ -13,4 +13,5 @@
<file path="$PROJECT_DIR$/src/old" /> <file path="$PROJECT_DIR$/src/old" />
</excludeRoots> </excludeRoots>
</component> </component>
<component name="WestSettings"><![CDATA[{}]]></component>
</project> </project>

View File

@@ -1,5 +1,6 @@
#include "Chip8Display.h" #include "Chip8Display.h"
#include <format>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <vector> #include <vector>
@@ -12,15 +13,21 @@ void SDLTextureDestroyer::operator()(SDL_Texture* texture) const {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
} }
Chip8Display::Chip8Display(std::shared_ptr<MachineState> machine_state, SDL_Renderer& renderer): Chip8Display::Chip8Display(std::shared_ptr<MachineState> machine_state, std::shared_ptr<SDL_Renderer> renderer):
machine_state{std::move(machine_state)}, machine_state{std::move(machine_state)},
renderer{renderer}, renderer{std::move(renderer)},
width(64), width(64),
height(32) { height(32),
background_color{0x00, 0x2b, 0x59},
foreground_color(0x00, 0xb9, 0xbe) {
SDL_Texture* raw_texture = SDL_CreateTexture(this->renderer.get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!raw_texture) {
throw std::runtime_error(std::format("Couldn't create texture: {}", SDL_GetError()));
}
SDL_Texture* raw_texture = SDL_CreateTexture(&renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
this->texture = std::unique_ptr<SDL_Texture, SDLTextureDestroyer>(raw_texture); this->texture = std::unique_ptr<SDL_Texture, SDLTextureDestroyer>(raw_texture);
SDL_SetTextureScaleMode(texture.get(), SDL_SCALEMODE_LINEAR); SDL_SetTextureScaleMode(this->texture.get(), SDL_SCALEMODE_NEAREST);
} }
void Chip8Display::render() const { void Chip8Display::render() const {
@@ -28,36 +35,45 @@ void Chip8Display::render() const {
display_widget(); display_widget();
} }
void Chip8Display::update() const { void Chip8Display::update() const {}
}
void Chip8Display::update_texture() const { void Chip8Display::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(texture.get(), nullptr, &surface)) { if (SDL_LockTextureToSurface(this->texture.get(), nullptr, &surface)) {
SDL_FillSurfaceRect(surface, nullptr, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), nullptr, 0, 0, 0)); SDL_FillSurfaceRect(
surface,
nullptr,
SDL_MapRGB(
SDL_GetPixelFormatDetails(surface->format),
nullptr,
this->background_color.r,
this->background_color.g,
this->background_color.b
)
);
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 % width); const int x = (i % this->width);
const int y = (i / width); const int y = (i / this->width);
SDL_Rect rect = {x, y, 1, 1}; SDL_Rect rect = {x, y, 1, 1};
Uint32 color = SDL_MapRGB( const Uint32 color = SDL_MapRGB(
SDL_GetPixelFormatDetails(surface->format), SDL_GetPixelFormatDetails(surface->format),
nullptr, nullptr,
0, this->foreground_color.r,
255, this->foreground_color.g,
0 this->foreground_color.b
); );
SDL_FillSurfaceRect(surface, &rect, color); SDL_FillSurfaceRect(surface, &rect, color);
} }
} }
SDL_UnlockTexture(texture.get()); SDL_UnlockTexture(this->texture.get());
} else { } else {
SDL_Log("Failed to lock texture: %s", SDL_GetError()); throw std::runtime_error(std::format("Couldn't get texture lock onto surface: {}", SDL_GetError()));
} }
} }
@@ -66,15 +82,15 @@ void Chip8Display::display_widget() const {
const ImVec2 available_size = ImGui::GetContentRegionAvail(); const ImVec2 available_size = ImGui::GetContentRegionAvail();
const int scale_x = static_cast<int>(static_cast<float>(available_size.x) / static_cast<float>(width)); const int scale_x = static_cast<int>(static_cast<float>(available_size.x) / static_cast<float>(this->width));
const int scale_y = static_cast<int>(static_cast<float>(available_size.y) / static_cast<float>(height)); const int scale_y = static_cast<int>(static_cast<float>(available_size.y) / static_cast<float>(this->height));
const int scale = std::max(1, std::min(scale_x, scale_y)); const int scale = std::max(1, std::min(scale_x, scale_y));
const ImVec2 scaled_size(static_cast<float>(width * scale), static_cast<float>(height * scale)); const ImVec2 scaled_size(static_cast<float>(this->width * scale), static_cast<float>(this->height * scale));
const ImVec2 cursor_pos = ImGui::GetCursorPos(); const ImVec2 cursor_pos = ImGui::GetCursorPos();
const ImVec2 center_offset((available_size.x - scaled_size.x) / 2, (available_size.y - scaled_size.y) / 2); const ImVec2 center_offset((available_size.x - scaled_size.x) / 2, (available_size.y - scaled_size.y) / 2);
ImGui::SetCursorPos(ImVec2(cursor_pos.x + center_offset.x, cursor_pos.y + center_offset.y)); ImGui::SetCursorPos(ImVec2(cursor_pos.x + center_offset.x, cursor_pos.y + center_offset.y));
ImGui::Image((ImTextureID)((intptr_t)texture.get()), scaled_size); ImGui::Image(static_cast<ImTextureID>(reinterpret_cast<intptr_t>(texture.get())), scaled_size);
ImGui::End(); ImGui::End();
} }

View File

@@ -2,6 +2,7 @@
#define CHIP8DISPLAY_H #define CHIP8DISPLAY_H
#include <memory> #include <memory>
#include "Color.h"
#include "../Interpreter/MachineState.h" #include "../Interpreter/MachineState.h"
#include "SDL3/SDL.h" #include "SDL3/SDL.h"
@@ -11,11 +12,14 @@ struct SDLTextureDestroyer {
class Chip8Display { class Chip8Display {
std::shared_ptr<MachineState> machine_state; std::shared_ptr<MachineState> machine_state;
SDL_Renderer& renderer; std::shared_ptr<SDL_Renderer> renderer;
int width; int width;
int height; int height;
Color background_color;
Color foreground_color;
std::unique_ptr<SDL_Texture, SDLTextureDestroyer> texture; std::unique_ptr<SDL_Texture, SDLTextureDestroyer> texture;
void update_texture() const; void update_texture() const;
@@ -24,7 +28,7 @@ class Chip8Display {
public: public:
Chip8Display( Chip8Display(
std::shared_ptr<MachineState> machine_state, std::shared_ptr<MachineState> machine_state,
SDL_Renderer& renderer std::shared_ptr<SDL_Renderer> renderer
); );
void update() const; void update() const;

13
src/Graphics/Color.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef COLOR_H
#define COLOR_H
#include <cstdint>
struct Color {
uint8_t r;
uint8_t g;
uint8_t b;
Color(const uint8_t r, const uint8_t g, const uint8_t b) : r(r), g(g), b(b) {}
};
#endif //COLOR_H

View File

@@ -1,6 +1,8 @@
#include "Graphics.h" #include "Graphics.h"
#include <cmath>
#include <format> #include <format>
#include <iostream>
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_sdl3.h" #include "imgui_impl_sdl3.h"
@@ -10,11 +12,7 @@ void SDLWindowDestroyer::operator()(SDL_Window* window) const {
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
} }
void SDLRendererDestroyer::operator()(SDL_Renderer* renderer) const { Graphics::Graphics(): window_width{1366}, window_height{768}, main_scale{1.0f} {
SDL_DestroyRenderer(renderer);
}
Graphics::Graphics(): window_width{1920}, window_height{1080}, main_scale{1.0f} {
create_sdl(); create_sdl();
create_imgui(); create_imgui();
} }
@@ -29,13 +27,13 @@ void Graphics::create_sdl() {
SDL_Window* raw_window = nullptr; SDL_Window* raw_window = nullptr;
SDL_Renderer* raw_renderer = nullptr; SDL_Renderer* raw_renderer = nullptr;
main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); this->main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; constexpr SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
if (!SDL_CreateWindowAndRenderer( if (!SDL_CreateWindowAndRenderer(
"CHIP-8 Emulator", "CHIP-8 Emulator",
window_width * main_scale, std::floor(static_cast<float>(this->window_width) * main_scale),
window_height * main_scale, std::floor(static_cast<float>(this->window_height) * main_scale),
window_flags, window_flags,
&raw_window, &raw_window,
&raw_renderer &raw_renderer
@@ -43,15 +41,15 @@ void Graphics::create_sdl() {
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()));
} }
window = std::unique_ptr<SDL_Window, SDLWindowDestroyer>(raw_window); this->window = std::unique_ptr<SDL_Window, SDLWindowDestroyer>(raw_window);
renderer = std::unique_ptr<SDL_Renderer, SDLRendererDestroyer>(raw_renderer); this->renderer = std::shared_ptr<SDL_Renderer>(raw_renderer, SDL_DestroyRenderer);
SDL_SetRenderVSync(renderer.get(), 1); SDL_SetRenderVSync(this->renderer.get(), 1);
SDL_SetWindowPosition(window.get(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_SetWindowPosition(this->window.get(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window.get()); SDL_ShowWindow(this->window.get());
} }
void Graphics::create_imgui() { void Graphics::create_imgui() const {
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
@@ -61,37 +59,32 @@ void Graphics::create_imgui() {
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle(); ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); style.ScaleAllSizes(this->main_scale);
style.FontScaleDpi = main_scale; style.FontScaleDpi = this->main_scale;
ImGui_ImplSDL3_InitForSDLRenderer(window.get(), renderer.get()); ImGui_ImplSDL3_InitForSDLRenderer(this->window.get(), this->renderer.get());
ImGui_ImplSDLRenderer3_Init(renderer.get()); ImGui_ImplSDLRenderer3_Init(this->renderer.get());
} }
SDL_Renderer& Graphics::get_renderer() { std::shared_ptr<SDL_Renderer> Graphics::get_renderer() {
return *renderer; return this->renderer;
} }
void Graphics::start_render() const {
void Graphics::start_render() {
if (SDL_GetWindowFlags(window.get()) & SDL_WINDOW_MINIMIZED) {
SDL_Delay(10);
}
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_render() { void Graphics::end_render() const {
ImGuiIO& io = ImGui::GetIO(); const ImGuiIO& io = ImGui::GetIO();
ImGui::Render(); ImGui::Render();
SDL_SetRenderScale(renderer.get(), io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); SDL_SetRenderScale(this->renderer.get(), io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(renderer.get(), 0, 0, 0, 0xFF); SDL_SetRenderDrawColor(this->renderer.get(), 0, 0, 0, 0xFF);
SDL_RenderClear(renderer.get()); SDL_RenderClear(this->renderer.get());
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer.get()); ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), this->renderer.get());
SDL_RenderPresent(renderer.get()); SDL_RenderPresent(this->renderer.get());
} }

View File

@@ -2,34 +2,28 @@
#define GRAPHICS_H #define GRAPHICS_H
#include <memory> #include <memory>
#include "Chip8Display.h"
#include "SDL3/SDL.h" #include "SDL3/SDL.h"
struct SDLWindowDestroyer { struct SDLWindowDestroyer {
void operator()(SDL_Window* window) const; void operator()(SDL_Window* window) const;
}; };
struct SDLRendererDestroyer {
void operator()(SDL_Renderer* renderer) const;
};
class Graphics { class Graphics {
int window_width; int window_width;
int window_height; int window_height;
float main_scale; float main_scale;
std::unique_ptr<SDL_Window, SDLWindowDestroyer> window; std::unique_ptr<SDL_Window, SDLWindowDestroyer> window;
std::unique_ptr<SDL_Renderer, SDLRendererDestroyer> renderer; std::shared_ptr<SDL_Renderer> renderer;
void create_sdl(); void create_sdl();
void create_imgui(); void create_imgui() const;
public: public:
Graphics(); Graphics();
void start_render(); void start_render() const;
void end_render(); void end_render() const;
SDL_Renderer& get_renderer(); std::shared_ptr<SDL_Renderer> get_renderer();
}; };
#endif //GRAPHICS_H #endif //GRAPHICS_H

View File

@@ -5,24 +5,29 @@
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));
void Interpreter::tick() { for (bool& display : this->machine_state->display) {
const uint8_t high_word = machine_state->memory[machine_state->pc]; display = rand() % 100 > 50;
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;
} }
} }
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 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;
@@ -125,118 +130,117 @@ Instruction Interpreter::decode(const uint16_t word) {
} }
void Interpreter::execute_instruction(const Instruction& instruction) { void Interpreter::execute_instruction(const Instruction& instruction) {
if (instruction.op_code == OpCode::CLS) cls(); if (instruction.op_code == OpCode::CLS) this->cls();
else if (instruction.op_code == OpCode::RET) ret(); else if (instruction.op_code == OpCode::RET) this->ret();
else if (instruction.op_code == OpCode::SYS_ADDR) sys_addr(); else if (instruction.op_code == OpCode::SYS_ADDR) this->sys_addr();
else if (instruction.op_code == OpCode::JP_ADDR) jp_addr(instruction); else if (instruction.op_code == OpCode::JP_ADDR) this->jp_addr(instruction);
else if (instruction.op_code == OpCode::CALL_ADDR) call_addr(instruction); else if (instruction.op_code == OpCode::CALL_ADDR) this->call_addr(instruction);
else if (instruction.op_code == OpCode::SE_VX_BYTE) se_vx_byte(instruction); else if (instruction.op_code == OpCode::SE_VX_BYTE) this->se_vx_byte(instruction);
else if (instruction.op_code == OpCode::SNE_VX_BYTE) sne_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) se_vx_vy(instruction); else if (instruction.op_code == OpCode::SE_VX_VY) this->se_vx_vy(instruction);
else if (instruction.op_code == OpCode::LD_VX_BYTE) ld_vx_byte(instruction); else if (instruction.op_code == OpCode::LD_VX_BYTE) this->ld_vx_byte(instruction);
else if (instruction.op_code == OpCode::ADD_VX_BYTE) add_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) ld_vx_vy(instruction); else if (instruction.op_code == OpCode::LD_VX_VY) this->ld_vx_vy(instruction);
else if (instruction.op_code == OpCode::OR_VX_VY) or_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) and_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) xor_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) add_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) sub_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) shr_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) subn_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) shl_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) sne_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) ld_i_addr(instruction); else if (instruction.op_code == OpCode::LD_I_ADDR) this->ld_i_addr(instruction);
else if (instruction.op_code == OpCode::JP_V0_ADDR) jp_v0_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) rnd_vx_byte(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) drw_vx_vy_nibble(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) skp_vx(instruction); else if (instruction.op_code == OpCode::SKP_VX) this->skp_vx(instruction);
else if (instruction.op_code == OpCode::SKNP_VX) sknp_vx(instruction); else if (instruction.op_code == OpCode::SKNP_VX) this->sknp_vx(instruction);
else if (instruction.op_code == OpCode::LD_VX_DT) ld_vx_dt(instruction); else if (instruction.op_code == OpCode::LD_VX_DT) this->ld_vx_dt(instruction);
else if (instruction.op_code == OpCode::LD_VX_K) ld_vx_k(instruction); else if (instruction.op_code == OpCode::LD_VX_K) this->ld_vx_k(instruction);
else if (instruction.op_code == OpCode::LD_DT_VX) ld_dt_vx(instruction); else if (instruction.op_code == OpCode::LD_DT_VX) this->ld_dt_vx(instruction);
else if (instruction.op_code == OpCode::LD_ST_VX) ld_st_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) add_i_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) ld_f_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) ld_b_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) ld_i_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) ld_vx_i(instruction); else if (instruction.op_code == OpCode::LD_VX_I) this->ld_vx_i(instruction);
else if (instruction.op_code == OpCode::NOP) nop(); else if (instruction.op_code == OpCode::NOP) this->nop();
} }
void Interpreter::sys_addr() const {
void Interpreter::sys_addr() {
// NOP // NOP
} }
void Interpreter::nop() { void Interpreter::nop() const {
// NOP // NOP
} }
void Interpreter::cls() const { void Interpreter::cls() const {
machine_state->display.fill(false); this->machine_state->display.fill(false);
} }
void Interpreter::ret() const { void Interpreter::ret() const {
machine_state->sp -= 1; this->machine_state->sp -= 1;
machine_state->pc = machine_state->stack[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 {
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 {
machine_state->stack[machine_state->sp] = machine_state->pc; this->machine_state->stack[this->machine_state->sp] = this->machine_state->pc;
machine_state->sp += 1; this->machine_state->sp += 1;
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 (machine_state->v[instruction.x] == instruction.kk) { if (this->machine_state->v[instruction.x] == instruction.kk) {
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 (machine_state->v[instruction.x] != instruction.kk) { if (this->machine_state->v[instruction.x] != instruction.kk) {
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 (machine_state->v[instruction.x] == machine_state->v[instruction.y]) { if (this->machine_state->v[instruction.x] == this->machine_state->v[instruction.y]) {
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 {
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 {
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 {
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 { 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 { 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 { 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 { void Interpreter::add_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x]; auto& vx = this->machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y]; const auto& vy = this->machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF]; auto& vf = this->machine_state->v[0xF];
if (vx + vy > 0xFF) { if (vx + vy > 0xFF) {
vf = 1; vf = 1;
@@ -248,9 +252,9 @@ void Interpreter::add_vx_vy(const Instruction& instruction) const {
} }
void Interpreter::sub_vx_vy(const Instruction& instruction) const { void Interpreter::sub_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x]; auto& vx = this->machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y]; const auto& vy = this->machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF]; auto& vf = this->machine_state->v[0xF];
if (vx > vy) { if (vx > vy) {
vf = 1; vf = 1;
@@ -262,9 +266,9 @@ void Interpreter::sub_vx_vy(const Instruction& instruction) const {
} }
void Interpreter::shr_vx_vy(const Instruction& instruction) const { void Interpreter::shr_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x]; auto& vx = this->machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y]; const auto& vy = this->machine_state->v[instruction.y];
auto& vf = 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;
@@ -280,9 +284,9 @@ void Interpreter::shr_vx_vy(const Instruction& instruction) const {
} }
void Interpreter::subn_vx_vy(const Instruction& instruction) const { void Interpreter::subn_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x]; auto& vx = this->machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y]; const auto& vy = this->machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF]; auto& vf = this->machine_state->v[0xF];
if (vy > vx) { if (vy > vx) {
vf = 1; vf = 1;
@@ -294,11 +298,11 @@ void Interpreter::subn_vx_vy(const Instruction& instruction) const {
} }
void Interpreter::shl_vx_vy(const Instruction& instruction) const { void Interpreter::shl_vx_vy(const Instruction& instruction) const {
auto& vx = machine_state->v[instruction.x]; auto& vx = this->machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y]; const auto& vy = this->machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF]; 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; vx = vy;
} }
@@ -312,36 +316,37 @@ void Interpreter::shl_vx_vy(const Instruction& instruction) const {
} }
void Interpreter::sne_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]) { if (this->machine_state->v[instruction.x] != this->machine_state->v[instruction.y]) {
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 {
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 (quirks & static_cast<uint8_t>(InterpreterQuirks::SUPER_CHIP_JUMP)) { if (this->quirks & static_cast<uint8_t>(InterpreterQuirks::SUPER_CHIP_JUMP)) {
machine_state->pc = instruction.nnn + machine_state->v[instruction.x]; this->machine_state->pc = instruction.nnn + this->machine_state->v[instruction.x];
} else { } 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) { void Interpreter::rnd_vx_byte(const Instruction& instruction) {
auto random = std::uniform_int_distribution<uint8_t>(0, 0xFF); auto distribution = std::uniform_int_distribution<uint8_t>(0, 0xFF);
const auto value = random(random_generator); 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 { void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const {
const auto& memory = machine_state->memory; const auto& memory = this->machine_state->memory;
auto& display = machine_state->display; auto& display = this->machine_state->display;
const auto& vx = machine_state->v[instruction.x]; const auto& vx = this->machine_state->v[instruction.x];
const auto& vy = machine_state->v[instruction.y]; const auto& vy = this->machine_state->v[instruction.y];
auto& vf = machine_state->v[0xF]; auto& vf = this->machine_state->v[0xF];
auto& i = this->machine_state->i;
const uint8_t start_x = vx & 63; const uint8_t start_x = vx & 63;
const uint8_t start_y = vy & 31; const uint8_t start_y = vy & 31;
@@ -354,7 +359,7 @@ void Interpreter::drw_vx_vy_nibble(const Instruction& instruction) const {
break; break;
} }
const auto sprite_byte = memory[machine_state->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;
@@ -379,80 +384,80 @@ 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 (machine_state->keyboard & 1 << instruction.x) { if (this->machine_state->keyboard & 1 << instruction.x) {
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 (!(machine_state->keyboard & 1 << instruction.x)) { if (!(this->machine_state->keyboard & 1 << instruction.x)) {
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 {
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 { void Interpreter::ld_vx_k(const Instruction& instruction) const {
if (machine_state->keyboard == 0) { if (this->machine_state->keyboard == 0) {
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 (machine_state->keyboard & 1 << key) { if (this->machine_state->keyboard & 1 << key) {
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 {
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 { 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 { 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 { 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 { void Interpreter::ld_b_vx(const Instruction& instruction) const {
const auto number = machine_state->v[instruction.x]; const auto number = this->machine_state->v[instruction.x];
machine_state->memory[machine_state->i] = number / 100; this->machine_state->memory[this->machine_state->i] = number / 100;
machine_state->memory[machine_state->i + 1] = (number - machine_state->memory[machine_state->i] * 100) / 10; this->machine_state->memory[this->machine_state->i + 1] = (number - this->machine_state->memory[this->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; 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 = 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) {
machine_state->memory[machine_state->i] = machine_state->v[reg]; this->machine_state->memory[this->machine_state->i] = this->machine_state->v[reg];
machine_state->i++; this->machine_state->i++;
} else { } 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 { 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++) { for (auto reg = 0; reg <= instruction.x; reg++) {
if (use_quirk) { if (use_quirk) {
machine_state->v[reg] = machine_state->memory[machine_state->i]; this->machine_state->v[reg] = this->machine_state->memory[this->machine_state->i];
machine_state->i++; this->machine_state->i++;
} else { } 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];
} }
} }
} }

View File

@@ -8,8 +8,8 @@
#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,
}; };
@@ -19,11 +19,11 @@ class Interpreter {
uint8_t quirks = 0; uint8_t quirks = 0;
static Instruction decode(uint16_t word); Instruction decode(uint16_t word) const;
void execute_instruction(const Instruction& instruction); void execute_instruction(const Instruction& instruction);
static void sys_addr(); void sys_addr() const;
static void nop(); void nop() const;
void cls() const; void cls() const;
void ret() const; void ret() const;
void jp_addr(const Instruction& instruction) const; void jp_addr(const Instruction& instruction) const;
@@ -66,5 +66,4 @@ public:
}; };
#endif //INTERPRETER_H #endif //INTERPRETER_H

View File

@@ -13,17 +13,15 @@ Machine::Machine():
accumulator{0} {} accumulator{0} {}
void Machine::iterate() { void Machine::iterate() {
execute_interpreter(); this->execute_interpreter();
this->chip8_display->update();
chip8_display->update(); this->graphics->start_render();
graphics->start_render();
ImGui::ShowDemoWindow(); ImGui::ShowDemoWindow();
chip8_display->render(); this->chip8_display->render();
graphics->end_render(); this->graphics->end_render();
} }
bool Machine::on_event(const SDL_Event* event) { 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) {
@@ -34,15 +32,15 @@ bool Machine::on_event(const SDL_Event* event) {
} }
void Machine::execute_interpreter() { void Machine::execute_interpreter() {
const auto target_cycle_time = 1.0 / ips; const auto target_cycle_time = 1.0 / this->ips;
const auto current_time = SDL_GetTicks(); const auto current_time = SDL_GetTicks();
const auto delta_time = static_cast<double>(current_time - last_update_time) / 1000.0; const auto delta_time = static_cast<double>(current_time - this->last_update_time) / 1000.0;
last_update_time = current_time; this->last_update_time = current_time;
accumulator += delta_time; this->accumulator += delta_time;
// ReSharper disable once CppDFALoopConditionNotUpdated // ReSharper disable once CppDFALoopConditionNotUpdated
while (accumulator >= target_cycle_time) { while (this->accumulator >= target_cycle_time) {
interpreter->tick(); this->interpreter->tick();
accumulator -= target_cycle_time; this->accumulator -= target_cycle_time;
} }
} }

View File

@@ -10,6 +10,7 @@ class Machine {
std::shared_ptr<MachineState> machine_state; std::shared_ptr<MachineState> machine_state;
std::unique_ptr<Interpreter> interpreter; std::unique_ptr<Interpreter> interpreter;
std::unique_ptr<Graphics> graphics; std::unique_ptr<Graphics> graphics;
std::unique_ptr<Chip8Display> chip8_display; std::unique_ptr<Chip8Display> chip8_display;
int ips; int ips;
@@ -21,7 +22,7 @@ void execute_interpreter();
public: public:
Machine(); Machine();
void iterate(); void iterate();
static bool on_event(const SDL_Event* event); bool on_event(const SDL_Event* event) const;
}; };
#endif //MACHINE_H #endif //MACHINE_H

19
src/old/MachineState.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef MACHINESTATE_H
#define MACHINESTATE_H
#include <array>
#include <cstdint>
struct MachineState {
std::array<uint8_t, 4096> memory{};
std::array<uint16_t, 16> v{};
std::array<uint16_t, 16> stack{};
std::array<bool, 2048> display{};
uint16_t keyboard = 0;
uint16_t pc = 0x200;
uint8_t sp = 0;
uint16_t i = 0;
uint8_t dt = 0;
uint8_t st = 0;
};
#endif //MACHINESTATE_H

51
src/old/main.cpp Normal file
View File

@@ -0,0 +1,51 @@
#define SDL_MAIN_USE_CALLBACKS 1
#include <SDL3/SDL_main.h>
#include "Chip8.h"
#include "imgui_impl_sdl3.h"
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
const auto chip8 = new Chip8();
*appstate = chip8;
if (!chip8->init()) {
return SDL_APP_FAILURE;
}
int num_keys;
const bool* kb_state = SDL_GetKeyboardState(&num_keys);
const std::span kb_state_view(kb_state, num_keys);
chip8->set_keyboard_state(kb_state_view);
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppIterate(void* appstate) {
const auto chip8 = static_cast<Chip8*>(appstate);
chip8->iterate();
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
const auto chip8 = static_cast<Chip8*>(appstate);
ImGui_ImplSDL3_ProcessEvent(event);
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS;
}
if (event->type == SDL_EVENT_KEY_DOWN) {
chip8->on_keydown(event->key.scancode);
}
return SDL_APP_CONTINUE;
}
void SDL_AppQuit(void* appstate, SDL_AppResult result) {
const auto chip8 = static_cast<Chip8*>(appstate);
delete chip8;
}