diff --git a/CMakeLists.txt b/CMakeLists.txt index 074456b..e527244 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ else() set(libname "config") endif() -target_link_libraries(8ChocChip PRIVATE sfml-graphics sfml-audio sfml-window sfml-system nfd ${libname}++) +target_link_libraries(8ChocChip PRIVATE SDL3::SDL3 nfd ${libname}++) # Set the RPATH of the executable to include the directory where SFML libraries are located set_target_properties(8ChocChip PROPERTIES diff --git a/dependencies/sdl b/dependencies/sdl index 2f4a7bb..78cc5c1 160000 --- a/dependencies/sdl +++ b/dependencies/sdl @@ -1 +1 @@ -Subproject commit 2f4a7bbcedaaf49c8bf87e34081120a6a49a0d26 +Subproject commit 78cc5c173404488d80751af226d1eaf67033bcc4 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index df9402f..88e17c8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,12 +2,4 @@ add_subdirectory(sdl) add_subdirectory(util) add_subdirectory(emulator) -target_sources(8ChocChip PUBLIC main.cpp) - -if(CMAKE_HOST_WIN32) - set(libname "libconfig") -else() - set(libname "config") -endif() - -target_link_libraries(8ChocChip PRIVATE nfd ${libname}++ SDL2) \ No newline at end of file +target_sources(8ChocChip PUBLIC main.cpp) \ No newline at end of file diff --git a/src/emulator/Cpu.cpp b/src/emulator/Cpu.cpp index bac905e..e4704e8 100644 --- a/src/emulator/Cpu.cpp +++ b/src/emulator/Cpu.cpp @@ -71,9 +71,9 @@ void Cpu::cycle() { // Play sound until timer runs out if (this->soundTimer > 0) { - this->speaker->play(); + // this->speaker->play(); } else { - this->speaker->stop(); + // this->speaker->stop(); } } diff --git a/src/emulator/Keyboard.h b/src/emulator/Keyboard.h index 73aff39..bc1dfd2 100644 --- a/src/emulator/Keyboard.h +++ b/src/emulator/Keyboard.h @@ -9,6 +9,24 @@ class Keyboard { public: std::unordered_map keysPressed; std::function onNextKeyPress; + std::unordered_map KEYMAP = { + {30, 0x1}, // 1 + {31, 0x2}, // 2 + {32, 0x3}, // 3 + {33, 0xc}, // 4 + {20, 0x4}, // Q + {26, 0x5}, // W + {8, 0x6}, // E + {21, 0xD}, // R + {4, 0x7}, // A + {22, 0x8}, // S + {7, 0x9}, // D + {9, 0xE}, // F + {29, 0xA}, // Z + {27, 0x0}, // X + {6, 0xB}, // C + {25, 0xF} // V + }; void setOnNextKeyPress(std::function callback); void handleKeyDown(uint8_t keyCode); diff --git a/src/emulator/Renderer.cpp b/src/emulator/Renderer.cpp index a6b2b77..bcfba69 100644 --- a/src/emulator/Renderer.cpp +++ b/src/emulator/Renderer.cpp @@ -4,12 +4,12 @@ Renderer::Renderer() { this->display.resize(this->columns * this->rows); } -void Renderer::render() { +void Renderer::render(SDL_Renderer* renderer) { // Render the display for (uint16_t y = 0; y < this->rows; ++y) { for (uint16_t x = 0; x < this->columns; ++x) { if (this->display[y * this->columns + x]) { - drawPixel(x, y); + drawPixel(renderer, x, y); } } } diff --git a/src/emulator/Renderer.h b/src/emulator/Renderer.h index 97b7c6f..f7c4387 100644 --- a/src/emulator/Renderer.h +++ b/src/emulator/Renderer.h @@ -1,8 +1,9 @@ #ifndef RENDERER_H #define RENDERER_H -#include +#include #include +#include class Renderer { public: @@ -12,12 +13,12 @@ class Renderer { void clear(); - void render(); + void render(SDL_Renderer* renderer); uint16_t getColumns() const; uint16_t getRows() const; - virtual void drawPixel(uint16_t x, uint16_t y) = 0; + virtual void drawPixel(SDL_Renderer* renderer, uint16_t x, uint16_t y) = 0; private: const uint16_t columns = 64; const uint16_t rows = 32; diff --git a/src/main.cpp b/src/main.cpp index 0aee35f..fc8b5cf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,67 +2,75 @@ #include #include #include +#include +#include "sdl/MainMenu.h" -#include "sfml/Emulator.h" -#include "fstream" +#include #include "util/MiscUtil.h" -#include "sfml/MainMenu.h" - -#include "libconfig.h" #include "libconfig.hh" int main(int argc, char **argv) { - bool quickRom = false; std::string rom; for (int i = 0; i < argc; i++) { - std::string arg = argv[i]; + std::string_view arg = argv[i]; if (arg.rfind("--") != 0) continue; // TODO: Account for --longform or -sf (short form) commands. just needs a better command handler - std::string command = MiscUtil::toLowerCase(arg); + std::string command = MiscUtil::toLowerCase(std::string(arg)); if (command == "--rom") { - if (argc - 1 <= i) { - std::cerr << "Please include the path to the file" << std::endl; - } else { - quickRom = true; - rom = argv[i + 1]; + if (i + 1 < argc) { + // return Emulator().launch(argv[++i]); } + std::cerr << "Please include the path to the file" << std::endl; + return 0; + } + if (command == "--help") { + std::cerr << "Usage: 8chocchip --rom " << std::endl; + return 0; } } - std::string home = std::filesystem::path(getenv("HOME")).string(); - std::string configFilePath = (std::filesystem::path(home) / ".8chocchip.cfg").string(); + const char* home = nullptr; +#ifdef _WIN32 + home = std::getenv("USERPROFILE"); +#else + home = std::getenv("HOME"); +#endif + if (!home) { + std::cerr << "HOME environment variable not set!" << std::endl; + return 1; + } - std::vector windows; + std::string configFilePath = (std::filesystem::path(home) / ".8chocchip.cfg").string(); std::vector romDirectories; std::unordered_map> romFiles; - std::ifstream file(configFilePath, std::ios::binary | std::ios::ate); - if (file.good()) { - libconfig::Config config; + libconfig::Config config; + if (std::ifstream file(configFilePath, std::ios::binary | std::ios::ate); file.good()) { config.readFile(configFilePath); libconfig::Setting &settings = config.getRoot(); - if (!settings.exists("directories")) { settings.add("directories", libconfig::Setting::TypeArray); } - libconfig::Setting &directories = settings["directories"]; + libconfig::Setting& directories = settings["directories"]; + romDirectories.reserve(directories.getLength()); for (int i = 0; i < directories.getLength(); i++) { libconfig::Setting &string = directories[i]; std::string directoryPath = string.c_str(); romDirectories.emplace_back(directoryPath); - for (const auto& file: std::filesystem::directory_iterator(directoryPath)) { - if (file.is_directory()) - continue; // Skip directories + for (const auto& romFile: std::filesystem::directory_iterator(directoryPath)) { + if (romFile.is_directory()) { + continue; + } - printf("Processing file: %s\n", file.path().c_str()); + std::cout << "Processing file: " << romFile.path().c_str() << std::endl; // Check if the rom directory doesn't exist in romFiles, then add it if (romFiles.find(&romDirectories.back()) == romFiles.end()) { @@ -70,32 +78,65 @@ int main(int argc, char **argv) { } // Add the file path to the romFiles entry - romFiles.find(&romDirectories.back())->second.emplace_back(file.path()); + romFiles.find(&romDirectories.back())->second.emplace_back(romFile.path().string()); } } } else { - config_t cfg; - config_init(&cfg); - - config_setting_t *root = config_root_setting(&cfg); - config_setting_t *list = config_setting_add(root, "directories", CONFIG_TYPE_LIST); + try { + config.getRoot().add("directories", libconfig::Setting::TypeList); + config.writeFile(configFilePath.c_str()); - if (config_write_file(&cfg, configFilePath.c_str()) == CONFIG_FALSE) { - std::cerr << "Error creating configuration file." << std::endl; - config_destroy(&cfg); + std::cout << "Configuration file created successfully." << std::endl; + } catch (const libconfig::FileIOException &ioException) { + std::cerr << "I/O error while writing the configuration file." << std::endl; + return 1; + } catch (const libconfig::SettingException &settingException) { + std::cerr << "Setting error: " << settingException.what() << std::endl; return 1; } + } - std::cout << "Configuration file created successfully." << std::endl; + std::vector> windows; + MainMenu window(configFilePath, romFiles, romDirectories, windows); + windows.emplace_back(&window); + window.init(); - config_destroy(&cfg); - } + bool quit = false; + SDL_Event event; - if (quickRom) { - Emulator emulator; - return emulator.launch(rom); - } else { - MainMenu(romFiles, romDirectories, windows, configFilePath); + while (!quit) { + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_QUIT) { + quit = true; + } + + for (const auto& window : windows) { + window->handleEvent(event); + } + } + + for (const auto& windowPtr : windows) { + Window* window = windowPtr.get(); + std::cout << "start " << window << std::endl; + window->update(); + std::cout << "middle" << std::endl; + window->render(); + std::cout << "enmd" << std::endl; + } + + bool allWindowsClosed = true; + for (const auto& window : windows) { + if(window->isShown()){ + allWindowsClosed = false; + break; + } + } + + if (allWindowsClosed) { + quit = true; + } + + std::cout << "end loop e" << std::endl; } return 0; diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index b7a3c5c..a4b1f3e 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -1,5 +1,13 @@ target_sources(8ChocChip PRIVATE - sdl.cpp - sdl.h) + Emulator.cpp + Emulator.h + MainMenu.cpp + MainMenu.h + InputHandler.cpp + InputHandler.h + Window.cpp + Window.h +) -add_subdirectory(emulator) \ No newline at end of file +add_subdirectory(emulator) +add_subdirectory(ui) \ No newline at end of file diff --git a/src/sdl/Emulator.cpp b/src/sdl/Emulator.cpp new file mode 100644 index 0000000..9781fae --- /dev/null +++ b/src/sdl/Emulator.cpp @@ -0,0 +1,65 @@ +#include "Emulator.h" + +Emulator::Emulator(const std::string &rom) : cpu(&renderWrapper, &keyboard, &speaker), rom(rom) {} + +void Emulator::init() { + Window::init(); + + if (this->rom.empty()) { + std::cerr << "No ROM file has been specified :(" << std::endl; + return; + } + + std::ifstream file(this->rom, std::ios::binary | std::ios::ate); + if (!file.good()) { + std::cerr << "Can not find file " << this->rom << std::endl; + return; + } + + cpu.loadSpritesIntoMemory(); + + cpu.loadProgramIntoMemory(&file); +} + +bool Emulator::handleEvent(SDL_Event& event) { + if (!Window::handleEvent(event)) { + return false; + } + + switch (event.type) { + case SDL_EVENT_KEY_DOWN: + keyboard.handleKeyDown(event.key.scancode); + break; + case SDL_EVENT_KEY_UP: + keyboard.handleKeyUp(event.key.scancode); + break; + } + + return true; +} + +// void Emulator::focus() { +// if (!mShown) { +// SDL_ShowWindow(mWindow); +// } +// +// SDL_RaiseWindow(mWindow); +// } + +void Emulator::update() { + // Run a cycle of the emulator + this->cpu.cycle(); +} + +void Emulator::render() { + // Set renderer draw color + SDL_SetRenderDrawColor(this->renderer, 0, 0, 0, 0); + // Clear the window + SDL_RenderClear(this->renderer); + + // Render the window + this->renderWrapper.render(this->renderer); + SDL_RenderPresent(this->renderer); + + SDL_Delay(16); +} diff --git a/src/sdl/Emulator.h b/src/sdl/Emulator.h new file mode 100644 index 0000000..5631254 --- /dev/null +++ b/src/sdl/Emulator.h @@ -0,0 +1,28 @@ +#ifndef INC_8CHOCCHIP_SDL_H +#define INC_8CHOCCHIP_SDL_H + +#include "Window.h" +#include "../emulator/Cpu.h" +#include "emulator/SdlKeyboard.h" +#include "emulator/SdlRenderer.h" +#include "emulator/SdlSpeaker.h" + +class Emulator : public Window { +private: + SdlRenderer renderWrapper; + SdlSpeaker speaker; + SdlKeyboard keyboard; + Cpu cpu; + + const std::string &rom; +public: + Emulator(const std::string &rom); + + void init() override; + bool handleEvent(SDL_Event& event) override; + void update() override; + void render() override; +}; + + +#endif \ No newline at end of file diff --git a/src/sdl/InputHandler.cpp b/src/sdl/InputHandler.cpp index 17254a5..da10154 100644 --- a/src/sdl/InputHandler.cpp +++ b/src/sdl/InputHandler.cpp @@ -3,13 +3,13 @@ #include #include -void InputHandler::addKey(sf::Keyboard::Key key) { +void InputHandler::addKey(SDL_Keycode key) { removeKey(key); // Do this because when a button is held down it adds many into the list and breaks functionality\ // If the key is already in the list this will remove it, if not it wont do anything this->keys.emplace_back(key); } -void InputHandler::removeKey(sf::Keyboard::Key key) { +void InputHandler::removeKey(SDL_Keycode key) { auto it = std::find(this->keys.begin(), this->keys.end(), key); if (it != this->keys.end()) { this->keys.erase(it); @@ -23,20 +23,20 @@ void InputHandler::updateLastKeys() { } } -bool InputHandler::isJustPressed(sf::Keyboard::Key key) { +bool InputHandler::isJustPressed(SDL_Keycode key) { return std::count(this->keys.begin(), this->keys.end(), key) > 0 && std::count(this->lastKeys.begin(), this->lastKeys.end(), key) == 0; } -bool InputHandler::isPressed(sf::Keyboard::Key key) { +bool InputHandler::isPressed(SDL_Keycode key) { return std::count(this->keys.begin(), this->keys.end(), key); } -void InputHandler::addButton(sf::Mouse::Button button) { +void InputHandler::addButton(SDL_Keycode button) { removeButton(button); this->mouse.emplace_back(button); } -void InputHandler::removeButton(sf::Mouse::Button button) { +void InputHandler::removeButton(SDL_Keycode button) { auto it = std::find(this->mouse.begin(), this->mouse.end(), button); if (it != this->mouse.end()) { this->mouse.erase(it); @@ -50,10 +50,10 @@ void InputHandler::updateLastMouse() { } } -bool InputHandler::isJustClicked(sf::Mouse::Button button) { +bool InputHandler::isJustClicked(SDL_Keycode button) { return std::count(this->mouse.begin(), this->mouse.end(), button) && !std::count(this->lastMouse.begin(), this->lastMouse.end(), button); } -bool InputHandler::isClicked(sf::Mouse::Button button) { +bool InputHandler::isClicked(SDL_Keycode button) { return std::count(this->mouse.begin(), this->mouse.end(), button); } \ No newline at end of file diff --git a/src/sdl/InputHandler.h b/src/sdl/InputHandler.h index eb01dfc..f3d615e 100644 --- a/src/sdl/InputHandler.h +++ b/src/sdl/InputHandler.h @@ -1,33 +1,31 @@ #ifndef INC_8CHOCCHIP_INPUTHANDLER_H #define INC_8CHOCCHIP_INPUTHANDLER_H +#include #include -#include "SFML/Window/Keyboard.hpp" -#include "SFML/Window/Mouse.hpp" - class InputHandler { private: - std::vector keys; - std::vector mouse; + std::vector keys; + std::vector mouse; - std::vector lastKeys; - std::vector lastMouse; + std::vector lastKeys; + std::vector lastMouse; public: InputHandler() = default; - void addKey(sf::Keyboard::Key key); - void removeKey(sf::Keyboard::Key key); + void addKey(SDL_Keycode key); + void removeKey(SDL_Keycode key); void updateLastKeys(); - bool isJustPressed(sf::Keyboard::Key key); - bool isPressed(sf::Keyboard::Key key); + bool isJustPressed(SDL_Keycode key); + bool isPressed(SDL_Keycode key); - void addButton(sf::Mouse::Button button); - void removeButton(sf::Mouse::Button button); + void addButton(SDL_Keycode button); + void removeButton(SDL_Keycode button); void updateLastMouse(); - bool isJustClicked(sf::Mouse::Button button); - bool isClicked(sf::Mouse::Button button); + bool isJustClicked(SDL_Keycode button); + bool isClicked(SDL_Keycode button); }; -#endif // INC_8CHOCCHIP_INPUTHANDLER_H +#endif \ No newline at end of file diff --git a/src/sdl/MainMenu.cpp b/src/sdl/MainMenu.cpp new file mode 100644 index 0000000..8bd8f6e --- /dev/null +++ b/src/sdl/MainMenu.cpp @@ -0,0 +1,133 @@ +#include "MainMenu.h" + +#include +#include +#include +#include + +#include +#include + +#include "../util/MiscUtil.h" +#include "Emulator.h" + +#define WIDTH (64 * 15) +#define HEIGHT (32 * 15) + +MainMenu::MainMenu(std::string configFilePath, std::unordered_map> &romFiles, + std::vector &romDirectories, std::vector> &windows) : + configFilePath(configFilePath), romDirectories(romDirectories), romFiles(romFiles), windows(windows), + chooseFolder(0, 400, WIDTH, 80, "Select ROM") {} + +void MainMenu::init() { + Window::init(); + + for (auto& thing: this->romFiles) { + for (std::string& file: thing.second) { + + TextButton romButton(0, 25.0f * this->roms.size(), WIDTH, 25, MiscUtil::getFileFromPath(file)); + + this->roms.emplace(file, romButton); + } + } +} + +bool MainMenu::handleEvent(SDL_Event &event) { + if (!Window::handleEvent(event)) { + return false; + } + + switch (event.type) { + case SDL_EVENT_KEY_DOWN: + this->inputHandler.addKey(event.key.scancode); + break; + case SDL_EVENT_KEY_UP: + this->inputHandler.removeKey(event.key.scancode); + break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + this->inputHandler.addButton(event.button.button); + break; + case SDL_EVENT_MOUSE_BUTTON_UP: + this->inputHandler.removeButton(event.button.button); + break; + } + + return true; +} + +void MainMenu::update() { + SDL_FPoint point{}; + SDL_GetMouseState(&point.x, &point.y); + + if (inputHandler.isJustPressed(SDL_SCANCODE_F3)) { + this->debug = !this->debug; + } + + for (auto &romButton: roms) { + romButton.second.update(this->inputHandler, point); + + if (!romButton.second.isJustClicked()) { + continue; + } + + this->windows.emplace_back(std::make_unique(romButton.first))->init(); + std::cout << 1 << std::endl; + } + this->chooseFolder.update(this->inputHandler, point); + + if (this->chooseFolder.isJustClicked()) { + + if (nfdresult_t result = PickFolder(this->outPath); result == NFD_OKAY) { + libconfig::Config config; + config.readFile(this->configFilePath); + + libconfig::Setting &settings = config.getRoot(); + + if (!settings.exists("directories")) { + settings.add("directories", libconfig::Setting::TypeArray); + } + + libconfig::Setting &directories = settings["directories"]; + directories.add(libconfig::Setting::TypeString) = outPath.get(); + + romDirectories.emplace_back(outPath.get()); + + for (const auto &file: std::filesystem::directory_iterator(outPath.get())) { + if (file.is_directory()) { + continue; // TODO: Make sure its a file that can be emulated, at least basic checks so it isn't like + // a word doc + } + + printf("Processing file - : %s\n", file.path().c_str()); + + // Check if the rom directory doesn't exist in romFiles, then add it + if (romFiles.find(&romDirectories.back()) == romFiles.end()) { + romFiles.emplace(&romDirectories.back(), std::vector()); + } + + // Add the file path to the romFiles entry + romFiles.find(&romDirectories.back())->second.emplace_back(file.path().string()); + + TextButton romButton(0, 25.0f * roms.size(), WIDTH, 25, file.path().filename().string()); + roms.emplace(file.path().string(), romButton); + } + config.writeFile(configFilePath); + } + } + + this->inputHandler.updateLastKeys(); + this->inputHandler.updateLastMouse(); + + std::cout << 2 << std::endl; +} + +void MainMenu::render() { + SDL_SetRenderDrawColor(this->renderer, 0x00, 0x00, 0x00, 0x00); + SDL_RenderClear(renderer); + for (auto &romButton: roms) { + romButton.second.draw(renderer); + } + this->chooseFolder.draw(renderer); + + SDL_RenderPresent(renderer); +} diff --git a/src/sdl/MainMenu.h b/src/sdl/MainMenu.h new file mode 100644 index 0000000..25dedd1 --- /dev/null +++ b/src/sdl/MainMenu.h @@ -0,0 +1,38 @@ +#ifndef MAINMENU_H +#define MAINMENU_H + +#include +#include + +#include + +#include "Emulator.h" +#include "InputHandler.h" +#include "Window.h" +#include "ui/TextButton.h" + +class MainMenu : public Window { +private: + std::string configFilePath; + std::vector& romDirectories; + std::unordered_map>& romFiles; + std::vector>& windows; + + NFD::Guard nfdGuard; + NFD::UniquePath outPath; + + std::unordered_map roms; + TextButton chooseFolder; + + InputHandler inputHandler{}; +public: + MainMenu(std::string configFilePath, std::unordered_map>& romFiles, + std::vector& romDirectories, std::vector>& windows); + + void init() override; + bool handleEvent(SDL_Event& event) override; + void update() override; + void render() override; +}; + +#endif \ No newline at end of file diff --git a/src/sdl/Window.cpp b/src/sdl/Window.cpp new file mode 100644 index 0000000..9e0cc7f --- /dev/null +++ b/src/sdl/Window.cpp @@ -0,0 +1,99 @@ +#include "Window.h" + +#include + +Window::Window() { +} + +Window::~Window() { + +} + +void Window::init() { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; + return; + } + + if (!SDL_CreateWindowAndRenderer("8ChocChip - CHIP-8 Emulator", 64 * 15, 32 * 15, SDL_WINDOW_RESIZABLE, &this->window, &this->renderer)) { + std::cerr << "Couldn't create window and renderer. SDL_Error: " << SDL_GetError() << std::endl; + return; + } + + // Set window icon + SDL_Surface* icon = SDL_LoadBMP("assets/icon.bmp"); + if (!icon) { + std::cerr << "Icon could not be loaded! SDL_Error: " << SDL_GetError() << std::endl; + return; + } + SDL_SetWindowIcon(this->window, icon); + SDL_DestroySurface(icon); + + this->windowId = SDL_GetWindowID(this->window); + this->shown = true; +} + +bool Window::handleEvent(SDL_Event &event) { + if (event.window.windowID == this->windowId) { + bool caption = false; + + switch (event.type) { + case SDL_EVENT_WINDOW_SHOWN: + this->shown = true; + break; + case SDL_EVENT_WINDOW_HIDDEN: + this->shown = false; + break; + case SDL_EVENT_WINDOW_RESIZED: + //TODO + break; + case SDL_EVENT_WINDOW_EXPOSED: + SDL_RenderPresent(this->renderer); + break; + case SDL_EVENT_WINDOW_MOUSE_ENTER: + this->mouseFocus = true; + caption = true; + break; + case SDL_EVENT_WINDOW_MOUSE_LEAVE: + this->mouseFocus = false; + caption = false; + break; + case SDL_EVENT_WINDOW_FOCUS_GAINED: + this->keyboardFocus = true; + caption = true; + break; + case SDL_EVENT_WINDOW_FOCUS_LOST: + this->keyboardFocus = false; + caption = true; + break; + case SDL_EVENT_WINDOW_MINIMIZED: + this->minimised = true; + break; + case SDL_EVENT_WINDOW_MAXIMIZED: + this->minimised = false; + break; + case SDL_EVENT_WINDOW_RESTORED: + this->minimised = false; + break; + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + SDL_HideWindow(this->window); + break; + } + + return true; + } + + return false; +} + + +void Window::update() { +} + +void Window::close() { + +} + +bool Window::isShown() { + return true; +} diff --git a/src/sdl/Window.h b/src/sdl/Window.h new file mode 100644 index 0000000..d835520 --- /dev/null +++ b/src/sdl/Window.h @@ -0,0 +1,35 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include + +class Window { +protected: + SDL_Window* window = nullptr; + SDL_Renderer* renderer = nullptr; + unsigned int windowId = -1; + + int height = 720; + int width = 480; + + bool mouseFocus = false; + bool keyboardFocus = false; + bool fullscreen = false; + bool minimised = false; + bool shown = false; + + bool debug = false; +public: + Window(); + virtual ~Window(); + + virtual void init(); + virtual bool handleEvent(SDL_Event& event); + virtual void update(); + virtual void render() = 0; + void close(); + + bool isShown(); +}; + +#endif \ No newline at end of file diff --git a/src/sdl/emulator/SdlKeyboard.h b/src/sdl/emulator/SdlKeyboard.h index 7950b17..3e09c58 100644 --- a/src/sdl/emulator/SdlKeyboard.h +++ b/src/sdl/emulator/SdlKeyboard.h @@ -6,27 +6,27 @@ class SdlKeyboard : public Keyboard { private: - std::unordered_map KEYMAP = { - {49, 0x1}, // 1 - {50, 0x2}, // 2 - {51, 0x3}, // 3 - {52, 0xc}, // 4 - {113, 0x4}, // Q - {119, 0x5}, // W - {101, 0x6}, // E - {114, 0xD}, // R - {97, 0x7}, // A - {115, 0x8}, // S - {100, 0x9}, // D - {102, 0xE}, // F - {122, 0xA}, // Z - {120, 0x0}, // X - {99, 0xB}, // C - {118, 0xF} // V - }; + // std::unordered_map KEYMAP = { + // {49, 0x1}, // 1 + // {50, 0x2}, // 2 + // {51, 0x3}, // 3 + // {52, 0xc}, // 4 + // {113, 0x4}, // Q + // {119, 0x5}, // W + // {101, 0x6}, // E + // {114, 0xD}, // R + // {97, 0x7}, // A + // {115, 0x8}, // S + // {100, 0x9}, // D + // {102, 0xE}, // F + // {122, 0xA}, // Z + // {120, 0x0}, // X + // {99, 0xB}, // C + // {118, 0xF} // V + // }; public: - void handleKeyDown(uint8_t keyCode) override; - void handleKeyUp(uint8_t keyCode) override; + void handleKeyDown(uint8_t keyCode); + void handleKeyUp(uint8_t keyCode); }; #endif // INC_8CHOCCHIP_SDLKEYBOARD_H diff --git a/src/sdl/emulator/SdlRenderer.cpp b/src/sdl/emulator/SdlRenderer.cpp index 7ba78b3..0657e81 100644 --- a/src/sdl/emulator/SdlRenderer.cpp +++ b/src/sdl/emulator/SdlRenderer.cpp @@ -1,17 +1,14 @@ #include "SdlRenderer.h" -SdlRenderer::SdlRenderer(SDL_Renderer* window) { - this->window = window; +#include +#include - this->scale = 15; // Scale up because 64 x 32 would be tiny on our screens now +void SdlRenderer::drawPixel(SDL_Renderer* renderer, uint16_t x, uint16_t y) { + const SDL_FRect rect = {x * scale, y * scale, scale, scale}; + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // Set color to white + SDL_RenderFillRect(renderer, &rect); } -void SdlRenderer::drawPixel(uint16_t x, uint16_t y) { - SDL_Rect rect = {x * scale, y * scale, scale, scale}; - SDL_SetRenderDrawColor(window, 255, 255, 255, 255); // Set color to white - SDL_RenderFillRect(window, &rect); -} - -uint8_t SdlRenderer::getScale() const { +float SdlRenderer::getScale() const { return this->scale; } \ No newline at end of file diff --git a/src/sdl/emulator/SdlRenderer.h b/src/sdl/emulator/SdlRenderer.h index 9809cf2..4572f52 100644 --- a/src/sdl/emulator/SdlRenderer.h +++ b/src/sdl/emulator/SdlRenderer.h @@ -2,18 +2,14 @@ #define INC_8CHOCCHIP_SDLRENDERER_H #include "../../emulator/Renderer.h" -#include "SDL2/SDL.h" +#include class SdlRenderer : public Renderer { private: - SDL_Renderer* window; - - uint8_t scale; + float scale = 15; public: - SdlRenderer(SDL_Renderer* window); - - void drawPixel(uint16_t x, uint16_t y) override; - uint8_t getScale() const; + void drawPixel(SDL_Renderer* renderer, uint16_t x, uint16_t y) override; + float getScale() const; }; -#endif // INC_8CHOCCHIP_SDLRENDERER_H +#endif \ No newline at end of file diff --git a/src/sdl/emulator/SdlSpeaker.cpp b/src/sdl/emulator/SdlSpeaker.cpp index 553f1b7..ebe3f5d 100644 --- a/src/sdl/emulator/SdlSpeaker.cpp +++ b/src/sdl/emulator/SdlSpeaker.cpp @@ -1,13 +1,14 @@ #include "SdlSpeaker.h" -#include -SdlSpeaker::SdlSpeaker() { +#include -} +SdlSpeaker::SdlSpeaker() = default; void SdlSpeaker::play() { + std::cout <<"sp" << std::endl; } void SdlSpeaker::stop() { + std::cout <<"sp1" << std::endl; } diff --git a/src/sdl/emulator/SdlSpeaker.h b/src/sdl/emulator/SdlSpeaker.h index f7941ee..539b1e9 100644 --- a/src/sdl/emulator/SdlSpeaker.h +++ b/src/sdl/emulator/SdlSpeaker.h @@ -12,4 +12,4 @@ class SdlSpeaker : public Speaker { void stop() override; }; -#endif // INC_8CHOCCHIP_SDLSPEAKER_H +#endif \ No newline at end of file diff --git a/src/sdl/sdl.cpp b/src/sdl/sdl.cpp deleted file mode 100644 index 8e04c66..0000000 --- a/src/sdl/sdl.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "sdl.h" - -#include -#include -#include - -#include "../emulator/Cpu.h" -#include "emulator/SdlKeyboard.h" -#include "emulator/SdlRenderer.h" -#include "emulator/SdlSpeaker.h" - -#include "SDL2/SDL.h" - -int sdl::launch(const std::string &rom) { - if (rom.empty()) { - std::cerr << "No ROM file has been specified :(" << std::endl; - return 1; - } - - std::ifstream file(rom, std::ios::binary | std::ios::ate); - if (!file.good()) { - std::cerr << "Can not find file " << rom << std::endl; - return 1; - } - - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { - std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; - return -1; - } - - SDL_Window *window = SDL_CreateWindow("8ChocChip - CHIP-8 Emulator", SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, 64 * 15, 32 * 15, SDL_WINDOW_SHOWN); - - if (window == nullptr) { - std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl; - return -1; - } - - // Set window icon - SDL_Surface *icon = SDL_LoadBMP("../../assets/icon.bmp"); - if (icon == nullptr) { - std::cerr << "Icon could not be loaded! SDL_Error: " << SDL_GetError() << std::endl; - return -1; - } - SDL_SetWindowIcon(window, icon); - SDL_FreeSurface(icon); - - // Create renderer - SDL_Renderer *windowRenderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); - if (windowRenderer == nullptr) { - std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() << std::endl; - return -1; - } - - SdlRenderer renderer(windowRenderer); - SdlSpeaker speaker; - SdlKeyboard keyboard; - Cpu cpu(&renderer, &keyboard, &speaker); - - cpu.loadSpritesIntoMemory(); - - cpu.loadProgramIntoMemory(&file); - - bool focus; - - auto start = std::chrono::high_resolution_clock::now(); - auto end = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed_seconds; - - // Variables to count frames - int frames = 0; - double fps; - - const int SCREEN_TICKS_PER_FRAME = 1000 / 60; // Time per frame in milliseconds - - Uint32 startTicks; - - while (true) { - startTicks = SDL_GetTicks(); - - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { - SDL_DestroyRenderer(windowRenderer); - SDL_DestroyWindow(window); - SDL_Quit(); - return 0; - } else if (event.type == SDL_WINDOWEVENT) { - if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) { - focus = true; - } else if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { - focus = false; - } - } - - if (!focus) continue; - - // Handle keyboard inputs - if (event.type == SDL_KEYDOWN) { - keyboard.handleKeyDown(event.key.keysym.sym); - } else if (event.type == SDL_KEYUP) { - keyboard.handleKeyUp(event.key.keysym.sym); - } - } - - // Run a cycle of the emulator - cpu.cycle(); - - // Set renderer draw color - SDL_SetRenderDrawColor(windowRenderer, 0, 0, 0, 255); - // Clear the window - SDL_RenderClear(windowRenderer); - - // Render the window - renderer.render(); - SDL_RenderPresent(windowRenderer); - - // Calculate time spent in frame - int frameTicks = SDL_GetTicks() - startTicks; - - // If frame finished early - if (frameTicks < SCREEN_TICKS_PER_FRAME) { - // Wait remaining time - SDL_Delay(SCREEN_TICKS_PER_FRAME - frameTicks); - } - - frames++; - - end = std::chrono::high_resolution_clock::now(); - elapsed_seconds = end - start; - - // If elapsed time is greater than or equal to 1 second - if (elapsed_seconds.count() >= 1.0) { - // Calculate FPS - fps = frames / elapsed_seconds.count(); - - // Output FPS - std::cout << "FPS: " << fps << std::endl; - - // Reset frame count and start time - frames = 0; - start = std::chrono::high_resolution_clock::now(); - } - } -} \ No newline at end of file diff --git a/src/sdl/sdl.h b/src/sdl/sdl.h deleted file mode 100644 index c816ac2..0000000 --- a/src/sdl/sdl.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef INC_8CHOCCHIP_SDL_H -#define INC_8CHOCCHIP_SDL_H - -#include - -class sdl { -public: - int launch(const std::string &rom); -}; - - -#endif // INC_8CHOCCHIP_SDL_H diff --git a/src/sdl/ui/CMakeLists.txt b/src/sdl/ui/CMakeLists.txt new file mode 100644 index 0000000..79ff477 --- /dev/null +++ b/src/sdl/ui/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(8ChocChip PRIVATE + TextButton.cpp + TextButton.h +) \ No newline at end of file diff --git a/src/sdl/ui/TextButton.cpp b/src/sdl/ui/TextButton.cpp new file mode 100644 index 0000000..2ca470c --- /dev/null +++ b/src/sdl/ui/TextButton.cpp @@ -0,0 +1,73 @@ +#include "TextButton.h" + +#include + +TextButton::TextButton(float x, float y, float width, float height, const std::string& buttonText) : text(text) { + this->button = SDL_FRect{x, y, width, height}; + // this->button.setPosition(sf::Vector2f(x, y)); + + // this->originalPosition = this->button.getPosition(); + // this->originalSize = this->button.getSize(); + + // this->text.setFont(*font); + // this->text.setString(buttonText); + // this->text.setCharacterSize(20); + // this->text.setFillColor(sf::Color::Black); + // this->text.setPosition(x + width / 2 - this->text.getGlobalBounds().width / 2, y + height / 2 - this->text.getGlobalBounds().height / 2); + + this->idleColor = SDL_Color{192, 192, 192}; + this->hoverColor = SDL_Color{128, 128, 128}; + this->activeColor = SDL_Color{64, 64, 64}; + + // this->button.setFillColor(this->idleColor); + + this->isPressed = false; + this->isHovered = false; +} + +void TextButton::updateSize(const SDL_Point originalSize, const SDL_Point updatedSize) { + // this->button.setSize(SDL_Point(this->originalSize.x / originalSize.x * updatedSize.x, this->originalSize.y / originalSize.y * updatedSize.y)); + // this->button.setPosition(this->originalPosition.x / originalSize.x * updatedSize.x, this->originalPosition.y / originalSize.y * updatedSize.y); + + // this->text.setPosition(this->button.getPosition().x + this->button.getSize().x / 2 - this->text.getGlobalBounds().width / 2, this->button.getPosition().y + this->button.getSize().y / 2 - this->text.getGlobalBounds().height / 2); +} + +void TextButton::update(InputHandler& inputHandler, SDL_FPoint pos) { + this->lastPressed = this->isPressed; + this->isHovered = SDL_PointInRectFloat(&pos, &this->button); + + if (this->isHovered && inputHandler.isJustClicked(SDL_BUTTON_LEFT)) { + this->isPressed = true; + updateColour(this->activeColor); + } else if (this->isHovered && inputHandler.isPressed(SDL_KMOD_LSHIFT)) { + updateColour( SDL_Color{255, 0, 0}); + } else if (this->isHovered) { + updateColour(this->hoverColor); + } else { + this->isPressed = false; + updateColour(this->idleColor); + } +} + +void TextButton::updateColour(const SDL_Color color) { + if (this->color.r == color.r && this->color.g == color.g && this->color.b == color.b) { + return; + } + + this->currentColor = color; +} + +void TextButton::draw(SDL_Renderer* window) const { + // window.draw(this->button); + + SDL_SetRenderDrawColor(window, this->currentColor.r, this->currentColor.g, this->currentColor.b, this->currentColor.a); + SDL_RenderFillRect(window, &this->button); +} + +bool TextButton::isClicked() const { + return this->isPressed; +} + +bool TextButton::isJustClicked() const { + return !this->lastPressed && this->isPressed; +} \ No newline at end of file diff --git a/src/sdl/ui/TextButton.h b/src/sdl/ui/TextButton.h new file mode 100644 index 0000000..37ce40c --- /dev/null +++ b/src/sdl/ui/TextButton.h @@ -0,0 +1,43 @@ +#ifndef TEXTBUTTON_H +#define TEXTBUTTON_H + +#include "../InputHandler.h" +#include + +#include + +class TextButton { +private: + SDL_FRect button; + SDL_Point originalSize; + SDL_Point originalPosition; + std::string& text; + // sf::Font* font{}; + SDL_Color color; + SDL_Color idleColor; + SDL_Color hoverColor; + SDL_Color activeColor; + SDL_Color currentColor; + bool isPressed; + bool lastPressed{}; + bool isHovered; + +public: + TextButton(float x, float y, float width, float height, const std::string& buttonText); + + void updateSize(SDL_Point originalSize, SDL_Point updatedSize); + + void update(InputHandler& inputHandler, SDL_FPoint pos); + + void draw(SDL_Renderer* window) const; + + bool isClicked() const; + + bool isJustClicked() const; + + void updateColour(SDL_Color color); +}; + + + +#endif \ No newline at end of file diff --git a/src/sfml/CMakeLists.txt b/src/sfml/CMakeLists.txt deleted file mode 100644 index 6e1d4d1..0000000 --- a/src/sfml/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -target_sources(8ChocChip PRIVATE - MainMenu.cpp - MainMenu.h - Emulator.cpp - Emulator.h - InputHandler.cpp - InputHandler.h) - -add_subdirectory(ui) -add_subdirectory(emulator) \ No newline at end of file diff --git a/src/sfml/Emulator.cpp b/src/sfml/Emulator.cpp deleted file mode 100644 index 834bd84..0000000 --- a/src/sfml/Emulator.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "Emulator.h" - -#include -#include - -#include "../emulator/Cpu.h" -#include "../emulator/Keyboard.h" -#include "emulator/SfmlRenderer.h" -#include "emulator/SfmlSpeaker.h" - -int Emulator::launch(const std::string &rom) { - if (rom.empty()) { - std::cerr << "No ROM file has been specified :(" << std::endl; - return 1; - } - - std::ifstream file(rom, std::ios::binary | std::ios::ate); - if (!file.good()) { - std::cerr << "Can not find file " << rom << std::endl; - return 1; - } - - sf::RenderWindow window(sf::VideoMode(64 * 15, 32 * 15), "8ChocChip - CHIP-8 Emulator", sf::Style::Titlebar | sf::Style::Close); - sf::Image icon; - icon.loadFromFile("../../assets/icon.png"); - window.setIcon(64, 64, icon.getPixelsPtr()); - window.setFramerateLimit(60); - - SfmlRenderer renderer(&window); - - SfmlSpeaker speaker; - Keyboard keyboard; - Cpu cpu(&renderer, &keyboard, &speaker); - - cpu.loadSpritesIntoMemory(); - - cpu.loadProgramIntoMemory(&file); - - bool focus; - - while (window.isOpen()) { - sf::Event event{}; - while (window.pollEvent(event)) { - if (event.type == sf::Event::Closed) { - window.close(); - } else if (event.type == sf::Event::LostFocus) { - focus = false; - } else if (event.type == sf::Event::GainedFocus) { - focus = true; - } - - if (!focus) continue; - - // TODO: You can hold down the button and it will run at the next possible point - // fix this but make it a little easier to time because otherwise you need to time it perfectly which doesnt feel good - // ^ if the InputHandler was to be used anyway - // Handle keyboard inputs - if (event.type == sf::Event::KeyPressed) { - keyboard.handleKeyDown(event.key.code); - } else if (event.type == sf::Event::KeyReleased) { - keyboard.handleKeyUp(event.key.code); - } - } - - // Run a cycle of the emulator - cpu.cycle(); - - // Clear the window - window.clear(sf::Color::Black); - - // Render the window - renderer.render(); - window.display(); - } - - return 0; -} diff --git a/src/sfml/Emulator.h b/src/sfml/Emulator.h deleted file mode 100644 index 46ed1cc..0000000 --- a/src/sfml/Emulator.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef INC_8CHOCCHIP_EMULATOR_H -#define INC_8CHOCCHIP_EMULATOR_H - -#include - -class Emulator { -private: -public: - int launch(const std::string& rom); -}; - - -#endif // INC_8CHOCCHIP_EMULATOR_H diff --git a/src/sfml/MainMenu.cpp b/src/sfml/MainMenu.cpp deleted file mode 100644 index eb13f24..0000000 --- a/src/sfml/MainMenu.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "MainMenu.h" - -#include -#include - -#include "libconfig.h++" -#include "nfd.hpp" - -#include "Emulator.h" -#include "ui/TextButton.h" -#include "../util/MiscUtil.h" - -MainMenu::MainMenu(std::unordered_map>& romFiles, - std::vector& romDirectories, std::vector>& windows, - std::string configFilePath) : - window(sf::VideoMode(640, 480), "8ChocChip - Chip8 Emulator"), windows(windows), - romDirectories(romDirectories), romFiles(romFiles), inputHandler() { - - NFD::Guard nfdGuard; - - // auto-freeing memory - NFD::UniquePath outPath; - - sf::Vector2u originalWindowSize = this->window.getSize(); - sf::Image icon; - icon.loadFromFile("assets/icon.png"); - this->window.setIcon(64, 64, icon.getPixelsPtr()); -// this->window.setVerticalSyncEnabled(true); - - sf::Font font; - font.loadFromFile("assets/font.ttf"); - - std::unordered_map roms; - - for (auto& thing : romFiles) { - for (std::string& file : thing.second) { - - TextButton romButton(0, 25.0f * roms.size(), this->window.getSize().x, 25, MiscUtil::getFileFromPath(file), &font); - - roms.emplace(file, romButton); - } - } - - TextButton button(0, 400, 640, 80, "Select ROM", &font); - - bool focus; - bool debug = false; - - auto start = std::chrono::high_resolution_clock::now(); - auto end = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed_seconds{}; - - // Variables to count frames - int frames = 0; - double fps; - - while (this->window.isOpen()) { - sf::Event event{}; - sf::Vector2i pos = sf::Mouse::getPosition(this->window); - - this->inputHandler.updateLastKeys(); - this->inputHandler.updateLastMouse(); - - while (this->window.pollEvent(event)) { - if (event.type == sf::Event::Closed) { - this->window.close(); - } else if (event.type == sf::Event::LostFocus) { - focus = false; - } else if (event.type == sf::Event::GainedFocus) { - focus = true; - } else if (event.type == sf::Event::Resized) { - sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); - this->window.setView(sf::View(visibleArea)); - - for (auto& romButton : roms) { - romButton.second.updateSize(originalWindowSize, this->window.getSize()); - romButton.second.update(&this->inputHandler, pos); - } - - button.updateSize(originalWindowSize, this->window.getSize()); - button.update(&this->inputHandler, pos); - } else if (event.type == sf::Event::KeyPressed) { - this->inputHandler.addKey(event.key.code); - } else if (event.type == sf::Event::KeyReleased) { - this->inputHandler.removeKey(event.key.code); - } else if (event.type == sf::Event::MouseButtonPressed) { - this->inputHandler.addButton(event.mouseButton.button); - } else if (event.type == sf::Event::MouseButtonReleased) { - this->inputHandler.removeButton(event.mouseButton.button); - } - } - - if (focus) { - if (this->inputHandler.isJustPressed(sf::Keyboard::F3)) { - debug = !debug; - } - - for (auto& romButton : roms) { - romButton.second.update(&this->inputHandler, pos); - - if (!romButton.second.isJustClicked()) continue; - - Emulator emulator; - std::thread newWindow(&Emulator::launch, &emulator, romButton.first); - newWindow.detach(); - windows.emplace_back(&newWindow); - } - button.update(&this->inputHandler, pos); - - if (button.isJustClicked()) { - - if (nfdresult_t result = PickFolder(outPath); result == NFD_OKAY) { - libconfig::Config config; - config.readFile(configFilePath); - - libconfig::Setting& settings = config.getRoot(); - - if (!settings.exists("directories")) { - settings.add("directories", libconfig::Setting::TypeArray); - } - - libconfig::Setting& directories = settings["directories"]; - directories.add(libconfig::Setting::TypeString) = outPath.get(); - - romDirectories.emplace_back(outPath.get()); - - for (const auto& file : std::filesystem::directory_iterator(outPath.get())) { - if (file.is_directory()) continue; // TODO: Make sure its a file that can be emulated, at least basic checks so it isn't like a word doc - - printf("Processing file - : %s\n", file.path().c_str()); - - // Check if the rom directory doesn't exist in romFiles, then add it - if (romFiles.find(&romDirectories.back()) == romFiles.end()) { - romFiles.emplace(&romDirectories.back(), std::vector()); - } - - // Add the file path to the romFiles entry - romFiles.find(&romDirectories.back())->second.emplace_back(file.path().string()); - - TextButton romButton(0, 25.0f * roms.size(), this->window.getSize().x, 25, file.path().filename().string(), &font); - roms.emplace(file.path().string(), romButton); - } - config.writeFile(configFilePath); - } - } - } - - this->window.clear(sf::Color::White); - for (auto& romButton : roms) { - romButton.second.draw(this->window); - } - button.draw(this->window); - - this->window.display(); - - frames++; - - end = std::chrono::high_resolution_clock::now(); - elapsed_seconds = end - start; - - // If elapsed time is greater than or equal to 1 second - if (debug && elapsed_seconds.count() >= 1.0) { - // Calculate FPS - fps = frames / elapsed_seconds.count(); - - // Output FPS - std::cout << "FPS: " << fps << std::endl; - - // Reset frame count and start time - frames = 0; - start = std::chrono::high_resolution_clock::now(); - } - } -} diff --git a/src/sfml/MainMenu.h b/src/sfml/MainMenu.h deleted file mode 100644 index 9d5ec51..0000000 --- a/src/sfml/MainMenu.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef INC_8CHOCCHIP_MAINMENU_H -#define INC_8CHOCCHIP_MAINMENU_H - -#include -#include - -#include "SFML/Graphics.hpp" -#include "InputHandler.h" - -class MainMenu { -private: - sf::RenderWindow window; - std::vector>& windows; - - std::vector& romDirectories; - std::unordered_map>& romFiles; - - InputHandler inputHandler; -public: - MainMenu(std::unordered_map>& romFiles, - std::vector& romDirectories, std::vector>& windows, - std::string configFilePath); -}; - - -#endif // INC_8CHOCCHIP_MAINMENU_H diff --git a/src/sfml/emulator/CMakeLists.txt b/src/sfml/emulator/CMakeLists.txt deleted file mode 100644 index 9c17dbd..0000000 --- a/src/sfml/emulator/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(8ChocChip PRIVATE - SfmlSpeaker.cpp - SfmlSpeaker.h - SfmlRenderer.cpp - SfmlRenderer.h) \ No newline at end of file diff --git a/src/sfml/emulator/SfmlRenderer.cpp b/src/sfml/emulator/SfmlRenderer.cpp deleted file mode 100644 index cfbeacc..0000000 --- a/src/sfml/emulator/SfmlRenderer.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "SfmlRenderer.h" - -SfmlRenderer::SfmlRenderer(sf::RenderWindow* window) : window(window) { - this->scale = 15; // Scale up because 64 x 32 would be tiny on our screens now -} - -void SfmlRenderer::drawPixel(const uint16_t x, const uint16_t y) { - sf::RectangleShape rectangle(sf::Vector2f(getScale(), getScale())); - rectangle.setPosition(x * getScale(), y * getScale()); - rectangle.setFillColor(sf::Color::White); - - this->window->draw(rectangle); -} - -uint8_t SfmlRenderer::getScale() const { - return this->scale; -} \ No newline at end of file diff --git a/src/sfml/emulator/SfmlSpeaker.cpp b/src/sfml/emulator/SfmlSpeaker.cpp deleted file mode 100644 index 280b5bd..0000000 --- a/src/sfml/emulator/SfmlSpeaker.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "SfmlSpeaker.h" - -#include - -SfmlSpeaker::SfmlSpeaker() { - - this->sound.setVolume(100.f); - this->sound.setLoop(true); - - constexpr unsigned int sampleRate = 44100; - sf::Int16 samples[sampleRate]; - for (unsigned int i = 0; i < sampleRate; ++i) { - constexpr unsigned int frequency = 440; - samples[i] = static_cast(32767 * std::sin(2 * 3.14159265 * frequency * i / sampleRate)); // Mmmm yum pi - } - this->soundBuffer.loadFromSamples(samples, sampleRate, 1, sampleRate); - - this->sound.setBuffer(this->soundBuffer); -} - -void SfmlSpeaker::play() { - this->sound.play(); -} - -void SfmlSpeaker::stop() { - this->sound.stop(); -} - diff --git a/src/sfml/emulator/SfmlSpeaker.h b/src/sfml/emulator/SfmlSpeaker.h deleted file mode 100644 index 83888d8..0000000 --- a/src/sfml/emulator/SfmlSpeaker.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef INC_8CHOCCHIP_SFMLSPEAKER_H -#define INC_8CHOCCHIP_SFMLSPEAKER_H - -#include "SFML/Audio.hpp" - -#include "../../emulator/Speaker.h" - -class SfmlSpeaker : public Speaker { -private: - sf::SoundBuffer soundBuffer; - sf::Sound sound; -public: - SfmlSpeaker(); - - void play() override; - void stop() override; -}; - -#endif // INC_8CHOCCHIP_SFMLSPEAKER_H diff --git a/src/sfml/ui/TextButton.cpp b/src/sfml/ui/TextButton.cpp deleted file mode 100644 index 7c56856..0000000 --- a/src/sfml/ui/TextButton.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "TextButton.h" - -TextButton::TextButton(float x, float y, float width, float height, const std::string& buttonText, sf::Font* font) { - this->button.setSize(sf::Vector2f(width, height)); - this->button.setPosition(sf::Vector2f(x, y)); - - this->originalPosition = this->button.getPosition(); - this->originalSize = this->button.getSize(); - - this->text.setFont(*font); - this->text.setString(buttonText); - this->text.setCharacterSize(20); - this->text.setFillColor(sf::Color::Black); - this->text.setPosition(x + width / 2 - this->text.getGlobalBounds().width / 2, y + height / 2 - this->text.getGlobalBounds().height / 2); - - this->idleColor = sf::Color(192, 192, 192); - this->hoverColor = sf::Color(128, 128, 128); - this->activeColor = sf::Color(64, 64, 64); - - this->button.setFillColor(this->idleColor); - - this->isPressed = false; - this->isHovered = false; -} - -void TextButton::updateSize(const sf::Vector2u originalSize, const sf::Vector2u updatedSize) { - this->button.setSize(sf::Vector2f(this->originalSize.x / originalSize.x * updatedSize.x, this->originalSize.y / originalSize.y * updatedSize.y)); - this->button.setPosition(this->originalPosition.x / originalSize.x * updatedSize.x, this->originalPosition.y / originalSize.y * updatedSize.y); - - this->text.setPosition(this->button.getPosition().x + this->button.getSize().x / 2 - this->text.getGlobalBounds().width / 2, this->button.getPosition().y + this->button.getSize().y / 2 - this->text.getGlobalBounds().height / 2); -} - -void TextButton::update(InputHandler* inputHandler, sf::Vector2i pos) { - this->lastPressed = this->isPressed; - this->isHovered = this->button.getGlobalBounds().contains(pos.x, pos.y); - - if (this->isHovered && inputHandler->isJustClicked(sf::Mouse::Left)) { - this->isPressed = true; - updateColour(this->activeColor); - } else if (this->isHovered && inputHandler->isPressed(sf::Keyboard::Key::LShift)) { - updateColour( sf::Color(255, 0, 0)); - } else if (this->isHovered) { - updateColour(this->hoverColor); - } else { - this->isPressed = false; - updateColour(this->idleColor); - } -} - -void TextButton::updateColour(const sf::Color color) { - if (this->color == color) { - return; - } - - this->button.setFillColor(color); -} - -void TextButton::draw(sf::RenderWindow &window) const { - window.draw(this->button); - window.draw(this->text); -} - -bool TextButton::isClicked() const { - return this->isPressed; -} - -bool TextButton::isJustClicked() const { - return !this->lastPressed && this->isPressed; -} \ No newline at end of file diff --git a/src/sfml/ui/TextButton.h b/src/sfml/ui/TextButton.h deleted file mode 100644 index 7e3491a..0000000 --- a/src/sfml/ui/TextButton.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef TEXTBUTTON_H -#define TEXTBUTTON_H - -#include "SFML/Graphics.hpp" - -#include "../InputHandler.h" - -class TextButton { -private: - sf::RectangleShape button; - sf::Vector2f originalSize; - sf::Vector2f originalPosition; - sf::Text text; - sf::Font* font{}; - sf::Color color; - sf::Color idleColor; - sf::Color hoverColor; - sf::Color activeColor; - bool isPressed; - bool lastPressed{}; - bool isHovered; - -public: - TextButton(float x, float y, float width, float height, const std::string& buttonText, sf::Font *font); - - void updateSize(sf::Vector2u originalSize, sf::Vector2u updatedSize); - - void update(InputHandler* inputHandler, sf::Vector2i pos); - - void draw(sf::RenderWindow& window) const; - - bool isClicked() const; - - bool isJustClicked() const; - - void updateColour(sf::Color color); -}; - - - -#endif //TEXTBUTTON_H