diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..99fd9211 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,21 @@ +name: Build + +on: [pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + submodules: 'recursive' + + - name: Build Examples + uses: espressif/esp-idf-ci-action@v1 + with: + esp_idf_version: release-v5.2 + target: esp32s3 + path: '.' diff --git a/.github/workflows/package_main.yml b/.github/workflows/package_main.yml new file mode 100644 index 00000000..2a4dc59f --- /dev/null +++ b/.github/workflows/package_main.yml @@ -0,0 +1,46 @@ +name: Build and Package Main + +on: + push: + branches: [main] + release: + types: [published] + +jobs: + build: + + runs-on: ubuntu-latest + continue-on-error: false + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + submodules: 'recursive' + + - name: Build Main Code + uses: espressif/esp-idf-ci-action@v1 + with: + esp_idf_version: release-v5.2 + target: esp32s3 + path: '.' + command: './patches.sh && idf.py build' + + - name: Upload Build Outputs + uses: actions/upload-artifact@v3 + with: + name: build-artifacts + path: build/bootloader/bootloader.bin + path: build/partition_table/partition-table.bin + path: build/esp-box-emu.bin + + - name: Attach files to release + uses: softprops/action-gh-release@v1 + if: ${{ github.event.release && github.event.action == 'published' }} + with: + files: | + build/esp-box-emu.bin + build/bootloader/bootloader.bin + build/partition_table/partition-table.bin + build/flash_args + diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml new file mode 100644 index 00000000..6bd7c9b3 --- /dev/null +++ b/.github/workflows/static_analysis.yml @@ -0,0 +1,25 @@ +name: Static analysis + +on: [pull_request] + +jobs: + static_analysis: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + submodules: 'recursive' + + - name: Run static analysis + uses: esp-cpp/StaticAnalysis@master + with: + # Do not build the project and do not use cmake to generate compile_commands.json + use_cmake: false + + # Use the 5.2 release version since it's what we build with + esp_idf_version: release/v5.2 + + # (Optional) cppcheck args + cppcheck_args: -i$GITHUB_WORKSPACE/lib -i$GITHUB_WORKSPACE/components/gbc/gnuboy -i$GITHUB_WORKSPACE/components/nes/nofrendo -i$GITHUB_WORKSPACE/components/gui/generated -i$GITHUB_WORKSPACE/components/menu/generated -i$GITHUB_WORKSPACE/components/jpegdec -i$GITHUB_WORKSPACE/components/codec -i$GITHUB_WORKSPACE/components/espp --force --enable=all --inline-suppr --inconclusive --platform=mips32 --suppressions-list=$GITHUB_WORKSPACE/suppressions.txt diff --git a/.gitmodules b/.gitmodules index 1656da26..eb2e7f85 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "components/jpegdec"] path = components/jpegdec url = git@github.com:bitbank2/JPEGDEC -[submodule "components/jpegenc"] - path = components/jpegenc - url = git@github.com:esp-cpp/JPEGENC diff --git a/components/box-emu-hal/src/i2s_audio.cpp b/components/box-emu-hal/src/i2s_audio.cpp index 888fc9ce..c7f226e2 100644 --- a/components/box-emu-hal/src/i2s_audio.cpp +++ b/components/box-emu-hal/src/i2s_audio.cpp @@ -79,9 +79,9 @@ int get_audio_volume() { static esp_err_t i2s_driver_init(void) { - printf("initializing i2s driver...\n"); + fmt::print("initializing i2s driver...\n"); auto ret_val = ESP_OK; - printf("Using newer I2S standard\n"); + fmt::print("Using newer I2S standard\n"); i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port, I2S_ROLE_MASTER); chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle)); @@ -114,7 +114,7 @@ static esp_err_t i2s_driver_init(void) // es7210 is for audio input codec static esp_err_t es7210_init_default(void) { - printf("initializing es7210 codec...\n"); + fmt::print("initializing es7210 codec...\n"); esp_err_t ret_val = ESP_OK; audio_hal_codec_config_t cfg; memset(&cfg, 0, sizeof(cfg)); @@ -131,7 +131,7 @@ static esp_err_t es7210_init_default(void) ret_val |= es7210_adc_ctrl_state(cfg.codec_mode, AUDIO_HAL_CTRL_START); if (ESP_OK != ret_val) { - printf("Failed initialize codec\n"); + fmt::print("Failed initialize codec\n"); } return ret_val; @@ -140,7 +140,7 @@ static esp_err_t es7210_init_default(void) // es8311 is for audio output codec static esp_err_t es8311_init_default(void) { - printf("initializing es8311 codec...\n"); + fmt::print("initializing es8311 codec...\n"); esp_err_t ret_val = ESP_OK; audio_hal_codec_config_t cfg; memset(&cfg, 0, sizeof(cfg)); @@ -158,7 +158,7 @@ static esp_err_t es8311_init_default(void) ret_val |= es8311_codec_ctrl_state(cfg.codec_mode, AUDIO_HAL_CTRL_START); if (ESP_OK != ret_val) { - printf("Failed initialize codec\n"); + fmt::print("Failed initialize codec\n"); } return ret_val; @@ -212,10 +212,10 @@ static void init_mute_button(void) { .callback = [](auto &m, auto&cv) -> bool { static gpio_num_t io_num; if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { - // invert the state since these are active low switches - bool pressed = !gpio_get_level(io_num); // see if it's the mute button if (io_num == mute_pin) { + // invert the state since these are active low switches + bool pressed = !gpio_get_level(io_num); // NOTE: the MUTE is actually connected to a flip-flop which holds // state, so pressing it actually toggles the state that we see on // the ESP pin. Therefore, when we get an edge trigger, we should @@ -251,7 +251,7 @@ void audio_init() { /* Checko IO config result */ if (ESP_OK != bsp_io_config_state) { - printf("Failed initialize power control IO\n"); + fmt::print("Failed initialize power control IO\n"); } gpio_set_level(sound_power_pin, 1); @@ -282,9 +282,9 @@ void audio_play_frame(uint8_t *data, uint32_t num_bytes) { auto err = ESP_OK; err = i2s_channel_write(tx_handle, data, num_bytes, &bytes_written, 1000); if(num_bytes != bytes_written) { - printf("ERROR to write %ld != written %d\n", num_bytes, bytes_written); + fmt::print("ERROR to write {} != written {}\n", num_bytes, bytes_written); } if (err != ESP_OK) { - printf("ERROR writing i2s channel: %d, '%s'\n", err, esp_err_to_name(err)); + fmt::print("ERROR writing i2s channel: {}, '{}'\n", err, esp_err_to_name(err)); } } diff --git a/components/gbc/src/gameboy.cpp b/components/gbc/src/gameboy.cpp index bf929875..5a3bf060 100644 --- a/components/gbc/src/gameboy.cpp +++ b/components/gbc/src/gameboy.cpp @@ -310,7 +310,7 @@ void start_gameboy_tasks() { } std::vector get_gameboy_video_buffer() { - uint8_t* frame_buffer = get_frame_buffer0(); + const uint8_t* frame_buffer = get_frame_buffer0(); // copy the frame buffer to a new buffer auto width = GAMEBOY_SCREEN_WIDTH; auto height = GAMEBOY_SCREEN_HEIGHT; diff --git a/components/gui/include/gui.hpp b/components/gui/include/gui.hpp index 5c14673f..d357a57c 100644 --- a/components/gui/include/gui.hpp +++ b/components/gui/include/gui.hpp @@ -33,7 +33,7 @@ class Gui { espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; }; - Gui(const Config& config) + explicit Gui(const Config& config) : play_haptic_(config.play_haptic), set_waveform_(config.set_waveform), display_(config.display), @@ -64,7 +64,7 @@ class Gui { ready_to_play_ = new_state; } - bool ready_to_play() { + bool ready_to_play() const { return ready_to_play_; } @@ -84,7 +84,7 @@ class Gui { void add_rom(const RomInfo& rom); - std::optional get_selected_rom() { + std::optional get_selected_rom() const { if (focused_rom_ < 0 || focused_rom_ >= rom_infos_.size()) { return std::nullopt; } diff --git a/components/jpeg/CMakeLists.txt b/components/jpeg/CMakeLists.txt index 3d460704..4fdddb63 100644 --- a/components/jpeg/CMakeLists.txt +++ b/components/jpeg/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register( SRC_DIRS "src" INCLUDE_DIRS "include" - REQUIRES heap jpegdec format lvgl box-emu-hal) + REQUIRES "heap" "jpegdec" "format" "lvgl" "box-emu-hal") diff --git a/components/jpeg/include/jpeg.hpp b/components/jpeg/include/jpeg.hpp index 01df750a..3585add8 100644 --- a/components/jpeg/include/jpeg.hpp +++ b/components/jpeg/include/jpeg.hpp @@ -8,7 +8,7 @@ #include "spi_lcd.h" #include "format.hpp" -#include "jpegdec.h" +#include "JPEGDEC.h" class Jpeg { public: @@ -76,7 +76,7 @@ class Jpeg { imgfile_.open(filename, std::ios::binary | std::ios::ate); if (!imgfile_.is_open()) { fmt::print("Couldn't open {}\n", filename); - size = 0; + *size = 0; return; } // get size from current location (end) @@ -110,7 +110,7 @@ class Jpeg { auto ys = pDraw->y; auto ye = pDraw->y + height - 1; uint16_t *dst_buffer = (uint16_t*)decoded_data_; - uint16_t *src_buffer = (uint16_t*)pDraw->pPixels; + const uint16_t *src_buffer = (const uint16_t*)pDraw->pPixels; // two bytes per pixel for RGB565 auto num_bytes_per_row = width * 2; for (int y=ys; y<=ye; y++) { diff --git a/components/jpegenc b/components/jpegenc deleted file mode 160000 index 3db39f10..00000000 --- a/components/jpegenc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3db39f10edcfc0fed1fef286b6e54a0d7465fa72 diff --git a/components/menu/include/menu.hpp b/components/menu/include/menu.hpp index 0314856b..1ec836bd 100644 --- a/components/menu/include/menu.hpp +++ b/components/menu/include/menu.hpp @@ -32,7 +32,7 @@ class Menu { espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; }; - Menu(const Config& config) + explicit Menu(const Config& config) : display_(config.display), paused_image_path_(config.paused_image_path), action_callback_(config.action_callback), @@ -97,7 +97,7 @@ class Menu { void set_video_setting(VideoSetting setting); - bool is_paused() { return paused_; } + bool is_paused() const { return paused_; } void pause() { paused_ = true; lv_group_focus_freeze(group_, true); diff --git a/components/nes/src/nes.cpp b/components/nes/src/nes.cpp index 91bae685..0db9c35f 100644 --- a/components/nes/src/nes.cpp +++ b/components/nes/src/nes.cpp @@ -94,8 +94,8 @@ std::vector get_nes_video_buffer() { std::vector frame(NES_SCREEN_WIDTH * NES_VISIBLE_HEIGHT * 2); // the frame data for the NES is stored in frame_buffer0 as a 8 bit index into the palette // we need to convert this to a 16 bit RGB565 value - uint8_t *frame_buffer0 = get_frame_buffer0(); - uint16_t *palette = get_nes_palette(); + const uint8_t *frame_buffer0 = get_frame_buffer0(); + const uint16_t *palette = get_nes_palette(); for (int i = 0; i < NES_SCREEN_WIDTH * NES_VISIBLE_HEIGHT; i++) { uint8_t index = frame_buffer0[i]; uint16_t color = palette[index]; diff --git a/components/nes/src/video_audio.c b/components/nes/src/video_audio.c index 1682c86b..c555c01b 100644 --- a/components/nes/src/video_audio.c +++ b/components/nes/src/video_audio.c @@ -120,7 +120,7 @@ static void set_palette(rgb_t *pal); static void clear(uint8 color); static bitmap_t *lock_write(void); static void free_write(int num_dirties, rect_t *dirty_rects); -static void custom_blit(bitmap_t *bmp, int num_dirties, rect_t *dirty_rects); +static void custom_blit(const bitmap_t *bmp, int num_dirties, rect_t *dirty_rects); QueueHandle_t vidQueue; @@ -134,7 +134,7 @@ viddriver_t sdlDriver = clear, /* clear */ lock_write, /* lock_write */ free_write, /* free_write */ - custom_blit, /* custom_blit */ + (void (*)(bitmap_t *, int, rect_t *))custom_blit, /* custom_blit */ false /* invalidate flag */ }; @@ -149,7 +149,6 @@ void osd_set_video_scale(bool new_video_scale) { } void ili9341_write_frame_nes(const uint8_t* buffer, uint16_t* myPalette) { - short x, y; static const int x_offset = (320-256)/2; static const int y_offset = (240-224)/2; if (buffer == NULL) { @@ -163,11 +162,12 @@ void ili9341_write_frame_nes(const uint8_t* buffer, uint16_t* myPalette) { lcd_write_frame(0,0,320,240,NULL); } if (scale_video) { - uint8_t* framePtr = buffer; + const uint8_t* framePtr = buffer; static int buffer_index = 0; static const int LINE_COUNT = NUM_ROWS_IN_FRAME_BUFFER; float x_scale = 1.25f; float y_scale = 1.0f; + short x, y; for (y = 0; y < 240; y+= LINE_COUNT) { uint16_t* line_buffer = buffer_index ? (uint16_t*)get_vram1() : (uint16_t*)get_vram0(); buffer_index = buffer_index ? 0 : 1; @@ -186,9 +186,10 @@ void ili9341_write_frame_nes(const uint8_t* buffer, uint16_t* myPalette) { lcd_write_frame(0, y_offset+y, 320, num_lines_written, (uint8_t*)&line_buffer[0]); } } else { - uint8_t* framePtr = buffer; + const uint8_t* framePtr = buffer; static int buffer_index = 0; static const int LINE_COUNT = NUM_ROWS_IN_FRAME_BUFFER; + short x, y; for (y = 0; y < NES_GAME_HEIGHT; y+= LINE_COUNT) { uint16_t* line_buffer = buffer_index ? (uint16_t*)get_vram1() : (uint16_t*)get_vram0(); buffer_index = buffer_index ? 0 : 1; @@ -282,7 +283,7 @@ static void free_write(int num_dirties, rect_t *dirty_rects) bmp_destroy(&myBitmap); } -static void custom_blit(bitmap_t *bmp, int num_dirties, rect_t *dirty_rects) { +static void custom_blit(const bitmap_t *bmp, int num_dirties, rect_t *dirty_rects) { uint8_t *lcdfb = get_frame_buffer0(); if (bmp->line[0] != NULL) { @@ -447,10 +448,7 @@ int osd_init() { log_chain_logfunc(logprint); - if (osd_init_sound()) - { - abort(); - } + osd_init_sound(); vidQueue=xQueueCreate(1, sizeof(bitmap_t *)); xTaskCreatePinnedToCore(&videoTask, "videoTask", 6*1024, NULL, 20, NULL, 1); diff --git a/main/button_handlers.hpp b/main/button_handlers.hpp deleted file mode 100644 index 3d5267f9..00000000 --- a/main/button_handlers.hpp +++ /dev/null @@ -1,194 +0,0 @@ -#pragma once - -#include - -#include "format.hpp" - -#include "joypad_buttons.hpp" -#include "nes_lib/InputDevice.h" - -class Report { -public: - enum class Field { - TYPE, - LEFT_ANALOG_X, - LEFT_ANALOG_Y, - RIGHT_ANALOG_X, - RIGHT_ANALOG_Y, - BUTTON_CODE_1, - BUTTON_CODE_2, - UNKNOWN, - LEFT_ANALOG_TRIGGER, - RIGHT_ANALOG_TRIGGER, - }; - - enum class ButtonCode1 { - Y = 4, // left - B = 5, // down - A = 6, // right - X = 7, // up - }; - enum class ButtonCode2 { - L1 = 0, - R1 = 1, - L2 = 2, - R2 = 3, - SELECT = 4, - START = 5, - }; - - Report(const std::vector& data) { - left_stick_x = parse_analog(data[(int)Field::LEFT_ANALOG_X]); - left_stick_y = parse_analog(data[(int)Field::LEFT_ANALOG_Y]); - right_stick_x = parse_analog(data[(int)Field::RIGHT_ANALOG_X]); - right_stick_y = parse_analog(data[(int)Field::RIGHT_ANALOG_Y]); - - uint8_t button_code_1 = data[(int)Field::BUTTON_CODE_1]; - decode_dpad(button_code_1); - a = button_code_1 & (1 << (int)ButtonCode1::A); - b = button_code_1 & (1 << (int)ButtonCode1::B); - x = button_code_1 & (1 << (int)ButtonCode1::X); - y = button_code_1 & (1 << (int)ButtonCode1::Y); - - uint8_t button_code_2 = data[(int)Field::BUTTON_CODE_2]; - l1 = button_code_2 & (1 << (int)ButtonCode2::L1); - r1 = button_code_2 & (1 << (int)ButtonCode2::R1); - l2 = button_code_2 & (1 << (int)ButtonCode2::L2); - r2 = button_code_2 & (1 << (int)ButtonCode2::R2); - start = button_code_2 & (1 << (int)ButtonCode2::START); - select = button_code_2 & (1 << (int)ButtonCode2::SELECT); - - left_trigger = parse_analog(data[(int)Field::LEFT_ANALOG_TRIGGER], 0.0f, 255.0f); - right_trigger = parse_analog(data[(int)Field::RIGHT_ANALOG_TRIGGER], 0.0f, 255.0f); - } - - void set_joypad_state(InputDevice *joypad) { - joypad->externState[(int)JoypadButtons::A] = a; - joypad->externState[(int)JoypadButtons::B] = b; - joypad->externState[(int)JoypadButtons::Select] = select; - joypad->externState[(int)JoypadButtons::Start] = start; - joypad->externState[(int)JoypadButtons::Up] = dpad_up; - joypad->externState[(int)JoypadButtons::Down] = dpad_down; - joypad->externState[(int)JoypadButtons::Left] = dpad_left; - joypad->externState[(int)JoypadButtons::Right] = dpad_right; - } - - void decode_dpad(uint8_t value) { - dpad_up = dpad_down = dpad_left = dpad_right = false; - switch (value) { - case 0: - dpad_up = true; - break; - case 1: - dpad_up = true; - dpad_right = true; - break; - case 2: - dpad_right = true; - break; - case 3: - dpad_down = true; - dpad_right = true; - break; - case 4: - dpad_down = true; - break; - case 5: - dpad_down = true; - dpad_left = true; - break; - case 6: - dpad_left = true; - break; - case 7: - dpad_left = true; - dpad_up = true; - break; - case 8: - // nothing is pressed - break; - default: - break; - } - } - - static float parse_analog(uint8_t value, float center=127.0f, float range=127.0f) { - return ((float)value - center) / range; - } - - bool wants_to_quit() const { - return select && start; - } - -protected: - float left_stick_x; - float left_stick_y; - float right_stick_x; - float right_stick_y; - bool dpad_up; - bool dpad_down; - bool dpad_left; - bool dpad_right; - bool a; - bool b; - bool x; - bool y; - bool l1; - bool r1; - bool l2; - bool r2; - bool start; - bool select; - float left_trigger; - float right_trigger; -}; - -bool handle_input_report(const std::vector& report_data, InputDevice* joypad) { - if (report_data.size() != 10) { - fmt::print("Bad report size {}\n", report_data.size()); - return false; - } - Report report(report_data); - report.set_joypad_state(joypad); - return report.wants_to_quit(); -} - -bool string_to_input(InputDevice* joypad, const std::string& strdata) { - static JoypadButtons prev_button = JoypadButtons::NONE; - if (strdata.find("quit") != std::string::npos) { - fmt::print("QUITTING\n"); - return true; - } else if (strdata.find("start") != std::string::npos) { - fmt::print("start pressed\n"); - prev_button = JoypadButtons::Start; - } else if (strdata.find("select") != std::string::npos) { - fmt::print("select pressed\n"); - prev_button = JoypadButtons::Select; - } else if (strdata.find("clear") != std::string::npos) { - fmt::print("clearing button: {}\n", (int)prev_button); - joypad->externState[(int)prev_button] = false; - prev_button = JoypadButtons::NONE; - } else if (strdata.find("a") != std::string::npos) { - fmt::print("A pressed\n"); - prev_button = JoypadButtons::A; - } else if (strdata.find("b") != std::string::npos) { - fmt::print("B pressed\n"); - prev_button = JoypadButtons::B; - } else if (strdata.find("up") != std::string::npos) { - fmt::print("Up pressed\n"); - prev_button = JoypadButtons::Up; - } else if (strdata.find("down") != std::string::npos) { - fmt::print("Down pressed\n"); - prev_button = JoypadButtons::Down; - } else if (strdata.find("left") != std::string::npos) { - fmt::print("Left pressed\n"); - prev_button = JoypadButtons::Left; - } else if (strdata.find("right") != std::string::npos) { - fmt::print("Right pressed\n"); - prev_button = JoypadButtons::Right; - } - if (prev_button != JoypadButtons::NONE) { - joypad->externState[(int)prev_button] = true; - } - return false; -} diff --git a/main/cart.hpp b/main/cart.hpp index cea6b04e..de912ff3 100644 --- a/main/cart.hpp +++ b/main/cart.hpp @@ -39,6 +39,12 @@ class Cart { display_(config.display), logger_({.tag = "Cart", .level = config.verbosity}) { logger_.info("ctor"); + // clear the screen + espp::St7789::clear(0,0,320,240); + // copy the romdata + rom_size_bytes_ = copy_romdata_to_cart_partition(get_rom_filename()); + romdata_ = get_mmapped_romdata(); + // create the menu menu_ = std::make_unique(Menu::Config{ .display = display_, .paused_image_path = get_paused_image_path(), @@ -58,7 +64,6 @@ class Cart { virtual ~Cart() { logger_.info("Base dtor"); - deinit(); } std::string get_rom_filename() const { @@ -81,10 +86,10 @@ class Cart { std::filesystem::remove(paused_image_path, ec); } // copy the screenshot to the paused image - std::fstream screenshot(screenshot_path, std::ios::binary | std::ios::in); + std::fstream screenshot_file(screenshot_path, std::ios::binary | std::ios::in); std::fstream paused_image(paused_image_path, std::ios::binary | std::ios::out); - paused_image << screenshot.rdbuf(); - screenshot.close(); + paused_image << screenshot_file.rdbuf(); + screenshot_file.close(); paused_image.close(); } @@ -101,10 +106,10 @@ class Cart { } // copy the paused image to the screenshot std::fstream paused_image(paused_image_path, std::ios::binary | std::ios::in); - std::fstream screenshot(screenshot_path, std::ios::binary | std::ios::out); - screenshot << paused_image.rdbuf(); + std::fstream screenshot_file(screenshot_path, std::ios::binary | std::ios::out); + screenshot_file << paused_image.rdbuf(); paused_image.close(); - screenshot.close(); + screenshot_file.close(); } else { logger_.warn("paused image does not exist"); } @@ -147,19 +152,6 @@ class Cart { return true; } - virtual void init() { - logger_.info("Base init"); - espp::St7789::clear(0,0,320,240); - // copy the romdata - rom_size_bytes_ = copy_romdata_to_cart_partition(get_rom_filename()); - romdata_ = get_mmapped_romdata(); - handle_video_setting(); - } - - virtual void deinit() { - logger_.info("Base deinit"); - } - virtual bool run() { running_ = true; // handle touchpad so we can know if the user presses the menu @@ -229,7 +221,7 @@ class Cart { return ".sav"; } - virtual std::string get_screenshot_extension() const { + std::string get_screenshot_extension() const { return ".bin"; } @@ -278,7 +270,7 @@ class Cart { } } - std::string get_save_path(bool bypass_exist_check=false) { + std::string get_save_path(bool bypass_exist_check=false) const { namespace fs = std::filesystem; auto save_path = savedir_ + "/" + @@ -286,15 +278,12 @@ class Cart { fmt::format("_{}", menu_->get_selected_slot()) + get_save_extension(); if (bypass_exist_check || fs::exists(save_path)) { - logger_.info("found: {}", save_path); return save_path; - } else { - logger_.warn("Could not find {}", save_path); } return ""; } - std::string get_paused_image_path() { + std::string get_paused_image_path() const { namespace fs = std::filesystem; auto save_path = savedir_ + "/paused" + @@ -302,7 +291,7 @@ class Cart { return save_path; } - std::string get_screenshot_path(bool bypass_exist_check=false) { + std::string get_screenshot_path(bool bypass_exist_check=false) const { auto save_path = get_save_path(bypass_exist_check); if (!save_path.empty()) { return save_path + get_screenshot_extension(); diff --git a/main/gbc_cart.hpp b/main/gbc_cart.hpp index 2567e3de..1b1338ba 100644 --- a/main/gbc_cart.hpp +++ b/main/gbc_cart.hpp @@ -8,8 +8,9 @@ class GbcCart : public Cart { public: - GbcCart(const Cart::Config& config) + explicit GbcCart(const Cart::Config& config) : Cart(config) { + handle_video_setting(); init(); } @@ -17,6 +18,7 @@ class GbcCart : public Cart { deinit(); } + // cppcheck-suppress uselessOverride virtual void reset() override { Cart::reset(); #if defined(ENABLE_GBC) @@ -24,6 +26,7 @@ class GbcCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void load() override { Cart::load(); #if defined(ENABLE_GBC) @@ -31,6 +34,7 @@ class GbcCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void save() override { Cart::save(); #if defined(ENABLE_GBC) @@ -38,21 +42,21 @@ class GbcCart : public Cart { #endif } - virtual void init() override { - Cart::init(); + void init() { #if defined(ENABLE_GBC) init_gameboy(get_rom_filename(), romdata_, rom_size_bytes_); start_gameboy_tasks(); #endif } - virtual void deinit() override { + void deinit() { #if defined(ENABLE_GBC) stop_gameboy_tasks(); deinit_gameboy(); #endif } + // cppcheck-suppress uselessOverride virtual bool run() override { #if defined(ENABLE_GBC) run_gameboy_rom(); @@ -65,6 +69,7 @@ class GbcCart : public Cart { static constexpr size_t GAMEBOY_WIDTH = 160; static constexpr size_t GAMEBOY_HEIGHT = 144; + // cppcheck-suppress uselessOverride virtual void pre_menu() override { Cart::pre_menu(); #if defined(ENABLE_GBC) @@ -73,6 +78,7 @@ class GbcCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void post_menu() override { Cart::post_menu(); #if defined(ENABLE_GBC) @@ -92,6 +98,7 @@ class GbcCart : public Cart { return std::make_pair(GAMEBOY_WIDTH, GAMEBOY_HEIGHT); } + // cppcheck-suppress uselessOverride virtual std::vector get_video_buffer() const override { #if defined(ENABLE_GBC) return get_gameboy_video_buffer(); diff --git a/main/main.cpp b/main/main.cpp index b8d12a30..cc637535 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,8 +1,5 @@ #include "sdkconfig.h" -#include "FreeRTOS/FreeRTOS.h" -#include "FreeRTOS/queue.h" - #include #include #include diff --git a/main/nes_cart.hpp b/main/nes_cart.hpp index 7b52f962..ac7c2a35 100644 --- a/main/nes_cart.hpp +++ b/main/nes_cart.hpp @@ -8,8 +8,9 @@ class NesCart : public Cart { public: - NesCart(const Cart::Config& config) + explicit NesCart(const Cart::Config& config) : Cart(config) { + handle_video_setting(); init(); } @@ -17,6 +18,7 @@ class NesCart : public Cart { deinit(); } + // cppcheck-suppress uselessOverride virtual void reset() override { Cart::reset(); #if defined(ENABLE_NES) @@ -24,6 +26,7 @@ class NesCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void load() override { Cart::load(); #if defined(ENABLE_NES) @@ -31,6 +34,7 @@ class NesCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void save() override { Cart::save(); #if defined(ENABLE_NES) @@ -38,21 +42,21 @@ class NesCart : public Cart { #endif } - virtual void init() override { - Cart::init(); + void init() { #if defined(ENABLE_NES) init_nes(get_rom_filename(), romdata_, rom_size_bytes_); start_nes_tasks(); #endif } - virtual void deinit() override { + void deinit() { #if defined(ENABLE_NES) stop_nes_tasks(); deinit_nes(); #endif } + // cppcheck-suppress uselessOverride virtual bool run() override { #if defined(ENABLE_NES) run_nes_rom(); @@ -64,6 +68,7 @@ class NesCart : public Cart { static constexpr size_t NES_WIDTH = 256; static constexpr size_t NES_HEIGHT = 240; + // cppcheck-suppress uselessOverride virtual void pre_menu() override { Cart::pre_menu(); #if defined(ENABLE_NES) @@ -72,6 +77,7 @@ class NesCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void post_menu() override { Cart::post_menu(); #if defined(ENABLE_NES) @@ -84,6 +90,7 @@ class NesCart : public Cart { return std::make_pair(NES_WIDTH, NES_HEIGHT); } + // cppcheck-suppress uselessOverride virtual std::vector get_video_buffer() const override { #if defined(ENABLE_NES) return get_nes_video_buffer(); diff --git a/main/sms_cart.hpp b/main/sms_cart.hpp index e81b8db8..03ddf110 100644 --- a/main/sms_cart.hpp +++ b/main/sms_cart.hpp @@ -8,8 +8,9 @@ class SmsCart : public Cart { public: - SmsCart(const Cart::Config& config) + explicit SmsCart(const Cart::Config& config) : Cart(config) { + handle_video_setting(); init(); } @@ -18,6 +19,7 @@ class SmsCart : public Cart { deinit(); } + // cppcheck-suppress uselessOverride virtual void reset() override { Cart::reset(); #if defined(ENABLE_SMS) @@ -25,6 +27,7 @@ class SmsCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void load() override { Cart::load(); #if defined(ENABLE_SMS) @@ -32,6 +35,7 @@ class SmsCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void save() override { Cart::save(); #if defined(ENABLE_SMS) @@ -39,8 +43,7 @@ class SmsCart : public Cart { #endif } - virtual void init() override { - Cart::init(); + void init() { #if defined(ENABLE_SMS) switch (info_.platform) { case Emulator::SEGA_MASTER_SYSTEM: @@ -59,14 +62,14 @@ class SmsCart : public Cart { #endif } - virtual void deinit() override { - logger_.info("deinit()"); + void deinit() { #if defined(ENABLE_SMS) stop_sms_tasks(); deinit_sms(); #endif } + // cppcheck-suppress uselessOverride virtual bool run() override { #if defined(ENABLE_SMS) run_sms_rom(); @@ -79,6 +82,7 @@ class SmsCart : public Cart { static constexpr size_t SMS_WIDTH = 256; static constexpr size_t SMS_HEIGHT = 192; + // cppcheck-suppress uselessOverride virtual void pre_menu() override { Cart::pre_menu(); #if defined(ENABLE_SMS) @@ -87,6 +91,7 @@ class SmsCart : public Cart { #endif } + // cppcheck-suppress uselessOverride virtual void post_menu() override { Cart::post_menu(); #if defined(ENABLE_SMS) @@ -106,6 +111,7 @@ class SmsCart : public Cart { return std::make_pair(SMS_WIDTH, SMS_HEIGHT); } + // cppcheck-suppress uselessOverride virtual std::vector get_video_buffer() const override { #if defined(ENABLE_SMS) return get_sms_video_buffer(); diff --git a/patches.sh b/patches.sh new file mode 100755 index 00000000..301f855b --- /dev/null +++ b/patches.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +if [[ -z "${IDF_PATH}" ]]; then + echo "IDF_PATH is not set, cannot find path to esp-idf. Please set it (using get_idf) and re-run this script." + exit -1 +else + echo "Applying patches to esp-idf in '${IDF_PATH}'" +fi + +lodestone_dir=$(pwd) +patches=($(find patches -type f)) +cd "${IDF_PATH}" +for patch in "${patches[@]}"; do + echo "Applying patch: ${patch}" + git apply ${lodestone_dir}/${patch} +done + +cd ${lodestone_dir} \ No newline at end of file diff --git a/patches/spi_master_heap_corruption_trace.patch b/patches/spi_master_heap_corruption_trace.patch new file mode 100644 index 00000000..c5a7e8e7 --- /dev/null +++ b/patches/spi_master_heap_corruption_trace.patch @@ -0,0 +1,22 @@ +diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c +index b29f55e9c9..277b864028 100644 +--- a/components/esp_driver_spi/src/gpspi/spi_master.c ++++ b/components/esp_driver_spi/src/gpspi/spi_master.c +@@ -870,7 +870,7 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf) + spi_transaction_t *trans_desc = trans_buf->trans; + if ((void *)trans_buf->buffer_to_send != &trans_desc->tx_data[0] && + trans_buf->buffer_to_send != trans_desc->tx_buffer) { +- free((void *)trans_buf->buffer_to_send); //force free, ignore const ++ // free((void *)trans_buf->buffer_to_send); //force free, ignore const + } + // copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one. + if (trans_buf->buffer_to_rcv && (void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] && trans_buf->buffer_to_rcv != trans_desc->rx_buffer) { // NOLINT(clang-analyzer-unix.Malloc) +@@ -879,7 +879,7 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf) + } else { + memcpy(trans_desc->rx_buffer, trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8); + } +- free(trans_buf->buffer_to_rcv); ++ // free(trans_buf->buffer_to_rcv); + } + } + diff --git a/suppressions.txt b/suppressions.txt new file mode 100644 index 00000000..a0709c22 --- /dev/null +++ b/suppressions.txt @@ -0,0 +1,12 @@ +// category of errors to suppress, e.g. unusedFunction +missingInclude +missingIncludeSystem +unusedFunction +unusedStructMember +functionStatic +cstyleCast + +// Specific suppressions of the form: +// [error id]:[filename]:[line] +*:lib/* +*:components/espp/*