diff --git a/extern/imgui/CMakeLists.txt b/extern/imgui/CMakeLists.txt index c0a2ce5..35696fd 100644 --- a/extern/imgui/CMakeLists.txt +++ b/extern/imgui/CMakeLists.txt @@ -14,6 +14,8 @@ add_library(imgui src/imgui.cpp src/imstb_rectpack.h src/imstb_textedit.h - src/imstb_truetype.h) + src/imstb_truetype.h + src/imgui_stdlib.cpp + include/imgui_stdlib.h) target_include_directories(imgui PUBLIC include PRIVATE src) -target_link_libraries(imgui PUBLIC SDL2::Core glad) \ No newline at end of file +target_link_libraries(imgui PUBLIC SDL2::Core glad) diff --git a/extern/imgui/include/imgui_stdlib.h b/extern/imgui/include/imgui_stdlib.h new file mode 100644 index 0000000..f860b0c --- /dev/null +++ b/extern/imgui/include/imgui_stdlib.h @@ -0,0 +1,22 @@ +// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) +// This is also an example of how you may wrap your own similar types. + +// Compatibility: +// - std::string support is only guaranteed to work from C++11. +// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) + +// Changelog: +// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string + +#pragma once + +#include + +namespace ImGui +{ + // ImGui::InputText() with std::string + // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity + IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); +} diff --git a/extern/imgui/src/imgui_stdlib.cpp b/extern/imgui/src/imgui_stdlib.cpp new file mode 100644 index 0000000..cb1fe17 --- /dev/null +++ b/extern/imgui/src/imgui_stdlib.cpp @@ -0,0 +1,76 @@ +// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) +// This is also an example of how you may wrap your own similar types. + +// Compatibility: +// - std::string support is only guaranteed to work from C++11. +// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) + +// Changelog: +// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string + +#include "imgui.h" +#include "imgui_stdlib.h" + +struct InputTextCallback_UserData +{ + std::string* Str; + ImGuiInputTextCallback ChainCallback; + void* ChainCallbackUserData; +}; + +static int InputTextCallback(ImGuiInputTextCallbackData* data) +{ + InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData; + if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) + { + // Resize string callback + // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want. + std::string* str = user_data->Str; + IM_ASSERT(data->Buf == str->c_str()); + str->resize(data->BufTextLen); + data->Buf = (char*)str->c_str(); + } + else if (user_data->ChainCallback) + { + // Forward to user callback, if any + data->UserData = user_data->ChainCallbackUserData; + return user_data->ChainCallback(data); + } + return 0; +} + +bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +{ + IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); + flags |= ImGuiInputTextFlags_CallbackResize; + + InputTextCallback_UserData cb_user_data; + cb_user_data.Str = str; + cb_user_data.ChainCallback = callback; + cb_user_data.ChainCallbackUserData = user_data; + return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); +} + +bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +{ + IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); + flags |= ImGuiInputTextFlags_CallbackResize; + + InputTextCallback_UserData cb_user_data; + cb_user_data.Str = str; + cb_user_data.ChainCallback = callback; + cb_user_data.ChainCallbackUserData = user_data; + return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data); +} + +bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +{ + IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); + flags |= ImGuiInputTextFlags_CallbackResize; + + InputTextCallback_UserData cb_user_data; + cb_user_data.Str = str; + cb_user_data.ChainCallback = callback; + cb_user_data.ChainCallbackUserData = user_data; + return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); +} diff --git a/src/compiler.cpp b/src/compiler.cpp index d917ceb..3b39959 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -11,14 +11,6 @@ #include "emu.hpp" -// hard-coded :-( -const std::string test_program = - "var count = 3;" - "label(main);" - "count += 3;" - "draw_char(0, 5, count);" - "jump(main);"; - void set_bit(uint16_t& opcode, int digit, int value) { uint16_t mask = 0x0000; switch(digit) { @@ -159,20 +151,22 @@ std::map get_arguments(std::vector args, std::vec return real_args; } -void compile() { +void compile(std::string code) { int current_offset = 0; int next_instruction = 0; std::map function_map; bool needs_to_store_next_function = false; std::string next_function_to_store; + + code.erase(std::remove(code.begin(), code.end(), '\n'), code.end()); while(true) { - next_instruction = test_program.find_first_of(';', current_offset + 1); + next_instruction = code.find_first_of(';', current_offset + 1); if(next_instruction == -1) break; - auto instruction = test_program.substr(current_offset == 0 ? current_offset : current_offset + 1, current_offset == 0 ? (next_instruction - current_offset) : (next_instruction - current_offset) - 1); + auto instruction = code.substr(current_offset == 0 ? current_offset : current_offset + 1, current_offset == 0 ? (next_instruction - current_offset) : (next_instruction - current_offset) - 1); if(needs_to_store_next_function) { int offset = (int)opcodes.size() + variable_data.size() + program_begin; diff --git a/src/compiler.hpp b/src/compiler.hpp index c41df43..b08ed68 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -1,4 +1,6 @@ #pragma once -void compile(); +#include + +void compile(std::string code); void load_compiled_rom(); diff --git a/src/main.cpp b/src/main.cpp index 0c08c2e..3985758 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ #include "imgui.h" #include "imgui_impl_sdl.h" #include "imgui_impl_opengl3.h" +#include "imgui_stdlib.h" #include "compiler.hpp" constexpr std::array chip8_fontset = { @@ -250,17 +251,6 @@ int main(int argc, char* argv[]) { ImGui::EndMenu(); } - if(ImGui::MenuItem("Compile & Run Program")) { - state.reset(); - - memcpy(state.memory, chip8_fontset.data(), chip8_fontset.size()); - - compile(); - load_compiled_rom(); - - is_rom_open = true; - } - ImGui::EndMenu(); } @@ -325,6 +315,33 @@ int main(int argc, char* argv[]) { } ImGui::End(); + if(ImGui::Begin("Compiler")) { + static std::string test_program = + "var count = 3;\n" + "label(main);\n" + "count += 3;\n" + "draw_char(0, 5, count);\n" + "jump(main);"; + + ImGui::InputTextMultiline("Code", &test_program); + + if(ImGui::MenuItem("Compile")) { + state.reset(); + + memcpy(state.memory, chip8_fontset.data(), chip8_fontset.size()); + + compile(test_program); + } + + if(ImGui::MenuItem("Run")) { + load_compiled_rom(); + + is_rom_open = true; + } + } + + ImGui::End(); + if(state.draw_dirty) { glBindTexture(GL_TEXTURE_2D, pixels_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, screen_width, screen_height, 0, GL_RED, GL_UNSIGNED_BYTE, state.pixels);