diff --git a/.gitignore b/.gitignore index d520f9bc..63817d7d 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,6 @@ build/ sdkconfig sdkconfig.old .DS_Store -squareline/backup +**/squareline/backup flash_data/ *-backups/ diff --git a/.gitmodules b/.gitmodules index eb2e7f85..1656da26 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [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/CMakeLists.txt b/CMakeLists.txt index 8f977d3a..a29d9409 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,19 +10,19 @@ set(EXTRA_COMPONENT_DIRS ) ### NES ### -set(NES_COMPONENTS "nofrendo nofrendo-esp32") +set(NES_COMPONENTS "nes") ### GBC ### -set(GBC_COMPONENTS "gnuboy") +set(GBC_COMPONENTS "gbc") ### SMS ### -# set(SMS_COMPONENTS "smsplus") +# set(SMS_COMPONENTS "sms") add_compile_definitions(BOARD_HAS_PSRAM) set( COMPONENTS - "main esptool_py fatfs esp_littlefs esp_lcd esp_psram task format display display_drivers monitor esp-idf-cxx ${NES_COMPONENTS} ${GBC_COMPONENTS} ${SMS_COMPONENTS} box-emu-hal gui" + "main esptool_py esp_lcd esp_psram task format display display_drivers monitor esp-idf-cxx ${NES_COMPONENTS} ${GBC_COMPONENTS} ${SMS_COMPONENTS} box-emu-hal gui menu" CACHE STRING "List of components to include" ) diff --git a/boxart/batman_the_animated_series.jpg b/boxart/batman_the_animated_series.jpg new file mode 100644 index 00000000..8c538527 Binary files /dev/null and b/boxart/batman_the_animated_series.jpg differ diff --git a/boxart/duck_tales.jpg b/boxart/duck_tales.jpg new file mode 100644 index 00000000..bcd291c0 Binary files /dev/null and b/boxart/duck_tales.jpg differ diff --git a/boxart/final_fantasy.jpg b/boxart/final_fantasy.jpg new file mode 100644 index 00000000..e11f6c82 Binary files /dev/null and b/boxart/final_fantasy.jpg differ diff --git a/boxart/final_fantasy_adventure.jpg b/boxart/final_fantasy_adventure.jpg new file mode 100644 index 00000000..babec991 Binary files /dev/null and b/boxart/final_fantasy_adventure.jpg differ diff --git a/boxart/final_fantasy_ii.jpg b/boxart/final_fantasy_ii.jpg new file mode 100644 index 00000000..23a316ea Binary files /dev/null and b/boxart/final_fantasy_ii.jpg differ diff --git a/boxart/final_fantasy_iii.jpg b/boxart/final_fantasy_iii.jpg new file mode 100644 index 00000000..833b075b Binary files /dev/null and b/boxart/final_fantasy_iii.jpg differ diff --git a/boxart/harvest_moon.jpg b/boxart/harvest_moon.jpg new file mode 100644 index 00000000..ce962752 Binary files /dev/null and b/boxart/harvest_moon.jpg differ diff --git a/boxart/harvest_moon_gbc.jpg b/boxart/harvest_moon_gbc.jpg new file mode 100644 index 00000000..f747df1f Binary files /dev/null and b/boxart/harvest_moon_gbc.jpg differ diff --git a/boxart/mario_golf.jpg b/boxart/mario_golf.jpg new file mode 100644 index 00000000..27c3adcb Binary files /dev/null and b/boxart/mario_golf.jpg differ diff --git a/boxart/mario_open_golf.jpg b/boxart/mario_open_golf.jpg new file mode 100644 index 00000000..1eff197e Binary files /dev/null and b/boxart/mario_open_golf.jpg differ diff --git a/boxart/mario_tennis.jpg b/boxart/mario_tennis.jpg new file mode 100644 index 00000000..e0503825 Binary files /dev/null and b/boxart/mario_tennis.jpg differ diff --git a/boxart/metal_gear.jpg b/boxart/metal_gear.jpg new file mode 100644 index 00000000..b023fdd5 Binary files /dev/null and b/boxart/metal_gear.jpg differ diff --git a/boxart/metal_gear_solid.jpg b/boxart/metal_gear_solid.jpg new file mode 100644 index 00000000..b127b4ec Binary files /dev/null and b/boxart/metal_gear_solid.jpg differ diff --git a/boxart/metroid_2_return_of_samus.jpg b/boxart/metroid_2_return_of_samus.jpg new file mode 100644 index 00000000..ecc125f7 Binary files /dev/null and b/boxart/metroid_2_return_of_samus.jpg differ diff --git a/boxart/source/batman_the_animated_series.jpg b/boxart/source/batman_the_animated_series.jpg new file mode 100644 index 00000000..868df1ed Binary files /dev/null and b/boxart/source/batman_the_animated_series.jpg differ diff --git a/boxart/source/duck_tales.jpg b/boxart/source/duck_tales.jpg new file mode 100644 index 00000000..d5262dc6 Binary files /dev/null and b/boxart/source/duck_tales.jpg differ diff --git a/boxart/source/final_fantasy.jpg b/boxart/source/final_fantasy.jpg new file mode 100644 index 00000000..aa62f2fe Binary files /dev/null and b/boxart/source/final_fantasy.jpg differ diff --git a/boxart/source/final_fantasy_adventure.jpg b/boxart/source/final_fantasy_adventure.jpg new file mode 100644 index 00000000..13ecc84e Binary files /dev/null and b/boxart/source/final_fantasy_adventure.jpg differ diff --git a/boxart/source/final_fantasy_ii.jpg b/boxart/source/final_fantasy_ii.jpg new file mode 100644 index 00000000..b8caf100 Binary files /dev/null and b/boxart/source/final_fantasy_ii.jpg differ diff --git a/boxart/source/final_fantasy_iii.jpg b/boxart/source/final_fantasy_iii.jpg new file mode 100644 index 00000000..2cb26cc9 Binary files /dev/null and b/boxart/source/final_fantasy_iii.jpg differ diff --git a/boxart/source/harvest_moon.jpg b/boxart/source/harvest_moon.jpg new file mode 100644 index 00000000..38fcb5dd Binary files /dev/null and b/boxart/source/harvest_moon.jpg differ diff --git a/boxart/source/harvest_moon_gbc.jpg b/boxart/source/harvest_moon_gbc.jpg new file mode 100644 index 00000000..2d6b300c Binary files /dev/null and b/boxart/source/harvest_moon_gbc.jpg differ diff --git a/boxart/source/mario_golf.jpg b/boxart/source/mario_golf.jpg new file mode 100644 index 00000000..b29469e6 Binary files /dev/null and b/boxart/source/mario_golf.jpg differ diff --git a/boxart/source/mario_open_golf.jpg b/boxart/source/mario_open_golf.jpg new file mode 100644 index 00000000..2e68b813 Binary files /dev/null and b/boxart/source/mario_open_golf.jpg differ diff --git a/boxart/source/mario_tennis.jpg b/boxart/source/mario_tennis.jpg new file mode 100644 index 00000000..664a88e6 Binary files /dev/null and b/boxart/source/mario_tennis.jpg differ diff --git a/boxart/source/metal_gear.jpg b/boxart/source/metal_gear.jpg new file mode 100644 index 00000000..a5f9411b Binary files /dev/null and b/boxart/source/metal_gear.jpg differ diff --git a/boxart/source/metal_gear_solid.jpg b/boxart/source/metal_gear_solid.jpg new file mode 100644 index 00000000..eca5c268 Binary files /dev/null and b/boxart/source/metal_gear_solid.jpg differ diff --git a/boxart/source/metroid_2_return_of_samus.jpg b/boxart/source/metroid_2_return_of_samus.jpg new file mode 100644 index 00000000..ed4cb341 Binary files /dev/null and b/boxart/source/metroid_2_return_of_samus.jpg differ diff --git a/boxart/source/tloz_oracle_ages.jpg b/boxart/source/tloz_oracle_ages.jpg index 6a0bc435..0c8bfc44 100755 Binary files a/boxart/source/tloz_oracle_ages.jpg and b/boxart/source/tloz_oracle_ages.jpg differ diff --git a/boxart/source/tloz_oracle_seasons.jpg b/boxart/source/tloz_oracle_seasons.jpg index db08ae8e..8470a541 100755 Binary files a/boxart/source/tloz_oracle_seasons.jpg and b/boxart/source/tloz_oracle_seasons.jpg differ diff --git a/boxart/tloz_oracle_ages.jpg b/boxart/tloz_oracle_ages.jpg index 1370bd0d..8f786e50 100644 Binary files a/boxart/tloz_oracle_ages.jpg and b/boxart/tloz_oracle_ages.jpg differ diff --git a/boxart/tloz_oracle_seasons.jpg b/boxart/tloz_oracle_seasons.jpg index 6c1de0b2..91616c5f 100644 Binary files a/boxart/tloz_oracle_seasons.jpg and b/boxart/tloz_oracle_seasons.jpg differ diff --git a/components/ads1x15/CMakeLists.txt b/components/ads1x15/CMakeLists.txt deleted file mode 100644 index 8fff0ac1..00000000 --- a/components/ads1x15/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - INCLUDE_DIRS "include" - SRC_DIRS "src" - REQUIRES "logger" - ) diff --git a/components/ads1x15/include/ads1x15.hpp b/components/ads1x15/include/ads1x15.hpp deleted file mode 100644 index 935ba076..00000000 --- a/components/ads1x15/include/ads1x15.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include - -#include "FreeRTOS/FreeRTOS.h" -#include "FreeRTOS/task.h" - -#include "logger.hpp" - -class Ads1x15 { -public: - static constexpr uint8_t ADDRESS = (0x48); ///< 1001 000 (ADDR = GND) - - typedef std::function write_fn; - typedef std::function read_fn; - - enum class Gain { - TWOTHIRDS = 0x0000, ///< +/-6.144V range = Gain 2/3 - ONE = 0x0200, ///< +/-4.096V range = Gain 1 - TWO = 0x0400, ///< +/-2.048V range = Gain 2 (default) - FOUR = 0x0600, ///< +/-1.024V range = Gain 4 - EIGHT = 0x0800, ///< +/-0.512V range = Gain 8 - SIXTEEN = 0x0A00, ///< +/-0.256V range = Gain 16 - }; - - enum class Ads1015Rate : uint16_t { - SPS128 = 0x0000, ///< 128 samples per second - SPS250 = 0x0020, ///< 250 samples per second - SPS490 = 0x0040, ///< 490 samples per second - SPS920 = 0x0060, ///< 920 samples per second - SPS1600 = 0x0080, ///< 1600 samples per second (default) - SPS2400 = 0x00A0, ///< 2400 samples per second - SPS3300 = 0x00C0, ///< 3300 samples per second - }; - - enum class Ads1115Rate : uint16_t { - SPS8 = 0x0000, ///< 8 samples per second - SPS16 = 0x0020, ///< 16 samples per second - SPS32 = 0x0040, ///< 32 samples per second - SPS64 = 0x0060, ///< 64 samples per second - SPS128 = 0x0080, ///< 128 samples per second (default) - SPS250 = 0x00A0, ///< 250 samples per second - SPS475 = 0x00C0, ///< 475 samples per second - SPS860 = 0x00E0, ///< 860 samples per second - }; - - struct Ads1015Config { - write_fn write; - read_fn read; - Gain gain{Gain::TWOTHIRDS}; - Ads1015Rate sample_rate{Ads1015Rate::SPS1600}; - espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; - }; - - struct Ads1115Config { - write_fn write; - read_fn read; - Gain gain{Gain::TWOTHIRDS}; - Ads1115Rate sample_rate{Ads1115Rate::SPS128}; - espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; - }; - - Ads1x15(const Ads1015Config& config) - : gain_(config.gain), - ads1015rate_(config.sample_rate), - bit_shift_(4), write_(config.write), read_(config.read), - logger_({.tag="Ads1015", .level = config.log_level}){ - } - - Ads1x15(const Ads1115Config& config) - : gain_(config.gain), - ads1115rate_(config.sample_rate), - bit_shift_(0), write_(config.write), read_(config.read), - logger_({.tag="Ads1115", .level = config.log_level}){ - } - - float sample_mv(int channel) { - return raw_to_mv(sample_raw(channel)); - } - -protected: - int16_t sample_raw(int channel); - - bool conversion_complete(); - - float raw_to_mv(int16_t raw) { - // see data sheet Table 3 - float fsRange; - switch (gain_) { - case Gain::TWOTHIRDS: - fsRange = 6144.0f; - break; - case Gain::ONE: - fsRange = 4096.0f; - break; - case Gain::TWO: - fsRange = 2048.0f; - break; - case Gain::FOUR: - fsRange = 1024.0f; - break; - case Gain::EIGHT: - fsRange = 512.0f; - break; - case Gain::SIXTEEN: - fsRange = 256.0f; - break; - default: - fsRange = 0.0f; - } - return raw * (fsRange / (32768 >> bit_shift_)); - } - - enum class Register : uint8_t { - POINTER_CONVERT = 0x00, ///< Conversion - POINTER_CONFIG = 0x01, ///< Configuration - POINTER_LOWTHRESH = 0x02, ///< Low Threshold - POINTER_HITHRESH = 0x03 ///< High Threshold - }; - - Gain gain_; - union { - Ads1015Rate ads1015rate_; - Ads1115Rate ads1115rate_; - uint16_t rate_; - }; - int bit_shift_; - write_fn write_; - read_fn read_; - espp::Logger logger_; -}; diff --git a/components/ads1x15/src/ads1x15.cpp b/components/ads1x15/src/ads1x15.cpp deleted file mode 100644 index ebf4f25b..00000000 --- a/components/ads1x15/src/ads1x15.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "ads1x15.hpp" - -static constexpr uint16_t REG_CONFIG_OS_SINGLE = - (0x8000); -static constexpr uint16_t REG_CONFIG_OS_BUSY = - (0x0000); ///< Read: Bit = 0 when conversion is in progress -static constexpr uint16_t REG_CONFIG_OS_NOTBUSY = - (0x8000); ///< Read: Bit = 1 when device is not performing a conversion - -static constexpr uint16_t REG_CONFIG_MUX_DIFF_0_1 = - (0x0000); ///< Differential P = AIN0, N = AIN1 (default) -static constexpr uint16_t REG_CONFIG_MUX_DIFF_0_3 = - (0x1000); ///< Differential P = AIN0, N = AIN3 -static constexpr uint16_t REG_CONFIG_MUX_DIFF_1_3 = - (0x2000); ///< Differential P = AIN1, N = AIN3 -static constexpr uint16_t REG_CONFIG_MUX_DIFF_2_3 = - (0x3000); ///< Differential P = AIN2, N = AIN3 -static constexpr uint16_t REG_CONFIG_MUX_SINGLE_0 = (0x4000); ///< Single-ended AIN0 -static constexpr uint16_t REG_CONFIG_MUX_SINGLE_1 = (0x5000); ///< Single-ended AIN1 -static constexpr uint16_t REG_CONFIG_MUX_SINGLE_2 = (0x6000); ///< Single-ended AIN2 -static constexpr uint16_t REG_CONFIG_MUX_SINGLE_3 = (0x7000); ///< Single-ended AIN3 - -static constexpr uint16_t MUX_BY_CHANNEL[] = { - REG_CONFIG_MUX_SINGLE_0, ///< Single-ended AIN0 - REG_CONFIG_MUX_SINGLE_1, ///< Single-ended AIN1 - REG_CONFIG_MUX_SINGLE_2, ///< Single-ended AIN2 - REG_CONFIG_MUX_SINGLE_3 ///< Single-ended AIN3 -}; ///< MUX config by channel - -static constexpr uint16_t REG_CONFIG_MODE_CONTIN = (0x0000); ///< Continuous conversion mode -static constexpr uint16_t REG_CONFIG_MODE_SINGLE = - (0x0100); ///< Power-down single-shot mode (default) - -static constexpr uint16_t REG_CONFIG_CMODE_TRAD = - (0x0000); ///< Traditional comparator with hysteresis (default) -static constexpr uint16_t REG_CONFIG_CMODE_WINDOW = (0x0010); ///< Window comparator - -static constexpr uint16_t REG_CONFIG_CPOL_ACTVLOW = - (0x0000); ///< ALERT/RDY pin is low when active (default) -static constexpr uint16_t REG_CONFIG_CPOL_ACTVHI = - (0x0008); ///< ALERT/RDY pin is high when active - -static constexpr uint16_t REG_CONFIG_CLAT_NONLAT = - (0x0000); ///< Non-latching comparator (default) -static constexpr uint16_t REG_CONFIG_CLAT_LATCH = (0x0004); ///< Latching comparator - -static constexpr uint16_t REG_CONFIG_CQUE_1CONV = - (0x0000); ///< Assert ALERT/RDY after one conversions -static constexpr uint16_t REG_CONFIG_CQUE_2CONV = - (0x0001); ///< Assert ALERT/RDY after two conversions -static constexpr uint16_t REG_CONFIG_CQUE_4CONV = - (0x0002); ///< Assert ALERT/RDY after four conversions -static constexpr uint16_t REG_CONFIG_CQUE_NONE = - (0x0003); ///< Disable the comparator and put ALERT/RDY in high state (default) - -int16_t Ads1x15::sample_raw(int channel) { - if (!write_ || !read_) { - logger_.error("Write / read functions not properly configured, cannot sample!"); - return 0; - } - // Start with default values - uint16_t config = - REG_CONFIG_CQUE_1CONV | // Comparator enabled and asserts on 1 - // match - REG_CONFIG_CLAT_NONLAT | // non-latching (default val) - REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val) - REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val) - REG_CONFIG_MODE_SINGLE; // Single conversion mode - // Set PGA/voltage range - config |= (uint16_t)gain_; - // Set data rate - config |= rate_; - config |= MUX_BY_CHANNEL[channel]; - // Set 'start single-conversion' bit - config |= REG_CONFIG_OS_SINGLE; - // configure to read from mux 0 - logger_.debug("configuring conversion for channel {}", channel); - write_((uint8_t)Register::POINTER_CONFIG, config); - write_((uint8_t)Register::POINTER_HITHRESH, 0x8000); - write_((uint8_t)Register::POINTER_LOWTHRESH, 0x0000); - // wait for conversion complete - logger_.debug("waiting for conversion complete..."); - while (!conversion_complete()) { - vTaskDelay(1); - } - logger_.debug("reading conversion result for channel {}", channel); - uint16_t val = read_((uint8_t)Register::POINTER_CONVERT) >> bit_shift_; - if (bit_shift_ > 0) { - if (val > 0x07FF) { - // negative number - extend the sign to the 16th bit - val |= 0xF000; - } - } - return (int16_t)val; -} - -bool Ads1x15::conversion_complete() { - return (read_((uint8_t)Register::POINTER_CONFIG) & 0x8000) != 0; -} diff --git a/components/box-emu-hal/CMakeLists.txt b/components/box-emu-hal/CMakeLists.txt index 69c83b5a..6d16d5ab 100644 --- a/components/box-emu-hal/CMakeLists.txt +++ b/components/box-emu-hal/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register( INCLUDE_DIRS "include" SRC_DIRS "src" - REQUIRES "driver" "heap" "esp_lcd" "esp_psram" "spi_flash" "nvs_flash" "codec" "display" "display_drivers" "controller" "mcp23x17" "ads1x15" "qwiicnes" "input_drivers" "ft5x06" "tt21100" "drv2605" + REQUIRES "driver" "heap" "fatfs" "esp_littlefs" "esp_lcd" "esp_psram" "spi_flash" "nvs_flash" "codec" "display" "display_drivers" "controller" "mcp23x17" "ads1x15" "qwiicnes" "input_drivers" "ft5x06" "tt21100" "drv2605" "event_manager" ) diff --git a/main/fs_init.hpp b/components/box-emu-hal/include/fs_init.hpp similarity index 70% rename from main/fs_init.hpp rename to components/box-emu-hal/include/fs_init.hpp index 80e82ea6..e88a6560 100644 --- a/main/fs_init.hpp +++ b/components/box-emu-hal/include/fs_init.hpp @@ -15,7 +15,4 @@ #define MOUNT_POINT "/sdcard" #endif -#define DEFAULT_MODE S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH - -bool mkdirp(const char* path, mode_t mode = DEFAULT_MODE); void fs_init(); diff --git a/components/box-emu-hal/include/hal_events.hpp b/components/box-emu-hal/include/hal_events.hpp new file mode 100644 index 00000000..447ecaa7 --- /dev/null +++ b/components/box-emu-hal/include/hal_events.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include "event_manager.hpp" + +extern const std::string mute_button_topic; +extern const std::string video_setting_topic; diff --git a/components/box-emu-hal/include/i2c.hpp b/components/box-emu-hal/include/i2c.hpp index 0c1405fc..4bf1f677 100644 --- a/components/box-emu-hal/include/i2c.hpp +++ b/components/box-emu-hal/include/i2c.hpp @@ -15,4 +15,3 @@ void i2c_read_internal_bus(uint8_t dev_addr, uint8_t* read_data, size_t read_len void i2c_write_external_bus(uint8_t dev_addr, uint8_t *data, size_t len); void i2c_read_external_bus(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, size_t read_len); -void i2c_read_external_bus(uint8_t dev_addr, uint8_t* read_data, size_t read_len); diff --git a/components/box-emu-hal/include/i2s_audio.h b/components/box-emu-hal/include/i2s_audio.h index 5267f533..6a4d1434 100644 --- a/components/box-emu-hal/include/i2s_audio.h +++ b/components/box-emu-hal/include/i2s_audio.h @@ -12,6 +12,11 @@ extern "C" { void audio_init(); int16_t* get_audio_buffer(); void audio_play_frame(uint8_t *data, uint32_t num_bytes); + +bool is_muted(); +void set_muted(bool mute); + +int get_audio_volume(); void set_audio_volume(int percent); #ifdef __cplusplus diff --git a/components/box-emu-hal/include/input.h b/components/box-emu-hal/include/input.h index f524bc3f..424e75dc 100644 --- a/components/box-emu-hal/include/input.h +++ b/components/box-emu-hal/include/input.h @@ -20,11 +20,8 @@ extern "C" }; void init_input(); - bool read_joystick(float *x, float *y); void get_input_state(struct InputState *state); void touchpad_read(unsigned char *num_touch_points, unsigned short* x, unsigned short* y, unsigned char* btn_state); - void reset_user_quit(); - bool user_quit(); #ifdef __cplusplus } diff --git a/components/box-emu-hal/include/mmap.hpp b/components/box-emu-hal/include/mmap.hpp index a11f3872..6bfb6495 100644 --- a/components/box-emu-hal/include/mmap.hpp +++ b/components/box-emu-hal/include/mmap.hpp @@ -5,10 +5,11 @@ #include #include "nvs_flash.h" +#include "spi_flash_mmap.h" #include "esp_partition.h" #include "format.hpp" void init_memory(); -size_t copy_romdata_to_nesgame_partition(const std::string& rom_filename); +size_t copy_romdata_to_cart_partition(const std::string& rom_filename); uint8_t *get_mmapped_romdata(); diff --git a/components/box-emu-hal/include/spi_lcd.h b/components/box-emu-hal/include/spi_lcd.h index 737812a3..561ded67 100644 --- a/components/box-emu-hal/include/spi_lcd.h +++ b/components/box-emu-hal/include/spi_lcd.h @@ -27,7 +27,7 @@ extern "C" { #endif -#define NUM_ROWS_IN_FRAME_BUFFER 50 +#define NUM_ROWS_IN_FRAME_BUFFER 25 uint16_t make_color(uint8_t r, uint8_t g, uint8_t b); uint16_t* get_vram0(); diff --git a/components/box-emu-hal/include/video_setting.hpp b/components/box-emu-hal/include/video_setting.hpp new file mode 100644 index 00000000..fc693acb --- /dev/null +++ b/components/box-emu-hal/include/video_setting.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +enum class VideoSetting { ORIGINAL, FIT, FILL, MAX_UNUSED }; + +VideoSetting get_video_setting(); +void set_video_setting(const VideoSetting& setting); diff --git a/main/fs_init.cpp b/components/box-emu-hal/src/fs_init.cpp similarity index 79% rename from main/fs_init.cpp rename to components/box-emu-hal/src/fs_init.cpp index b1ca6249..e9303b8c 100644 --- a/main/fs_init.cpp +++ b/components/box-emu-hal/src/fs_init.cpp @@ -2,50 +2,6 @@ #include "format.hpp" -/** Utility function to create directory tree */ -bool mkdirp(const char* path, mode_t mode) { - // return std::filesystem::create_directories(path); - - // Invalid string - if(path[0] == '\0') { - return false; - } - - // const cast for hack - char* p = const_cast(path); - - // Find next slash mkdir() it and until we're at end of string - while (*p != '\0') { - // Skip first character - p++; - - // Find first slash or end - while(*p != '\0' && *p != '/') p++; - - // Remember value from p - char v = *p; - - // Write end of string at p - *p = '\0'; - - fmt::print("Making directory: {} ({})\n", path, 0775); - // Create folder from path to '\0' inserted at p - auto ret = mkdir(path, mode); - if(ret != 0 && errno != EEXIST) { - fmt::print("could not make {}, {} - {}\n", path, ret, errno); - *p = v; - return false; - } else { - fmt::print("made {}\n", path); - } - - // Restore path to it's former glory - *p = v; - } - - return true; -} - #if CONFIG_ROM_STORAGE_LITTLEFS static esp_vfs_littlefs_conf_t conf = { .base_path = MOUNT_POINT, diff --git a/components/box-emu-hal/src/i2c.cpp b/components/box-emu-hal/src/i2c.cpp index 09332c18..13e2bfdd 100644 --- a/components/box-emu-hal/src/i2c.cpp +++ b/components/box-emu-hal/src/i2c.cpp @@ -104,19 +104,3 @@ void i2c_read_external_bus(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_dat read_len, I2C_TIMEOUT_MS / portTICK_PERIOD_MS); } - -void i2c_read_external_bus(uint8_t dev_addr, uint8_t* read_data, size_t read_len) { - static const int I2C_BUS_MS_TO_WAIT = 1000; - static const int I2C_BUS_TICKS_TO_WAIT = (I2C_BUS_MS_TO_WAIT/portTICK_PERIOD_MS); - static uint8_t I2C_ACK_CHECK_EN = 1; - static uint8_t cmd_buffer[I2C_LINK_RECOMMENDED_SIZE(4)]; - i2c_cmd_handle_t cmd = i2c_cmd_link_create_static(cmd_buffer, I2C_LINK_RECOMMENDED_SIZE(4)); - - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_READ, I2C_ACK_CHECK_EN); - i2c_master_read(cmd, read_data, read_len, I2C_MASTER_LAST_NACK); - i2c_master_stop(cmd); - - i2c_master_cmd_begin(I2C_EXTERNAL, cmd, I2C_BUS_TICKS_TO_WAIT); - i2c_cmd_link_delete_static(cmd); -} diff --git a/components/box-emu-hal/src/i2s_audio.cpp b/components/box-emu-hal/src/i2s_audio.cpp index 357af781..8396a03d 100644 --- a/components/box-emu-hal/src/i2s_audio.cpp +++ b/components/box-emu-hal/src/i2s_audio.cpp @@ -1,5 +1,6 @@ #include "i2s_audio.h" +#include #include #include @@ -13,6 +14,10 @@ #include "esp_check.h" #include "i2c.hpp" +#include "task.hpp" +#include "event_manager.hpp" + +#include "hal_events.hpp" #include "es7210.h" #include "es8311.h" @@ -42,12 +47,38 @@ static i2s_chan_handle_t rx_handle = NULL; static int16_t *audio_buffer; +const std::string mute_button_topic = "mute/pressed"; +static std::atomic muted_{false}; +static std::atomic volume_{60}; + int16_t *get_audio_buffer() { return audio_buffer; } +void update_volume_output() { + if (muted_) { + es8311_codec_set_voice_volume(0); + } else { + es8311_codec_set_voice_volume(volume_); + } +} + +void set_muted(bool mute) { + muted_ = mute; + update_volume_output(); +} + +bool is_muted() { + return muted_; +} + void set_audio_volume(int percent) { - es8311_codec_set_voice_volume(percent); + volume_ = percent; + update_volume_output(); +} + +int get_audio_volume() { + return volume_; } static esp_err_t i2s_driver_init(void) @@ -137,6 +168,66 @@ static esp_err_t es8311_init_default(void) return ret_val; } +static std::unique_ptr mute_task; +static QueueHandle_t gpio_evt_queue; + +static void gpio_isr_handler(void *arg) { + uint32_t gpio_num = (uint32_t)arg; + xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); +} + +static void init_mute_button(void) { + static constexpr size_t MUTE_GPIO = 1; + // create the gpio event queue + gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); + // setup gpio interrupts for mute button + gpio_config_t io_conf; + memset(&io_conf, 0, sizeof(io_conf)); + // interrupt on any edge (since MUTE is connected to flipflop, see note below) + io_conf.intr_type = GPIO_INTR_ANYEDGE; + io_conf.pin_bit_mask = (1< bool { + static uint32_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((gpio_num_t)io_num); + // see if it's the mute button + if (io_num == MUTE_GPIO) { + // 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 + // read the state to know whether to be muted or not. + set_muted(pressed); + // simply publish that the mute button was presssed + espp::EventManager::get().publish(mute_button_topic, ""); + } + } + // don't want to stop the task + return false; + }, + .stack_size_bytes = 4*1024, + }); + mute_task->start(); +} + static bool initialized = false; void audio_init() { if (initialized) return; @@ -167,6 +258,9 @@ void audio_init() { audio_buffer = (int16_t*)heap_caps_malloc(AUDIO_BUFFER_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_DMA); + // now initialize the mute gpio + init_mute_button(); + initialized = true; } diff --git a/components/box-emu-hal/src/input.cpp b/components/box-emu-hal/src/input.cpp index 033b9854..7d73db6b 100644 --- a/components/box-emu-hal/src/input.cpp +++ b/components/box-emu-hal/src/input.cpp @@ -60,6 +60,7 @@ void tt21100_read(uint8_t *read_data, size_t read_len) { /** * Gamepad controller configuration */ + #if USE_QWIICNES void qwiicnes_write(uint8_t reg_addr, uint8_t value) { uint8_t write_buf[] = {reg_addr, value}; @@ -72,29 +73,12 @@ uint8_t qwiicnes_read(uint8_t reg_addr) { return data; } #else -void mcp23x17_write(uint8_t reg_addr, uint8_t value) { - uint8_t data[] = {reg_addr, value}; - i2c_write_external_bus(espp::Mcp23x17::ADDRESS, data, 2); -}; - -uint8_t mcp23x17_read(uint8_t reg_addr) { - uint8_t data; - i2c_read_external_bus(espp::Mcp23x17::ADDRESS, reg_addr, &data, 1); - return data; -}; -#endif // else !USE_QWIICNES - -std::atomic user_quit_{false}; -extern "C" void reset_user_quit() { - user_quit_ = false; -} - -extern "C" bool user_quit() { - // TODO: allow select + start to trigger this condition as well? - return user_quit_; +void i2c_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, size_t data_len) { + i2c_read_external_bus(dev_addr, reg_addr, data, data_len); } +#endif // else !USE_QWIICNES -extern "C" void touchpad_read(uint8_t* num_touch_points, uint16_t* x, uint16_t* y, uint8_t* btn_state) { +void touchpad_read(uint8_t* num_touch_points, uint16_t* x, uint16_t* y, uint8_t* btn_state) { // NOTE: ft5x06 does not have button support, so data->btn_val cannot be set #if USE_FT5X06 ft5x06->get_touch_point(num_touch_points, x, y); @@ -106,12 +90,11 @@ extern "C" void touchpad_read(uint8_t* num_touch_points, uint16_t* x, uint16_t* // now hand it off tt21100->get_touch_point(num_touch_points, x, y); *btn_state = tt21100->get_home_button_state(); - user_quit_ = (bool)(*btn_state); #endif } static std::atomic initialized = false; -extern "C" void init_input() { +void init_input() { if (initialized) return; fmt::print("Initializing input drivers...\n"); @@ -152,8 +135,8 @@ extern "C" void init_input() { .port_a_interrupt_mask = 0x00, .port_b_direction_mask = 0xFF, // D-pad B0-B3, ABXY B4-B7 .port_b_interrupt_mask = 0x00, - .write = mcp23x17_write, - .read = mcp23x17_read, + .write = i2c_write_external_bus, + .read = i2c_read, .log_level = espp::Logger::Verbosity::WARN }); #endif diff --git a/components/box-emu-hal/src/mmap.cpp b/components/box-emu-hal/src/mmap.cpp index bf3f22e1..170f334b 100644 --- a/components/box-emu-hal/src/mmap.cpp +++ b/components/box-emu-hal/src/mmap.cpp @@ -1,6 +1,6 @@ #include "mmap.hpp" -const esp_partition_t* nesgame_partition; +const esp_partition_t* cart_partition; spi_flash_mmap_handle_t hrom; void init_memory() { @@ -13,19 +13,19 @@ void init_memory() { } ESP_ERROR_CHECK(ret); - // get the romdata (nesgame) partition, type 0x40, subtype 1 (partitions.csv) - nesgame_partition = esp_partition_find_first((esp_partition_type_t)0x40, (esp_partition_subtype_t)1, NULL); - if (!nesgame_partition) { - fmt::print(fg(fmt::color::red), "Couldn't find nesgame_partition!\n"); + // get the romdata (cart) partition, type 0x40, subtype 1 (partitions.csv) + cart_partition = esp_partition_find_first((esp_partition_type_t)0x40, (esp_partition_subtype_t)1, NULL); + if (!cart_partition) { + fmt::print(fg(fmt::color::red), "Couldn't find cart_partition!\n"); } } -size_t copy_romdata_to_nesgame_partition(const std::string& rom_filename) { +size_t copy_romdata_to_cart_partition(const std::string& rom_filename) { esp_err_t err; - // erase the existing rom (if any) in the nesgame_partition - err = esp_partition_erase_range(nesgame_partition, 0, nesgame_partition->size); + // erase the existing rom (if any) in the cart_partition + err = esp_partition_erase_range(cart_partition, 0, cart_partition->size); if (err != ESP_OK) { - fmt::print("Couldn't erase nesgame_partition!\n"); + fmt::print("Couldn't erase cart_partition!\n"); } // load the file data and iteratively copy it over std::ifstream romfile(rom_filename, std::ios::binary | std::ios::ate); //open file at end @@ -43,13 +43,13 @@ size_t copy_romdata_to_nesgame_partition(const std::string& rom_filename) { for (size_t offset=0; offset < filesize; offset += block_size) { size_t read_size = std::min(filesize - offset, block_size); romfile.read(block, read_size); - err = esp_partition_write(nesgame_partition, offset, block, read_size); + err = esp_partition_write(cart_partition, offset, block, read_size); if (err != ESP_OK) { - fmt::print("Couldn't write to nesgame_partition, offset: {}, read_size: {}!\n", offset, read_size); + fmt::print("Couldn't write to cart_partition, offset: {}, read_size: {}!\n", offset, read_size); } bytes_written += read_size; } - fmt::print("Copied {} bytes to nesgame_partition\n", bytes_written); + fmt::print("Copied {} bytes to cart_partition\n", bytes_written); romfile.close(); return bytes_written; } @@ -59,11 +59,11 @@ extern "C" uint8_t *osd_getromdata() { } uint8_t *get_mmapped_romdata() { - uint8_t* romdata; esp_err_t err; - err = esp_partition_mmap(nesgame_partition, 0, 3*1024*1024, SPI_FLASH_MMAP_DATA, (const void**)&romdata, &hrom); + uint8_t* romdata = nullptr; + err = esp_partition_mmap(cart_partition, 0, 3*1024*1024, (esp_partition_mmap_memory_t)SPI_FLASH_MMAP_DATA, (const void**)&romdata, &hrom); if (err != ESP_OK) { - fmt::print("Couldn't map nesgame_partition!\n"); + fmt::print("Couldn't map cart_partition!\n"); return nullptr; } fmt::print("Initialized. ROM@{}\n", fmt::ptr(romdata)); diff --git a/components/box-emu-hal/src/video_setting.cpp b/components/box-emu-hal/src/video_setting.cpp new file mode 100644 index 00000000..2eddb77b --- /dev/null +++ b/components/box-emu-hal/src/video_setting.cpp @@ -0,0 +1,11 @@ +#include "video_setting.hpp" + +static std::atomic video_setting_{VideoSetting::ORIGINAL}; + +VideoSetting get_video_setting() { + return video_setting_; +} + +void set_video_setting(const VideoSetting& setting) { + video_setting_ = setting; +} diff --git a/components/controller/CMakeLists.txt b/components/controller/CMakeLists.txt deleted file mode 100644 index 50dd73b4..00000000 --- a/components/controller/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register( - INCLUDE_DIRS "include" - REQUIRES driver joystick - ) diff --git a/components/controller/example/CMakeLists.txt b/components/controller/example/CMakeLists.txt deleted file mode 100644 index 26248ab9..00000000 --- a/components/controller/example/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) - -# add the component directories that we want to use -set(EXTRA_COMPONENT_DIRS - "../../../components/" - "../../../components/espp/components" -) - -set( - COMPONENTS - "main esptool_py driver ads1x15 adc task controller" - CACHE STRING - "List of components to include" - ) - -project(controller_example) - -set(CMAKE_CXX_STANDARD 20) diff --git a/components/controller/example/README.md b/components/controller/example/README.md deleted file mode 100644 index ffe0beb9..00000000 --- a/components/controller/example/README.md +++ /dev/null @@ -1,67 +0,0 @@ -_Note that this is a template for an ESP-IDF example README.md file. When using this template, replace all these emphasised placeholders with example-specific content._ - -| Supported Targets | _Supported target, e.g. ESP32_ | _Another supported target, e.g. ESP32-S3_ | -| ----------------- | ------------------------------ | ----------------------------------------- | - -_If the example supports all targets supported by ESP-IDF then the table can be omitted_ -# _Example Title_ - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -_What is this example? What does it do?_ - -_What features of ESP-IDF does it use?_ - -_What could someone create based on this example? ie applications/use cases/etc_ - -_If there are any acronyms or Espressif-only words used here, explain them or mention where in the datasheet/TRM this information can be found._ - -## How to use example - -### Hardware Required - -_If possible, example should be able to run on any commonly available ESP32 development board. Otherwise, describe what specific hardware should be used._ - -_If any other items (server, BLE device, app, second chip, whatever) are needed, mention them here. Include links if applicable. Explain how to set them up._ - -### Configure the project - -``` -idf.py menuconfig -``` - -* _If there is any project configuration that the user must set for this example, mention this here._ - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(Replace PORT with the name of the serial port to use.) - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -_Include an example of the console output from the running example, here:_ - -``` -Use this style for pasting the log. -``` - -_If the user is supposed to interact with the example at this point (read/write GATT attribute, send HTTP request, press button, etc. then mention it here)_ - -_For examples where ESP32 is connected with some other hardware, include a table or schematics with connection details._ - -## Troubleshooting - -_If there are any likely problems or errors which many users might encounter, mention them here. Remove this section for very simple examples where nothing is likely to go wrong._ - -## Example Breakdown - -_If the example source code is lengthy, complex, or cannot be easily understood, use this section to break down and explain the source code. This can be done by breaking down the execution path step by step, or explaining what each major function/task/source file does. Add sub titles if necessary. Remove this section for very simple examples where the source code is self explanatory._ \ No newline at end of file diff --git a/components/controller/example/main/CMakeLists.txt b/components/controller/example/main/CMakeLists.txt deleted file mode 100644 index a941e22b..00000000 --- a/components/controller/example/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRC_DIRS "." - INCLUDE_DIRS ".") diff --git a/components/controller/example/main/controller_example.cpp b/components/controller/example/main/controller_example.cpp deleted file mode 100644 index 054b64d7..00000000 --- a/components/controller/example/main/controller_example.cpp +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include - -#include "driver/i2c.h" - -#include "ads1x15.hpp" -#include "controller.hpp" -#include "oneshot_adc.hpp" -#include "task.hpp" - -using namespace std::chrono_literals; - -#define I2C_NUM (I2C_NUM_1) -#define I2C_SCL_IO (GPIO_NUM_40) -#define I2C_SDA_IO (GPIO_NUM_41) -#define I2C_FREQ_HZ (400 * 1000) -#define I2C_TIMEOUT_MS (10) - -extern "C" void app_main(void) { - // First example shows using 2 analog pins with the controller for the x/y - // joystick - { - std::atomic quit_test = false; - fmt::print("Starting oneshot adc joystick controller example, press start & select together to quit!\n"); - //! [oneshot adc joystick controller example] - // make the adc we'll be reading from - std::vector channels{ - { - .unit = ADC_UNIT_2, - .channel = ADC_CHANNEL_1, // (x) Analog 0 on the joystick shield - .attenuation = ADC_ATTEN_DB_11 - }, - { - .unit = ADC_UNIT_2, - .channel = ADC_CHANNEL_2, // (y) Analog 1 on the joystick shield - .attenuation = ADC_ATTEN_DB_11 - } - }; - espp::OneshotAdc adc(espp::OneshotAdc::Config{ - .unit = ADC_UNIT_2, - .channels = channels, - }); - // make the function which will get the raw data from the ADC and convert to - // uncalibrated [-1,1] - auto read_joystick = [&adc, &channels](float *x, float *y) -> bool { - auto maybe_x_mv = adc.read_mv(channels[0].channel); - auto maybe_y_mv = adc.read_mv(channels[1].channel); - if (maybe_x_mv.has_value() && maybe_y_mv.has_value()) { - auto x_mv = maybe_x_mv.value(); - auto y_mv = maybe_y_mv.value(); - *x = (x_mv / 1700.0f - 1.0f); - *y = (y_mv / 1700.0f - 1.0f); - return true; - } - return false; - }; - // make the controller - NOTE: this was designed for connecting the Sparkfun - // Joystick Shield to the ESP32 S3 BOX - Controller controller(Controller::AnalogJoystickConfig{ - // buttons short to ground, so they are active low. this will enable the - // GPIO_PULLUP and invert the logic - .active_low = true, - .gpio_a = 38, // D3 on the joystick shield - .gpio_b = 39, // D5 on the joystick shield - .gpio_x = -1, // we're using this as start... - .gpio_y = -1, // we're using this as select... - .gpio_start = 42, // D4 on the joystick shield - .gpio_select = 21, // D6 on the joystick shield - .gpio_joystick_select = -1, // D2 on the joystick shield - .joystick_config = { - .x_calibration = {.center = 0.0f, .deadband = 0.2f, .minimum = -1.0f, .maximum = 1.0f}, - .y_calibration = {.center = 0.0f, .deadband = 0.2f, .minimum = -1.0f, .maximum = 1.0f}, - .get_values = read_joystick, - .log_level = espp::Logger::Verbosity::WARN - }, - .log_level = espp::Logger::Verbosity::WARN - }); - // and finally, make the task to periodically poll the controller and print - // the state - auto task_fn = [&quit_test, &controller](std::mutex& m, std::condition_variable& cv) { - controller.update(); - bool is_a_pressed = controller.is_pressed(Controller::Button::A); - bool is_b_pressed = controller.is_pressed(Controller::Button::B); - bool is_select_pressed = controller.is_pressed(Controller::Button::SELECT); - bool is_start_pressed = controller.is_pressed(Controller::Button::START); - bool is_up_pressed = controller.is_pressed(Controller::Button::UP); - bool is_down_pressed = controller.is_pressed(Controller::Button::DOWN); - bool is_left_pressed = controller.is_pressed(Controller::Button::LEFT); - bool is_right_pressed = controller.is_pressed(Controller::Button::RIGHT); - fmt::print("Controller buttons:\n" - "\tA: {}\n" - "\tB: {}\n" - "\tSelect: {}\n" - "\tStart: {}\n" - "\tUp: {}\n" - "\tDown: {}\n" - "\tLeft: {}\n" - "\tRight: {}\n", - is_a_pressed, - is_b_pressed, - is_select_pressed, - is_start_pressed, - is_up_pressed, - is_down_pressed, - is_left_pressed, - is_right_pressed - ); - quit_test = is_start_pressed && is_select_pressed; - // NOTE: sleeping in this way allows the sleep to exit early when the - // task is being stopped / destroyed - { - std::unique_lock lk(m); - cv.wait_for(lk, 500ms); - } - }; - auto task = espp::Task({ - .name = "Controller Task", - .callback = task_fn, - .stack_size_bytes = 6*1024, - .log_level = espp::Logger::Verbosity::WARN - }); - task.start(); - //! [oneshot adc joystick controller example] - while (!quit_test) { - std::this_thread::sleep_for(100ms); - } - } - - std::this_thread::sleep_for(500ms); - - // Second example shows using the i2c adc (ads1x15) with the controller for - // the x/y joystick - { - std::atomic quit_test = false; - fmt::print("Starting i2c adc joystick controller example, press start & select together to quit!\n"); - //! [i2c adc joystick controller example] - // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; // pin 3 on the joybonnet - i2c_cfg.scl_io_num = I2C_SCL_IO; // pin 5 on the joybonnet - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the i2c adc - auto ads_write = [](uint8_t reg_addr, uint16_t value) { - uint8_t write_buf[3] = {reg_addr, (uint8_t)(value >> 8), (uint8_t)(value & 0xFF)}; - i2c_master_write_to_device(I2C_NUM, - Ads1x15::ADDRESS, - write_buf, - 3, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - }; - auto ads_read = [](uint8_t reg_addr) -> uint16_t { - uint8_t read_data[2]; - i2c_master_write_read_device(I2C_NUM, - Ads1x15::ADDRESS, - ®_addr, - 1, // size of addr - read_data, - 2, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return (read_data[0] << 8) | read_data[1]; - }; - // make the actual ads class - Ads1x15 ads(Ads1x15::Ads1015Config{ - .write = ads_write, - .read = ads_read - }); - // make the task which will get the raw data from the I2C ADC and convert to - // uncalibrated [-1,1] - std::atomic joystick_x{0}; - std::atomic joystick_y{0}; - auto ads_read_task_fn = [&joystick_x, &joystick_y, &ads](std::mutex& m, std::condition_variable& cv) { - // NOTE: sleeping in this way allows the sleep to exit early when the - // task is being stopped / destroyed - { - using namespace std::chrono_literals; - std::unique_lock lk(m); - cv.wait_for(lk, 20ms); - } - auto x_mv = ads.sample_mv(1); - auto y_mv = ads.sample_mv(0); - joystick_x.store(x_mv / 1700.0f - 1.0f); - // y is inverted so negate it - joystick_y.store(-(y_mv / 1700.0f - 1.0f)); - }; - auto ads_task = espp::Task::make_unique({ - .name = "ADS", - .callback = ads_read_task_fn, - .stack_size_bytes{4*1024}, - .log_level = espp::Logger::Verbosity::INFO - }); - ads_task->start(); - // make the read joystick function used by the controller - auto read_joystick = [&joystick_x, &joystick_y](float *x, float *y) -> bool { - *x = joystick_x.load(); - *y = joystick_y.load(); - return true; - }; - // make the controller - NOTE: this was designed for connecting the Adafruit - // JoyBonnet to the ESP32 S3 BOX - Controller controller(Controller::AnalogJoystickConfig{ - // buttons short to ground, so they are active low. this will enable the - // GPIO_PULLUP and invert the logic - .active_low = true, - .gpio_a = 38, // pin 32 on the joybonnet - .gpio_b = 39, // pin 31 on the joybonnet - .gpio_x = -1, // pin 36 on the joybonnet - .gpio_y = -1, // pin 33 on the joybonnet - .gpio_start = 42, // pin 37 on the joybonnet - .gpio_select = 21, // pin 38 on the joybonnet - .gpio_joystick_select = -1, - .joystick_config = { - .x_calibration = {.center = 0.0f, .deadband = 0.2f, .minimum = -1.0f, .maximum = 1.0f}, - .y_calibration = {.center = 0.0f, .deadband = 0.2f, .minimum = -1.0f, .maximum = 1.0f}, - .get_values = read_joystick, - .log_level = espp::Logger::Verbosity::WARN - }, - .log_level = espp::Logger::Verbosity::WARN - }); - // and finally, make the task to periodically poll the controller and print - // the state - auto task_fn = [&quit_test, &controller](std::mutex& m, std::condition_variable& cv) { - controller.update(); - bool is_a_pressed = controller.is_pressed(Controller::Button::A); - bool is_b_pressed = controller.is_pressed(Controller::Button::B); - bool is_select_pressed = controller.is_pressed(Controller::Button::SELECT); - bool is_start_pressed = controller.is_pressed(Controller::Button::START); - bool is_up_pressed = controller.is_pressed(Controller::Button::UP); - bool is_down_pressed = controller.is_pressed(Controller::Button::DOWN); - bool is_left_pressed = controller.is_pressed(Controller::Button::LEFT); - bool is_right_pressed = controller.is_pressed(Controller::Button::RIGHT); - fmt::print("Controller buttons:\n" - "\tA: {}\n" - "\tB: {}\n" - "\tSelect: {}\n" - "\tStart: {}\n" - "\tUp: {}\n" - "\tDown: {}\n" - "\tLeft: {}\n" - "\tRight: {}\n", - is_a_pressed, - is_b_pressed, - is_select_pressed, - is_start_pressed, - is_up_pressed, - is_down_pressed, - is_left_pressed, - is_right_pressed - ); - quit_test = is_start_pressed && is_select_pressed; - // NOTE: sleeping in this way allows the sleep to exit early when the - // task is being stopped / destroyed - { - std::unique_lock lk(m); - cv.wait_for(lk, 500ms); - } - }; - auto task = espp::Task({ - .name = "Controller Task", - .callback = task_fn, - .stack_size_bytes = 6*1024, - .log_level = espp::Logger::Verbosity::WARN - }); - task.start(); - //! [i2c adc joystick controller example] - while (!quit_test) { - std::this_thread::sleep_for(100ms); - } - } - // now clean up the i2c driver (by now the task will have stopped, because we - // left its scope. - i2c_driver_delete(I2C_NUM); - - fmt::print("Controller example complete!\n"); - - while (true) { - std::this_thread::sleep_for(1s); - } -} diff --git a/components/controller/example/sdkconfig.defaults b/components/controller/example/sdkconfig.defaults deleted file mode 100644 index c3667f3e..00000000 --- a/components/controller/example/sdkconfig.defaults +++ /dev/null @@ -1,4 +0,0 @@ -# Common ESP-related -# -CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096 -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 diff --git a/components/controller/include/controller.hpp b/components/controller/include/controller.hpp deleted file mode 100644 index 85adac6b..00000000 --- a/components/controller/include/controller.hpp +++ /dev/null @@ -1,221 +0,0 @@ -#pragma once - -#include - -#include "driver/dedic_gpio.h" -#include "driver/gpio.h" - -#include "logger.hpp" -#include "joystick.hpp" - -/** - * @brief Class for managing controller input. - * - * The controller can be configured to either use a digital d-pad or an analog - * 2-axis joystick with select button. - * - * Digital configuration can support ABXY, start, select, and 4 digital - * directional inputs. - * - * Anaolg Joystick Configuration can support ABXY, start, select, two axis - * (analog) joystick, and joystick select button. It will also convert the - * joystick analog values into digital d-pad buttons. - */ -class Controller { -public: - enum class Button : int { A=0, B, X, Y, SELECT, START, UP, DOWN, LEFT, RIGHT, JOYSTICK_SELECT, LAST_UNUSED }; - struct State { - uint32_t a : 1; - uint32_t b : 1; - uint32_t x : 1; - uint32_t y : 1; - uint32_t select : 1; - uint32_t start : 1; - uint32_t up : 1; - uint32_t down : 1; - uint32_t left : 1; - uint32_t right : 1; - uint32_t joystick_select : 1; - }; - - struct DigitalConfig { - bool active_low{true}; - int gpio_a{-1}; - int gpio_b{-1}; - int gpio_x{-1}; - int gpio_y{-1}; - int gpio_start{-1}; - int gpio_select{-1}; - int gpio_up{-1}; - int gpio_down{-1}; - int gpio_left{-1}; - int gpio_right{-1}; - espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; - }; - - struct AnalogJoystickConfig { - bool active_low{true}; - int gpio_a{-1}; - int gpio_b{-1}; - int gpio_x{-1}; - int gpio_y{-1}; - int gpio_start{-1}; - int gpio_select{-1}; - int gpio_joystick_select{-1}; - espp::Joystick::Config joystick_config; - espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; - }; - - Controller(const DigitalConfig& config) - : logger_({.tag = "Digital Controller", .level = config.log_level}) { - gpio_.assign((int)Button::LAST_UNUSED, -1); - input_state_.assign((int)Button::LAST_UNUSED, false); - gpio_[(int)Button::A] = config.gpio_a; - gpio_[(int)Button::B] = config.gpio_b; - gpio_[(int)Button::X] = config.gpio_x; - gpio_[(int)Button::Y] = config.gpio_y; - gpio_[(int)Button::START] = config.gpio_start; - gpio_[(int)Button::SELECT] = config.gpio_select; - gpio_[(int)Button::UP] = config.gpio_up; - gpio_[(int)Button::DOWN] = config.gpio_down; - gpio_[(int)Button::LEFT] = config.gpio_left; - gpio_[(int)Button::RIGHT] = config.gpio_right; - init_gpio(config.active_low); - } - - Controller(const AnalogJoystickConfig& config) - : joystick_(std::make_unique(config.joystick_config)), - logger_({.tag = "Analog Joystick Controller", .level = config.log_level}) { - gpio_.assign((int)Button::LAST_UNUSED, -1); - input_state_.assign((int)Button::LAST_UNUSED, false); - gpio_[(int)Button::A] = config.gpio_a; - gpio_[(int)Button::B] = config.gpio_b; - gpio_[(int)Button::X] = config.gpio_x; - gpio_[(int)Button::Y] = config.gpio_y; - gpio_[(int)Button::START] = config.gpio_start; - gpio_[(int)Button::SELECT] = config.gpio_select; - gpio_[(int)Button::JOYSTICK_SELECT] = config.gpio_joystick_select; - init_gpio(config.active_low); - } - - ~Controller() { - dedic_gpio_del_bundle(gpio_bundle_); - } - - State get_state() { - logger_.debug("Returning state structure"); - std::scoped_lock lk(state_mutex_); - return State { - .a = input_state_[(int)Button::A], - .b = input_state_[(int)Button::B], - .x = input_state_[(int)Button::X], - .y = input_state_[(int)Button::Y], - .select = input_state_[(int)Button::SELECT], - .start = input_state_[(int)Button::START], - .up = input_state_[(int)Button::UP], - .down = input_state_[(int)Button::DOWN], - .left = input_state_[(int)Button::LEFT], - .right = input_state_[(int)Button::RIGHT], - .joystick_select = input_state_[(int)Button::JOYSTICK_SELECT], - }; - } - - bool is_pressed(const Button input) { - std::scoped_lock lk(state_mutex_); - return input_state_[(int)input]; - } - - void update() { - logger_.debug("Reading gpio bundle"); - // read the updated state for configured gpios (all at once) - uint32_t pin_state = dedic_gpio_bundle_read_in(gpio_bundle_); - // when setting up the dedic gpio, we removed the gpio that were not - // configured (-1) in our vector, but the returned bitmask simply orders - // them (low bit is low member in originally provided vector) so we need to - // track the actual bit corresponding to the pin in the pin_state. - int bit = 0; - // and pull out the state into the vector accordingly - logger_.debug("Parsing bundle state from pin state 0x{:04X}", pin_state); - { - std::scoped_lock lk(state_mutex_); - for (int i=0; iupdate(); - // now update the d-pad state if the joystick values are high enough - float x = joystick_->x(); - float y = joystick_->y(); - logger_.debug("Got joystick x,y: ({},{})", x, y); - std::scoped_lock lk(state_mutex_); - if (x > 0.5f) { - input_state_[(int)Button::RIGHT] = true; - } else if (x < -0.5f) { - input_state_[(int)Button::LEFT] = true; - } - if (y > 0.5f) { - input_state_[(int)Button::UP] = true; - } else if (y < -0.5f) { - input_state_[(int)Button::DOWN] = true; - } - } - } - -protected: - bool is_bit_set(uint32_t data, int bit) { - return (data & (1 << bit)) != 0; - } - - void init_gpio(bool active_low) { - // select only the gpios that are used (not -1) - std::vector actual_gpios; - for (auto gpio : gpio_) { - if (gpio != -1) { - actual_gpios.push_back(gpio); - } - } - - uint64_t pin_mask = 0; - for (auto gpio : actual_gpios) { - pin_mask |= (1ULL << gpio); - } - gpio_config_t io_config = { - .pin_bit_mask = pin_mask, - .mode = GPIO_MODE_INPUT, - .pull_up_en = active_low ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE, - .pull_down_en = active_low ? GPIO_PULLDOWN_DISABLE : GPIO_PULLDOWN_ENABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - ESP_ERROR_CHECK(gpio_config(&io_config)); - - // Create gpio_bundle_, input only - dedic_gpio_bundle_config_t gpio_bundle_config = { - .gpio_array = actual_gpios.data(), - .array_size = actual_gpios.size(), - .flags = { - .in_en = 1, - .in_invert = (unsigned int)(active_low ? 1 : 0), - .out_en = 0, // we _could_ enable input & output but we don't want to - .out_invert = 0, - }, - }; - ESP_ERROR_CHECK(dedic_gpio_new_bundle(&gpio_bundle_config, &gpio_bundle_)); - } - - std::mutex state_mutex_; - std::vector gpio_; - std::vector input_state_; - dedic_gpio_bundle_handle_t gpio_bundle_{NULL}; - std::unique_ptr joystick_; - espp::Logger logger_; -}; diff --git a/components/drv2605/CMakeLists.txt b/components/drv2605/CMakeLists.txt deleted file mode 100644 index 17999cee..00000000 --- a/components/drv2605/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register( - INCLUDE_DIRS "include" - REQUIRES "logger" - ) diff --git a/components/drv2605/include/drv2605.hpp b/components/drv2605/include/drv2605.hpp deleted file mode 100644 index d1614f4e..00000000 --- a/components/drv2605/include/drv2605.hpp +++ /dev/null @@ -1,174 +0,0 @@ -#pragma once - -#include - -#include "logger.hpp" - -class Drv2605 { -public: - static constexpr uint8_t ADDRESS = (0x5A); - - /** - * @brief Function to write a byte to a register - * @param reg_addr register address to write to - * @param data Data to write - */ - typedef std::function write_fn; - - /** - * @brief Function to read a byte from a register - * @param reg_addr register address to read from - * @return Byte read from the register - */ - typedef std::function read_fn; - - enum class Mode : uint8_t { - INTTRIG, ///< Internal Trigger (call star() to start playback) - EXTTRIGEDGE, ///< External edge trigger (rising edge on IN pin starts playback) - EXTTRIGLVL, ///< External level trigger (playback follows state of IN pin) - PWMANALOG, ///< PWM/Analog input - AUDIOVIBE, ///< Audio-to-vibe mode - REALTIME, ///< Real-time playback (RTP) - DIAGNOS, ///< Diagnostics - AUTOCAL, ///< Auto-calibration - }; - - // See https://learn.adafruit.com/assets/72593 for the complete list - enum class Waveform : uint8_t { - END = 0, ///< Signals this is the end of the waveforms to play - STRONG_CLICK = 1, - SHARP_CLICK = 4, - SOFT_BUMP = 7, - DOUBLE_CLICK = 10, - TRIPLE_CLICK = 12, - SOFT_FUZZ = 13, - STRONG_BUZZ = 14, - ALERT_750MS = 15, - ALERT_1000MS = 16, // omg there are 123 of theese i'm not typing them out right now... - BUZZ1 = 47, - BUZZ2 = 48, - BUZZ3 = 49, - BUZZ4 = 50, - BUZZ5 = 51, - PULSING_STRONG_1 = 52, - PULSING_STRONG_2 = 53, - TRANSITION_CLICK_1 = 58, - TRANSITION_HUM_1 = 64, - }; - - /** - * @brief The type of vibration motor connected to the Drv2605 - */ - enum class MotorType { - ERM, ///< Eccentric Rotating Mass (more common, therefore default) - LRA ///< Linear Resonant Actuator - }; - - struct Config { - write_fn write; /**< Function for writing a byte to a register on the Drv2605. */ - read_fn read; /**< Function for reading a byte from a register on the Drv2605. */ - MotorType motor_type{MotorType::ERM}; /**< MotorType that this driver is driving. */ - espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; /**< Log verbosity for the Drv2605. */ - }; - - Drv2605(const Config& config) - : write_(config.write), read_(config.read), - logger_({.tag="Drv2605", .level = config.log_level}){ - init(config); - } - - void start() { - logger_.info("Starting"); - write_((uint8_t)Register::START, 1); - } - - void stop() { - logger_.info("Stopping"); - write_((uint8_t)Register::START, 0); - } - - void set_mode(Mode mode) { - logger_.info("Setting mode {}", (uint8_t)mode); - write_((uint8_t)Register::MODE, (uint8_t)mode); - } - - void set_waveform(uint8_t slot, Waveform w) { - logger_.info("Setting waveform {}", (uint8_t)w); - write_((uint8_t)Register::WAVESEQ1 + slot, (uint8_t)w); - } - - /** - * @brief Select the waveform library to use. - * @param lib Library to use, 0=Empty, 1-5 are ERM, 6 is LRA - */ - void select_library(uint8_t lib) { - logger_.info("Selecting library {}", lib); - write_((uint8_t)Register::LIBRARY, lib); - } - -protected: - void init (const Config& config) { - logger_.info("Initializing motor"); - write_((uint8_t)Register::MODE, 0); // out of standby - write_((uint8_t)Register::RTPIN, 0); // no real-time playback - set_waveform(0, Waveform::STRONG_CLICK); // Strong Click - set_waveform(1, Waveform::END); // end sequence - write_((uint8_t)Register::OVERDRIVE, 0); // no overdrive - write_((uint8_t)Register::SUSTAINPOS, 0); - write_((uint8_t)Register::SUSTAINNEG, 0); - write_((uint8_t)Register::BREAK, 0); - write_((uint8_t)Register::AUDIOMAX, 0x64); - // set the motor type based on the config - set_motor_type(config.motor_type); - // turn on ERM OPEN LOOP - auto current_control3 = read_((uint8_t)Register::CONTROL3); - write_((uint8_t)Register::CONTROL3, current_control3 | 0x20); - } - - void set_motor_type(MotorType motor_type) { - logger_.info("Setting motor type {}", motor_type == MotorType::ERM ? "ERM" : "LRA"); - auto current_feedback = read_((uint8_t)Register::FEEDBACK); - uint8_t motor_config = (motor_type == MotorType::ERM) ? 0x7F : 0x80; - write_((uint8_t)Register::FEEDBACK, current_feedback | motor_config); - } - - enum class Register : uint8_t { - STATUS = 0x00, ///< Status - MODE = 0x01, ///< Mode - RTPIN = 0x02, ///< Real-Time playback input - LIBRARY = 0x03, ///< Waveform library selection - WAVESEQ1 = 0x04, ///< Waveform sequence 1 - WAVESEQ2 = 0x05, ///< Waveform sequence 2 - WAVESEQ3 = 0x06, ///< Waveform sequence 3 - WAVESEQ4 = 0x07, ///< Waveform sequence 4 - WAVESEQ5 = 0x08, ///< Waveform sequence 5 - WAVESEQ6 = 0x09, ///< Waveform sequence 6 - WAVESEQ7 = 0x0A, ///< Waveform sequence 7 - WAVESEQ8 = 0x0B, ///< Waveform sequence 8 - START = 0x0C, ///< Start/Stop playback control - OVERDRIVE = 0x0D,///< Overdrive time offset - SUSTAINPOS= 0x0E,///< Sustain time offset (positive) - SUSTAINNEG= 0x0F,///< Sustain time offset (negative) - BREAK = 0x10, ///< Break time offset - AUDIOCTRL = 0x11,///< Audio to vibe control - AUDIOMIN = 0x12, ///< Audio to vibe min input level - AUDIOMAX = 0x12, ///< Audio to vibe max input level - AUDIOOUTMIN=0x14,///< Audio to vibe min output drive - AUDIOOUTMAX=0x15,///< Audio to vibe max output drive - RATEDV = 0x16, ///< Rated voltage - CLAMPV = 0x17, ///< Overdrive clamp - AUTOCALCOMP=0x18,///< Auto calibration compensation result - AUTOCALEMP =0x19,///< Auto calibration back-EMF result - FEEDBACK = 0x1A, ///< Feedback control - CONTROL1 = 0x1B, ///< Control1 - CONTROL2 = 0x1C, ///< Control2 - CONTROL3 = 0x1D, ///< Control3 - CONTROL4 = 0x1E, ///< Control4 - VBAT = 0x21, ///< Vbat voltage monitor - LRARSON = 0x22, ///< LRA resonance-period - }; - - write_fn write_; - read_fn read_; - espp::Logger logger_; -}; diff --git a/components/espp b/components/espp index 8dd4be6d..13e6595f 160000 --- a/components/espp +++ b/components/espp @@ -1 +1 @@ -Subproject commit 8dd4be6dfcf83f667be5686abe1b0497a599bff8 +Subproject commit 13e6595fb7588956ad774b1c22b67e5727040592 diff --git a/components/gnuboy/CMakeLists.txt b/components/gbc/CMakeLists.txt similarity index 74% rename from components/gnuboy/CMakeLists.txt rename to components/gbc/CMakeLists.txt index eeca8068..57fa93e9 100644 --- a/components/gnuboy/CMakeLists.txt +++ b/components/gbc/CMakeLists.txt @@ -1,9 +1,9 @@ idf_component_register( INCLUDE_DIRS "include" - SRC_DIRS "src" + SRC_DIRS "src" "gnuboy/src" + PRIV_INCLUDE_DIRS "gnuboy/include" REQUIRES box-emu-hal ) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-misleading-indentation) target_compile_definitions(${COMPONENT_LIB} PRIVATE GNUBOY_NO_MINIZIP GNUBOY_NO_SCREENSHOT IS_LITTLE_ENDIAN) -target_compile_definitions(${COMPONENT_LIB} PUBLIC USE_GAMEBOY_GNUBOY) diff --git a/components/gnuboy/include/gnuboy/cpu.h b/components/gbc/gnuboy/include/gnuboy/cpu.h similarity index 100% rename from components/gnuboy/include/gnuboy/cpu.h rename to components/gbc/gnuboy/include/gnuboy/cpu.h diff --git a/components/gnuboy/include/gnuboy/cpucore.h b/components/gbc/gnuboy/include/gnuboy/cpucore.h similarity index 100% rename from components/gnuboy/include/gnuboy/cpucore.h rename to components/gbc/gnuboy/include/gnuboy/cpucore.h diff --git a/components/gnuboy/include/gnuboy/cpuregs.h b/components/gbc/gnuboy/include/gnuboy/cpuregs.h similarity index 100% rename from components/gnuboy/include/gnuboy/cpuregs.h rename to components/gbc/gnuboy/include/gnuboy/cpuregs.h diff --git a/components/gnuboy/include/gnuboy/defs.h b/components/gbc/gnuboy/include/gnuboy/defs.h similarity index 100% rename from components/gnuboy/include/gnuboy/defs.h rename to components/gbc/gnuboy/include/gnuboy/defs.h diff --git a/components/gnuboy/include/gnuboy/fastmem.h b/components/gbc/gnuboy/include/gnuboy/fastmem.h similarity index 100% rename from components/gnuboy/include/gnuboy/fastmem.h rename to components/gbc/gnuboy/include/gnuboy/fastmem.h diff --git a/components/gnuboy/include/gnuboy/fb.h b/components/gbc/gnuboy/include/gnuboy/fb.h similarity index 100% rename from components/gnuboy/include/gnuboy/fb.h rename to components/gbc/gnuboy/include/gnuboy/fb.h diff --git a/components/gnuboy/include/gnuboy/gnuboy.h b/components/gbc/gnuboy/include/gnuboy/gnuboy.h similarity index 100% rename from components/gnuboy/include/gnuboy/gnuboy.h rename to components/gbc/gnuboy/include/gnuboy/gnuboy.h diff --git a/components/gnuboy/include/gnuboy/hw.h b/components/gbc/gnuboy/include/gnuboy/hw.h similarity index 100% rename from components/gnuboy/include/gnuboy/hw.h rename to components/gbc/gnuboy/include/gnuboy/hw.h diff --git a/components/gnuboy/include/gnuboy/input.h b/components/gbc/gnuboy/include/gnuboy/input.h similarity index 100% rename from components/gnuboy/include/gnuboy/input.h rename to components/gbc/gnuboy/include/gnuboy/input.h diff --git a/components/gnuboy/include/gnuboy/lcd.h b/components/gbc/gnuboy/include/gnuboy/lcd.h similarity index 100% rename from components/gnuboy/include/gnuboy/lcd.h rename to components/gbc/gnuboy/include/gnuboy/lcd.h diff --git a/components/gnuboy/include/gnuboy/loader.h b/components/gbc/gnuboy/include/gnuboy/loader.h similarity index 100% rename from components/gnuboy/include/gnuboy/loader.h rename to components/gbc/gnuboy/include/gnuboy/loader.h diff --git a/components/gnuboy/include/gnuboy/mem.h b/components/gbc/gnuboy/include/gnuboy/mem.h similarity index 100% rename from components/gnuboy/include/gnuboy/mem.h rename to components/gbc/gnuboy/include/gnuboy/mem.h diff --git a/components/gnuboy/include/gnuboy/noise.h b/components/gbc/gnuboy/include/gnuboy/noise.h similarity index 100% rename from components/gnuboy/include/gnuboy/noise.h rename to components/gbc/gnuboy/include/gnuboy/noise.h diff --git a/components/gnuboy/include/gnuboy/pcm.h b/components/gbc/gnuboy/include/gnuboy/pcm.h similarity index 100% rename from components/gnuboy/include/gnuboy/pcm.h rename to components/gbc/gnuboy/include/gnuboy/pcm.h diff --git a/components/gnuboy/include/gnuboy/regs.h b/components/gbc/gnuboy/include/gnuboy/regs.h similarity index 100% rename from components/gnuboy/include/gnuboy/regs.h rename to components/gbc/gnuboy/include/gnuboy/regs.h diff --git a/components/gnuboy/include/gnuboy/rtc.h b/components/gbc/gnuboy/include/gnuboy/rtc.h similarity index 100% rename from components/gnuboy/include/gnuboy/rtc.h rename to components/gbc/gnuboy/include/gnuboy/rtc.h diff --git a/components/gnuboy/include/gnuboy/sound.h b/components/gbc/gnuboy/include/gnuboy/sound.h similarity index 100% rename from components/gnuboy/include/gnuboy/sound.h rename to components/gbc/gnuboy/include/gnuboy/sound.h diff --git a/components/gnuboy/src/cpu.c b/components/gbc/gnuboy/src/cpu.c similarity index 100% rename from components/gnuboy/src/cpu.c rename to components/gbc/gnuboy/src/cpu.c diff --git a/components/gnuboy/src/emu.c b/components/gbc/gnuboy/src/emu.c similarity index 100% rename from components/gnuboy/src/emu.c rename to components/gbc/gnuboy/src/emu.c diff --git a/components/gnuboy/src/fastmem.c b/components/gbc/gnuboy/src/fastmem.c similarity index 100% rename from components/gnuboy/src/fastmem.c rename to components/gbc/gnuboy/src/fastmem.c diff --git a/components/gnuboy/src/hw.c b/components/gbc/gnuboy/src/hw.c similarity index 100% rename from components/gnuboy/src/hw.c rename to components/gbc/gnuboy/src/hw.c diff --git a/components/gnuboy/src/inflate.c b/components/gbc/gnuboy/src/inflate.c similarity index 100% rename from components/gnuboy/src/inflate.c rename to components/gbc/gnuboy/src/inflate.c diff --git a/components/gnuboy/src/lcd.c b/components/gbc/gnuboy/src/lcd.c similarity index 100% rename from components/gnuboy/src/lcd.c rename to components/gbc/gnuboy/src/lcd.c diff --git a/components/gnuboy/src/lcdc.c b/components/gbc/gnuboy/src/lcdc.c similarity index 100% rename from components/gnuboy/src/lcdc.c rename to components/gbc/gnuboy/src/lcdc.c diff --git a/components/gnuboy/src/loader.c b/components/gbc/gnuboy/src/loader.c similarity index 97% rename from components/gnuboy/src/loader.c rename to components/gbc/gnuboy/src/loader.c index 72fe6220..c56f6cb4 100644 --- a/components/gnuboy/src/loader.c +++ b/components/gbc/gnuboy/src/loader.c @@ -103,7 +103,7 @@ static void initmem(void *mem, int size) static byte *inf_buf; static int inf_pos, inf_len; -static byte *_data_ptr = NULL; +// static byte *_data_ptr = NULL; int rom_load(uint8_t *rom_data, size_t rom_data_size) { @@ -113,8 +113,9 @@ int rom_load(uint8_t *rom_data, size_t rom_data_size) */ byte c, *data, *header; int len = 0, rlen; - data = heap_caps_malloc(0x400000, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - _data_ptr = data; + data = rom_data; + // data = heap_caps_malloc(0x400000, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + // _data_ptr = data; memcpy(data, rom_data, rom_data_size); // data = rom_data; @@ -366,10 +367,10 @@ void rtc_load() void loader_unload() { - printf("freeing data\n"); - if (_data_ptr != NULL) - free(_data_ptr); - printf("data freed!\n"); + // printf("freeing data\n"); + // if (_data_ptr != NULL) + // free(_data_ptr); + // printf("data freed!\n"); /* sram_save(); if (romfile) free(romfile); diff --git a/components/gnuboy/src/mem.c b/components/gbc/gnuboy/src/mem.c similarity index 100% rename from components/gnuboy/src/mem.c rename to components/gbc/gnuboy/src/mem.c diff --git a/components/gnuboy/src/refresh.c b/components/gbc/gnuboy/src/refresh.c similarity index 100% rename from components/gnuboy/src/refresh.c rename to components/gbc/gnuboy/src/refresh.c diff --git a/components/gnuboy/src/rtc.c b/components/gbc/gnuboy/src/rtc.c similarity index 100% rename from components/gnuboy/src/rtc.c rename to components/gbc/gnuboy/src/rtc.c diff --git a/components/gnuboy/src/save.c b/components/gbc/gnuboy/src/save.c similarity index 100% rename from components/gnuboy/src/save.c rename to components/gbc/gnuboy/src/save.c diff --git a/components/gnuboy/src/sound.c b/components/gbc/gnuboy/src/sound.c similarity index 100% rename from components/gnuboy/src/sound.c rename to components/gbc/gnuboy/src/sound.c diff --git a/components/gnuboy/src/split.c b/components/gbc/gnuboy/src/split.c similarity index 100% rename from components/gnuboy/src/split.c rename to components/gbc/gnuboy/src/split.c diff --git a/components/gbc/include/gameboy.hpp b/components/gbc/include/gameboy.hpp new file mode 100644 index 00000000..8c9fad85 --- /dev/null +++ b/components/gbc/include/gameboy.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include + +void set_gb_video_original(); +void set_gb_video_fit(); +void set_gb_video_fill(); +void reset_gameboy(); +void init_gameboy(const std::string& rom_filename, uint8_t *romdata, size_t rom_data_size); +void load_gameboy(std::string_view save_path); +void save_gameboy(std::string_view save_path); +void start_gameboy_tasks(); +void stop_gameboy_tasks(); +void run_gameboy_rom(); +void deinit_gameboy(); +std::vector get_gameboy_video_buffer(); diff --git a/main/gameboy.cpp b/components/gbc/src/gameboy.cpp similarity index 84% rename from main/gameboy.cpp rename to components/gbc/src/gameboy.cpp index 87984b26..4fafbb02 100644 --- a/main/gameboy.cpp +++ b/components/gbc/src/gameboy.cpp @@ -1,4 +1,4 @@ -#pragma GCC optimize ("Ofast") +// #pragma GCC optimize ("Ofast") #include "gameboy.hpp" @@ -16,10 +16,9 @@ #include "freertos/FreeRTOS.h" #include "freertos/queue.h" -static const size_t gameboy_screen_width = 160; -static const size_t gameboy_screen_height = 160; +static const size_t GAMEBOY_SCREEN_WIDTH = 160; +static const size_t GAMEBOY_SCREEN_HEIGHT = 144; -#if USE_GAMEBOY_GNUBOY extern "C" { #include #include @@ -61,7 +60,7 @@ static struct InputState state; static std::atomic scaled = false; static std::atomic filled = false; -bool IRAM_ATTR video_task(std::mutex &m, std::condition_variable& cv) { +bool video_task(std::mutex &m, std::condition_variable& cv) { static uint16_t *_frame; if (xQueuePeek(video_queue, &_frame, 10 / portTICK_PERIOD_MS) != pdTRUE) { // we couldn't get anything from the queue, return @@ -118,7 +117,7 @@ bool IRAM_ATTR video_task(std::mutex &m, std::condition_variable& cv) { return false; } -bool IRAM_ATTR run_to_vblank(std::mutex &m, std::condition_variable& cv) { +bool run_to_vblank(std::mutex &m, std::condition_variable& cv) { /* FRAME BEGIN */ auto start = std::chrono::high_resolution_clock::now(); @@ -187,7 +186,6 @@ bool IRAM_ATTR run_to_vblank(std::mutex &m, std::condition_variable& cv) { std::this_thread::sleep_until(start + delay); return false; } -#endif void set_gb_video_original() { scaled = false; @@ -204,31 +202,14 @@ void set_gb_video_fill() { filled = true; } -static std::string gbc_savedir = "/sdcard"; -static std::string current_cart = ""; - -static std::string get_save_path(bool bypass_exist_check=false) { - namespace fs = std::filesystem; - fmt::print("creating: {}\n", gbc_savedir); - // fs::create_directories(gbc_savedir); - mkdirp(gbc_savedir.c_str()); - auto save_path = gbc_savedir + "/" + fs::path(current_cart).stem().string() + "_gbc.sav"; - if (bypass_exist_check || fs::exists(save_path)) { - fmt::print("found: {}\n", save_path); - return save_path; - } else { - fmt::print("Could not find {}\n", save_path); - } - return ""; +void reset_gameboy() { + emu_reset(); } void init_gameboy(const std::string& rom_filename, uint8_t *romdata, size_t rom_data_size) { static bool initialized = false; - current_cart = rom_filename; - // lcd_set_queued_transmit(); -#if USE_GAMEBOY_GNUBOY // Note: Magic number obtained by adjusting until audio buffer overflows stop. const int audioBufferLength = AUDIO_BUFFER_SIZE; displayBuffer[0] = (uint16_t*)get_frame_buffer0(); @@ -257,7 +238,6 @@ void init_gameboy(const std::string& rom_filename, uint8_t *romdata, size_t rom_ sound_reset(); - fmt::print("GAMEBOY enabled: GNUBOY\n"); loader_init(romdata, rom_data_size); emu_reset(); totalElapsedSeconds = 0; @@ -279,19 +259,6 @@ void init_gameboy(const std::string& rom_filename, uint8_t *romdata, size_t rom_ }); video_queue = xQueueCreate(1, sizeof(uint16_t*)); } - auto save_path = get_save_path(); - if (save_path.size()) { - auto f = fopen(save_path.c_str(), "rb"); - loadstate(f); - fclose(f); - vram_dirty(); - pal_dirty(); - sound_dirty(); - mem_updatemap(); - } - gbc_video_task->start(); - gbc_task->start(); -#endif initialized = true; } @@ -306,26 +273,53 @@ void run_gameboy_rom() { pad_set(PAD_START, state.start); pad_set(PAD_A, state.a); pad_set(PAD_B, state.b); - // handle touchpad so we can know if the user needs to quit - uint8_t _num_touches, _btn_state; - uint16_t _x,_y; - touchpad_read(&_num_touches, &_x, &_y, &_btn_state); // don't need to do anything else because the gbc task runs the main display loop } -void deinit_gameboy() { - fmt::print("quitting gameboy emulation!\n"); -#if USE_GAMEBOY_GNUBOY - // stop the task... - gbc_task->stop(); - gbc_video_task->stop(); +void load_gameboy(std::string_view save_path) { + if (save_path.size()) { + auto f = fopen(save_path.data(), "rb"); + loadstate(f); + fclose(f); + vram_dirty(); + pal_dirty(); + sound_dirty(); + mem_updatemap(); + } +} + +void save_gameboy(std::string_view save_path) { // save state - fmt::print("Saving state\n"); - auto save_path = get_save_path(true); - auto f = fopen(save_path.c_str(), "wb"); + auto f = fopen(save_path.data(), "wb"); savestate(f); fclose(f); +} + +void stop_gameboy_tasks() { + // stop the task... + gbc_task->stop(); + gbc_video_task->stop(); +} + +void start_gameboy_tasks() { + // stop the task... + gbc_task->start(); + gbc_video_task->start(); +} + +std::vector get_gameboy_video_buffer() { + 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; + std::vector new_frame_buffer(width * 2 * height); + for (int y = 0; y < height; ++y) { + memcpy(&new_frame_buffer[y * width * 2], &frame_buffer[y * width * 2], width * 2); + } + return new_frame_buffer; +} + +void deinit_gameboy() { // now unload everything loader_unload(); -#endif } diff --git a/components/gnuboy/src/events.c b/components/gnuboy/src/events.c deleted file mode 100644 index f24cd621..00000000 --- a/components/gnuboy/src/events.c +++ /dev/null @@ -1,54 +0,0 @@ -#if 0 -/* - * events.c - * - * Event queue. - */ - - -#include "gnuboy/input.h" - - -char keystates[MAX_KEYS]; -int nkeysdown; - -#define MAX_EVENTS 32 - -static event_t eventqueue[MAX_EVENTS]; -static int eventhead, eventpos; - - -int ev_postevent(event_t *ev) -{ - int nextevent; - nextevent = (eventhead+1)%MAX_EVENTS; - if (nextevent == eventpos) - return 0; - eventqueue[eventhead] = *ev; - eventhead = nextevent; - return 1; -} - -int ev_getevent(event_t *ev) -{ - if (eventpos == eventhead) - { - ev->type = EV_NONE; - return 0; - } - *ev = eventqueue[eventpos]; - eventpos = (eventpos+1)%MAX_EVENTS; - if (ev->type == EV_PRESS) - { - keystates[ev->code] = 1; - nkeysdown++; - } - if (ev->type == EV_RELEASE) - { - keystates[ev->code] = 0; - nkeysdown--; - if (nkeysdown < 0) nkeysdown = 0; - } - return 1; -} -#endif diff --git a/components/gnuboy/src/keytable.c b/components/gnuboy/src/keytable.c deleted file mode 100644 index 5f8c8186..00000000 --- a/components/gnuboy/src/keytable.c +++ /dev/null @@ -1,155 +0,0 @@ -#if 0 -/* - * keytable.c - * - * Key names to keycodes mapping. - */ - -#include -#include -#include -#include - -#include "gnuboy/gnuboy.h" -#include "gnuboy/input.h" - -/* keytable - Mapping of key names to codes, and back. A single code - can have more than one name, in which case the first will be used - when saving config, but any may be used in setting config. */ - -keytable_t keytable[] = -{ - { "shift", K_SHIFT }, - { "ctrl", K_CTRL }, - { "alt", K_ALT }, - { "up", K_UP }, - { "down", K_DOWN }, - { "right", K_RIGHT }, - { "left", K_LEFT }, - { "enter", K_ENTER }, - { "tab", K_TAB }, - { "space", K_SPACE }, - { "bs", K_BS }, - { "backspace", K_BS }, /* dup */ - { "del", K_DEL }, - { "delete", K_DEL }, /* dup */ - { "ins", K_INS }, - { "insert", K_INS }, /* dup */ - { "home", K_HOME }, - { "end", K_END }, - { "prior", K_PRIOR }, - { "next", K_NEXT }, - { "pgup", K_PRIOR }, /* duplicate for pgup/pgdn fans */ - { "pgdn", K_NEXT }, /* ditto */ - { "esc", K_ESC }, - { "escape", K_ESC }, /* dup */ - { "pause", K_PAUSE }, - { "caps", K_CAPS }, - { "capslock", K_CAPS }, /* dup */ - { "numlock", K_NUMLOCK }, - { "scroll", K_SCROLL }, - - { "minus", K_MINUS }, - { "_", K_MINUS }, /* dup */ - { "equals", K_EQUALS }, - { "plus", K_EQUALS }, /* dup */ - { "+", K_EQUALS }, /* dup */ - { "tilde", K_TILDE }, - { "backquote", K_TILDE }, /* dup */ - { "`", K_TILDE }, /* dup */ - { "slash", K_SLASH }, - { "question", K_SLASH }, /* dup */ - { "?", K_SLASH }, /* dup */ - { "bslash", K_BSLASH }, - { "backslash", K_BSLASH }, /* dup */ - { "pipe", K_BSLASH }, /* dup */ - { "|", K_BSLASH }, /* dup */ - { "semi", K_SEMI }, - { "semicolon", K_SEMI }, /* dup */ - { "quote", K_QUOTE }, - - { "f1", K_F1 }, - { "f2", K_F2 }, - { "f3", K_F3 }, - { "f4", K_F4 }, - { "f5", K_F5 }, - { "f6", K_F6 }, - { "f7", K_F7 }, - { "f8", K_F8 }, - { "f9", K_F9 }, - { "f10", K_F10 }, - { "f11", K_F11 }, - { "f12", K_F12 }, - - { "num0", K_NUM0 }, - { "num1", K_NUM1 }, - { "num2", K_NUM2 }, - { "num3", K_NUM3 }, - { "num4", K_NUM4 }, - { "num5", K_NUM5 }, - { "num6", K_NUM6 }, - { "num7", K_NUM7 }, - { "num8", K_NUM8 }, - { "num9", K_NUM9 }, - { "numplus", K_NUMPLUS }, - { "numminus", K_NUMMINUS }, - { "nummul", K_NUMMUL }, - { "numdiv", K_NUMDIV }, - { "numdot", K_NUMDOT }, - { "numenter", K_NUMENTER }, - - /* Note that these are not presently used... */ - { "mouse0", K_MOUSE0 }, - { "mouse1", K_MOUSE1 }, - { "mouse2", K_MOUSE2 }, - { "mouse3", K_MOUSE3 }, - { "mouse4", K_MOUSE4 }, - - { "joyleft", K_JOYLEFT }, - { "joyright", K_JOYRIGHT }, - { "joyup", K_JOYUP }, - { "joydown", K_JOYDOWN }, - - { "joy0", K_JOY0 }, - { "joy1", K_JOY1 }, - { "joy2", K_JOY2 }, - { "joy3", K_JOY3 }, - { "joy4", K_JOY4 }, - { "joy5", K_JOY5 }, - { "joy6", K_JOY6 }, - { "joy7", K_JOY7 }, - { "joy8", K_JOY8 }, - { "joy9", K_JOY9 }, - { "joy10", K_JOY10 }, - { "joy11", K_JOY11 }, - { "joy12", K_JOY12 }, - { "joy13", K_JOY13 }, - { "joy14", K_JOY14 }, - { "joy15", K_JOY15 }, - - { NULL, 0 } -}; - -int k_keycode(char *name) -{ - keytable_t *key; - - for (key = keytable; key->name; key++) - if (!strcasecmp(key->name, name)) - return key->code; - if (strlen(name) == 1) - return tolower((unsigned char)name[0]); - return 0; -} - -char *k_keyname(int code) -{ - keytable_t *key; - - for (key = keytable; key->name; key++) - if (key->code == code) - return key->name; - return NULL; -} - -#endif diff --git a/components/gnuboy/src/newsound.c b/components/gnuboy/src/newsound.c deleted file mode 100644 index 4c1a5cbd..00000000 --- a/components/gnuboy/src/newsound.c +++ /dev/null @@ -1,51 +0,0 @@ -#if 0 -/* - * new sound core for 1.1.x - */ - - - -enum sevcode -{ - SEV_S1E, - SEV_S2E, - SEV_S3E, - SEV_S4E, - SEV_S1L, - SEV_S2L, - SEV_S3L, - SEV_S4L, - SEV_SW, - SEV_WAV -}; - - -struct sev -{ - int prev, next; - int time; -}; - - - -static struct sev *sevs; - - - -void sound_mix(int cycles) -{ - -} - - -void sound_update(int force) -{ - int now = 0; - - for (;;) - { - if (sevs->time > cpu.snd) break; - - } -} -#endif diff --git a/components/gnuboy/src/palette.c b/components/gnuboy/src/palette.c deleted file mode 100644 index 2ce7f590..00000000 --- a/components/gnuboy/src/palette.c +++ /dev/null @@ -1,148 +0,0 @@ -#if 0 -#include - -#include "gnuboy/gnuboy.h" -#include "gnuboy/defs.h" -#include "gnuboy/fb.h" - - -static byte palmap[32768]; -static byte pallock[256]; -static int palrev[256]; - -/* Course color mapping, for when palette is exhausted. */ -static byte crsmap[4][32768]; -static int crsrev[4][256]; -static const int crsmask[4] = { 0x7BDE, 0x739C, 0x6318, 0x4210 }; - -enum plstatus -{ - pl_unused = 0, - pl_linger, - pl_active, - pl_locked -}; - - -static byte bestmatch(int c) -{ - byte n, best; - int r, g, b; - int r2, g2, b2, c2; - int err, besterr; - - r = (c & 0x001F) << 3; - g = (c & 0x03E0) >> 2; - b = (c & 0x7C00) >> 7; - - best = 0; - besterr = 1024; - for (n = 1; n; n++) - { - c2 = palrev[n]; - r2 = (c2 & 0x001F) << 3; - g2 = (c2 & 0x03E0) >> 2; - b2 = (c2 & 0x7C00) >> 7; - err = abs(r-r2) + abs(b-b2) + abs(g-g2); - if (err < besterr) - { - besterr = err; - best = n; - } - } - return best; -} - -static void makecourse(int c, byte n) -{ - int i; - for (i = 0; i < 4; i++) - { - c &= crsmask[i]; - crsmap[i][c] = n; - crsrev[i][n] = c; - } -} - -static byte findcourse(int c) -{ - int i; - byte n; - for (i = 0; i < 4; i++) - { - c &= crsmask[i]; - n = crsmap[i][c]; - if (crsrev[i][n] == c) - return n; - } - return 0; -} - - -void pal_lock(byte n) -{ - if (!n) return; - if (pallock[n] >= pl_locked) - pallock[n]++; - else pallock[n] = pl_locked; -} - -byte pal_getcolor(int c, int r, int g, int b) -{ - byte n; - static byte l; - n = palmap[c]; - if (n && pallock[n] && palrev[n] == c) - { - pal_lock(n); - return n; - } - for (n = l+1; n != l; n++) - { - if (!n || pallock[n] /* || n < 16 */) continue; - pal_lock(n); - palmap[c] = n; - palrev[n] = c; - makecourse(c, n); - vid_setpal(n, r, g, b); - return (l = n); - } - n = findcourse(c); - pal_lock(n); - return n; -} - -void pal_release(byte n) -{ - if (pallock[n] >= pl_locked) - pallock[n]--; -} - - -void pal_expire() -{ - int i; - for (i = 0; i < 256; i++) - if (pallock[i] && pallock[i] < pl_locked) - pallock[i]--; -} - - -void pal_set332() -{ - int i, r, g, b; - - fb.indexed = 0; - fb.cc[0].r = 5; - fb.cc[1].r = 5; - fb.cc[2].r = 6; - fb.cc[0].l = 0; - fb.cc[1].l = 3; - fb.cc[2].l = 6; - - i = 0; - for (b = 0; b < 4; b++) for (g = 0; g < 8; g++) for (r = 0; r < 8; r++) - vid_setpal(i++, (r<<5)|(r<<2)|(r>>1), - (g<<5)|(g<<2)|(g>>1), (b<<6)|(b<<4)|(b<<2)|b); -} -#endif diff --git a/components/gnuboy/src/path.c b/components/gnuboy/src/path.c deleted file mode 100644 index 8f9b7945..00000000 --- a/components/gnuboy/src/path.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "gnuboy/gnuboy.h" - -#ifdef ALT_PATH_SEP -#define SEP ';' -#else -#define SEP ':' -#endif - -char *path_search(char *name, char *mode, char *path) -{ - FILE *f; - static char *buf; - char *p, *n; - int l; - - if (buf) free(buf); buf = 0; - if (!path || !*path || *name == DIRSEP_CHAR) - return (buf = strdup(name)); - - buf = malloc(strlen(path) + strlen(name) + 2); - - for (p = path; *p; p += l) - { - if (*p == SEP) p++; - n = strchr(p, SEP); - if (n) l = n - p; - else l = strlen(p); - strncpy(buf, p, l); - buf[l] = DIRSEP_CHAR; - strcpy(buf+l+1, name); - if ((f = fopen(buf, mode))) - { - fclose(f); - return buf; - } - } - return name; -} - diff --git a/components/gui/CMakeLists.txt b/components/gui/CMakeLists.txt index 3384d734..647763a0 100644 --- a/components/gui/CMakeLists.txt +++ b/components/gui/CMakeLists.txt @@ -1,4 +1,5 @@ idf_component_register( - SRC_DIRS "generated" - INCLUDE_DIRS "include" "generated" - REQUIRES lvgl task display logger jpeg) + SRC_DIRS "src" "generated" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "generated" + REQUIRES lvgl task display logger jpeg box-emu-hal) diff --git a/components/gui/include/gui.hpp b/components/gui/include/gui.hpp index 8839816a..39da7cc7 100644 --- a/components/gui/include/gui.hpp +++ b/components/gui/include/gui.hpp @@ -4,16 +4,16 @@ #include #include -extern "C" { -#include "ui.h" -#include "ui_comp.h" -} - +#include "event_manager.hpp" #include "display.hpp" #include "jpeg.hpp" #include "task.hpp" #include "logger.hpp" +#include "hal_events.hpp" +#include "i2s_audio.h" +#include "video_setting.hpp" + class Gui { public: typedef std::function play_haptic_fn; @@ -27,14 +27,13 @@ class Gui { espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; }; - enum class VideoSetting { ORIGINAL, FIT, FILL, MAX_UNUSED }; - Gui(const Config& config) : play_haptic_(config.play_haptic), set_waveform_(config.set_waveform), display_(config.display), logger_({.tag="Gui", .level=config.log_level}) { init_ui(); + update_shared_state(); // now start the gui updater task using namespace std::placeholders; task_ = espp::Task::make_unique({ @@ -43,6 +42,16 @@ class Gui { .stack_size_bytes = 6 * 1024 }); task_->start(); + // register events + espp::EventManager::get().add_subscriber(mute_button_topic, + "gui", + std::bind(&Gui::on_mute_button_pressed, this, _1)); + } + + ~Gui() { + task_->stop(); + deinit_ui(); + espp::EventManager::get().remove_subscriber(mute_button_topic, "gui"); } void ready_to_play(bool new_state) { @@ -53,94 +62,31 @@ class Gui { return ready_to_play_; } - void set_mute(bool muted) { - muted_ = muted; - if (muted_) { - lv_obj_add_state(ui_mutebutton, LV_STATE_CHECKED); - } else { - lv_obj_clear_state(ui_mutebutton, LV_STATE_CHECKED); - } - } + void set_mute(bool muted); void toggle_mute() { - set_mute(!muted_); + set_mute(!is_muted()); } - void set_audio_level(int new_audio_level) { - audio_level_ = std::clamp(new_audio_level, 0, 100); - lv_bar_set_value(ui_volumebar, audio_level_, LV_ANIM_ON); - } + void set_audio_level(int new_audio_level); - int get_audio_level() { - if (muted_) return 0; - return audio_level_; - } + int get_audio_level(); - void next_video_setting() { - int current_option = lv_dropdown_get_selected(ui_videosettingdropdown); - int max_options = lv_dropdown_get_option_cnt(ui_videosettingdropdown); - if (current_option < (max_options-1)) { - current_option++; - } else { - current_option = 0; - } - lv_dropdown_set_selected(ui_videosettingdropdown, current_option); - } + void set_video_setting(VideoSetting setting); - void prev_video_setting() { - int current_option = lv_dropdown_get_selected(ui_videosettingdropdown); - int max_options = lv_dropdown_get_option_cnt(ui_videosettingdropdown); - if (current_option > 0) { - current_option = max_options - 1; - } else { - current_option--; - } - lv_dropdown_set_selected(ui_videosettingdropdown, current_option); - } - - void set_video_setting(VideoSetting setting) { - lv_dropdown_set_selected(ui_videosettingdropdown, (int)setting); - } - - VideoSetting get_video_setting() { - return (VideoSetting)(lv_dropdown_get_selected(ui_videosettingdropdown)); - } - - void add_rom(const std::string& name, const std::string& image_path) { - // protect since this function is called from another thread context - std::lock_guard lk(mutex_); - // make a new rom, which is a button with a label in it - // make the rom's button - auto new_rom = lv_btn_create(ui_rompanel); - lv_obj_set_size(new_rom, LV_PCT(100), LV_SIZE_CONTENT); - lv_obj_add_flag( new_rom, LV_OBJ_FLAG_SCROLL_ON_FOCUS); - lv_obj_clear_flag( new_rom, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_add_event_cb(new_rom, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - lv_obj_center(new_rom); - // set the rom's label text - auto label = lv_label_create(new_rom); - lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_width(label, LV_PCT(100)); - lv_obj_add_flag(label, LV_OBJ_FLAG_EVENT_BUBBLE); - lv_obj_add_flag(label, LV_OBJ_FLAG_GESTURE_BUBBLE); - lv_label_set_text(label, name.c_str()); - lv_obj_add_style(label, &rom_label_style_, LV_STATE_DEFAULT); - lv_obj_center(label); - // and add it to our vector - roms_.push_back(new_rom); - boxart_paths_.push_back(image_path); - if (focused_rom_ == -1) { - // if we don't have a focused rom, then focus this newly added rom! - focus_rom(new_rom); - } - } + void add_rom(const std::string& name, const std::string& image_path); size_t get_selected_rom_index() { return focused_rom_; } - void pause() { paused_ = true; } - void resume() { paused_ = false; } + void pause() { + paused_ = true; + } + void resume() { + update_shared_state(); + paused_ = false; + } void next() { // protect since this function is called from another thread context @@ -168,32 +114,7 @@ class Gui { focus_rom(rom); } - void focus_rom(lv_obj_t *new_focus, bool scroll_to_view=true) { - std::lock_guard lk(mutex_); - if (roms_.size() == 0) { - return; - } - // unfocus all roms - for (int i=0; i < roms_.size(); i++) { - auto rom = roms_[i]; - lv_obj_clear_state(rom, LV_STATE_CHECKED); - if (rom == new_focus && i != focused_rom_) { - // if the focused_rom variable was not set correctly, set it now. - focused_rom_ = i; - } - } - // focus - lv_obj_add_state(new_focus, LV_STATE_CHECKED); - - if (scroll_to_view) { - lv_obj_scroll_to_view(new_focus, LV_ANIM_ON); - } - - // update the boxart - auto boxart_path = boxart_paths_[focused_rom_].c_str(); - focused_boxart_ = make_boxart(boxart_path); - lv_img_set_src(ui_boxart, &focused_boxart_); - } + void focus_rom(lv_obj_t *new_focus, bool scroll_to_view=true); void set_haptic_waveform(int new_waveform) { if (new_waveform > 123) { @@ -214,45 +135,24 @@ class Gui { set_haptic_waveform(haptic_waveform_ - 1); } - void update_haptic_waveform_label() { - auto haptic_label = fmt::format("{}", haptic_waveform_); - lv_label_set_text(ui_hapticlabel, haptic_label.c_str()); - } + void update_haptic_waveform_label(); protected: - void init_ui() { - ui_init(); - - // make the label scrolling animation - lv_anim_init(&rom_label_animation_template_); - lv_anim_set_delay(&rom_label_animation_template_, 1000); /*Wait 1 second to start the first scroll*/ - lv_anim_set_repeat_delay(&rom_label_animation_template_, - 3000); /*Repeat the scroll 3 seconds after the label scrolls back to the initial position*/ - - /*Initialize the label style with the animation template*/ - lv_style_init(&rom_label_style_); - lv_style_set_anim(&rom_label_style_, &rom_label_animation_template_); - - lv_obj_set_flex_flow(ui_rompanel, LV_FLEX_FLOW_COLUMN); - lv_obj_set_scroll_snap_y(ui_rompanel, LV_SCROLL_SNAP_CENTER); - - lv_bar_set_value(ui_volumebar, audio_level_, LV_ANIM_OFF); - - // rom screen navigation - lv_obj_add_event_cb(ui_settingsbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - lv_obj_add_event_cb(ui_playbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - - // volume settings - lv_obj_add_event_cb(ui_volumeupbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - lv_obj_add_event_cb(ui_volumedownbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - lv_obj_add_event_cb(ui_mutebutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - - // haptic settings - lv_obj_add_event_cb(ui_hapticdownbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - lv_obj_add_event_cb(ui_hapticupbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - lv_obj_add_event_cb(ui_hapticplaybutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); - // ensure the waveform is set and the ui is updated - set_haptic_waveform(haptic_waveform_); + void init_ui(); + void deinit_ui(); + + void load_rom_screen(); + + void update_shared_state() { + set_mute(is_muted()); + set_audio_level(get_audio_volume()); + set_video_setting(::get_video_setting()); + } + + VideoSetting get_video_setting(); + + void on_mute_button_pressed(const std::string& data) { + set_mute(is_muted()); } lv_img_dsc_t make_boxart(const std::string& path) { @@ -305,6 +205,9 @@ class Gui { case LV_EVENT_PRESSED: gui->on_pressed(e); break; + case LV_EVENT_VALUE_CHANGED: + gui->on_value_changed(e); + break; case LV_EVENT_LONG_PRESSED: break; case LV_EVENT_KEY: @@ -314,64 +217,10 @@ class Gui { } } - void on_pressed(lv_event_t *e) { - lv_obj_t * target = lv_event_get_target(e); - logger_.info("PRESSED: {}", fmt::ptr(target)); - // is it the settings button? - bool is_settings_button = (target == ui_settingsbutton); - if (is_settings_button) { - // TODO: DO SOMETHING HERE! - return; - } - // volume controls - bool is_volume_up_button = (target == ui_volumeupbutton); - if (is_volume_up_button) { - set_audio_level(audio_level_ + 10); - return; - } - bool is_volume_down_button = (target == ui_volumedownbutton); - if (is_volume_down_button) { - set_audio_level(audio_level_ - 10); - return; - } - bool is_mute_button = (target == ui_mutebutton); - if (is_mute_button) { - toggle_mute(); - return; - } - // haptic controls - bool is_haptic_up_button = (target == ui_hapticupbutton); - if (is_haptic_up_button) { - next_haptic_waveform(); - return; - } - bool is_haptic_down_button = (target == ui_hapticdownbutton); - if (is_haptic_down_button) { - previous_haptic_waveform(); - return; - } - bool is_hapticplay_button = (target == ui_hapticplaybutton); - if (is_hapticplay_button) { - play_haptic_(); - return; - } - // or is it the play button? - bool is_play_button = (target == ui_playbutton); - if (is_play_button) { - ready_to_play_ = true; - return; - } - // or is it one of the roms? - if (std::find(roms_.begin(), roms_.end(), target) != roms_.end()) { - // it's one of the roms, focus it! this was pressed, so don't scroll (it - // will already scroll) - focus_rom(target, false); - } - } + void on_pressed(lv_event_t *e); + void on_value_changed(lv_event_t *e); // LVLG gui objects - std::atomic muted_{false}; - std::atomic audio_level_{60}; std::vector boxart_paths_; std::vector roms_; std::atomic focused_rom_{-1}; @@ -384,7 +233,7 @@ class Gui { play_haptic_fn play_haptic_; set_waveform_fn set_waveform_; - std::atomic haptic_waveform_{16}; // for the DRV2605, this is a 1s alert + std::atomic haptic_waveform_{12}; std::atomic ready_to_play_{false}; std::atomic paused_{false}; diff --git a/squareline/emu.sll b/components/gui/squareline/emu.sll similarity index 100% rename from squareline/emu.sll rename to components/gui/squareline/emu.sll diff --git a/squareline/emu.spj b/components/gui/squareline/emu.spj similarity index 100% rename from squareline/emu.spj rename to components/gui/squareline/emu.spj diff --git a/components/gui/src/gui.cpp b/components/gui/src/gui.cpp new file mode 100644 index 00000000..dfdfba9c --- /dev/null +++ b/components/gui/src/gui.cpp @@ -0,0 +1,204 @@ +#include "gui.hpp" + +extern "C" { +#include "ui.h" +#include "ui_comp.h" +} + +void Gui::set_mute(bool muted) { + set_muted(muted); + if (muted) { + lv_obj_add_state(ui_mutebutton, LV_STATE_CHECKED); + } else { + lv_obj_clear_state(ui_mutebutton, LV_STATE_CHECKED); + } +} + +void Gui::set_audio_level(int new_audio_level) { + new_audio_level = std::clamp(new_audio_level, 0, 100); + lv_bar_set_value(ui_volumebar, new_audio_level, LV_ANIM_ON); + set_audio_volume(new_audio_level); +} + +void Gui::set_video_setting(VideoSetting setting) { + ::set_video_setting(setting); + lv_dropdown_set_selected(ui_videosettingdropdown, (int)setting); +} + +VideoSetting Gui::get_video_setting() { + return (VideoSetting)(lv_dropdown_get_selected(ui_videosettingdropdown)); +} + +void Gui::add_rom(const std::string& name, const std::string& image_path) { + // protect since this function is called from another thread context + std::lock_guard lk(mutex_); + // make a new rom, which is a button with a label in it + // make the rom's button + auto new_rom = lv_btn_create(ui_rompanel); + lv_obj_set_size(new_rom, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_add_flag( new_rom, LV_OBJ_FLAG_SCROLL_ON_FOCUS); + lv_obj_clear_flag( new_rom, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_add_event_cb(new_rom, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_center(new_rom); + // set the rom's label text + auto label = lv_label_create(new_rom); + lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_obj_set_width(label, LV_PCT(100)); + lv_obj_add_flag(label, LV_OBJ_FLAG_EVENT_BUBBLE); + lv_obj_add_flag(label, LV_OBJ_FLAG_GESTURE_BUBBLE); + lv_label_set_text(label, name.c_str()); + lv_obj_add_style(label, &rom_label_style_, LV_STATE_DEFAULT); + lv_obj_center(label); + // and add it to our vector + roms_.push_back(new_rom); + boxart_paths_.push_back(image_path); + if (focused_rom_ == -1) { + // if we don't have a focused rom, then focus this newly added rom! + focus_rom(new_rom); + } +} + +void Gui::focus_rom(lv_obj_t *new_focus, bool scroll_to_view) { + std::lock_guard lk(mutex_); + if (roms_.size() == 0) { + return; + } + // unfocus all roms + for (int i=0; i < roms_.size(); i++) { + auto rom = roms_[i]; + lv_obj_clear_state(rom, LV_STATE_CHECKED); + if (rom == new_focus && i != focused_rom_) { + // if the focused_rom variable was not set correctly, set it now. + focused_rom_ = i; + } + } + // focus + lv_obj_add_state(new_focus, LV_STATE_CHECKED); + + if (scroll_to_view) { + lv_obj_scroll_to_view(new_focus, LV_ANIM_ON); + } + + // update the boxart + auto boxart_path = boxart_paths_[focused_rom_].c_str(); + focused_boxart_ = make_boxart(boxart_path); + lv_img_set_src(ui_boxart, &focused_boxart_); +} + +void Gui::update_haptic_waveform_label() { + auto haptic_label = fmt::format("{}", haptic_waveform_); + lv_label_set_text(ui_hapticlabel, haptic_label.c_str()); +} + +void Gui::deinit_ui() { + lv_obj_del(ui_romscreen); + lv_obj_del(ui_settingsscreen); +} + +void Gui::init_ui() { + ui_init(); + + // make the label scrolling animation + lv_anim_init(&rom_label_animation_template_); + lv_anim_set_delay(&rom_label_animation_template_, 1000); /*Wait 1 second to start the first scroll*/ + lv_anim_set_repeat_delay(&rom_label_animation_template_, + 3000); /*Repeat the scroll 3 seconds after the label scrolls back to the initial position*/ + + /*Initialize the label style with the animation template*/ + lv_style_init(&rom_label_style_); + lv_style_set_anim(&rom_label_style_, &rom_label_animation_template_); + + lv_obj_set_flex_flow(ui_rompanel, LV_FLEX_FLOW_COLUMN); + lv_obj_set_scroll_snap_y(ui_rompanel, LV_SCROLL_SNAP_CENTER); + + lv_bar_set_value(ui_volumebar, get_audio_volume(), LV_ANIM_OFF); + + // rom screen navigation + lv_obj_add_event_cb(ui_settingsbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_playbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + + // video settings + lv_obj_add_event_cb(ui_videosettingdropdown, &Gui::event_callback, LV_EVENT_VALUE_CHANGED, static_cast(this)); + + // volume settings + lv_obj_add_event_cb(ui_volumeupbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_volumedownbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_mutebutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + + // haptic settings + lv_obj_add_event_cb(ui_hapticdownbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_hapticupbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_hapticplaybutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast(this)); + // ensure the waveform is set and the ui is updated + set_haptic_waveform(haptic_waveform_); +} + +void Gui::load_rom_screen() { + lv_scr_load(ui_romscreen); +} + +void Gui::on_value_changed(lv_event_t *e) { + lv_obj_t * target = lv_event_get_target(e); + logger_.info("Value changed: {}", fmt::ptr(target)); + // is it the settings button? + bool is_video_setting = (target == ui_videosettingdropdown); + if (is_video_setting) { + set_video_setting(this->get_video_setting()); + return; + } +} + +void Gui::on_pressed(lv_event_t *e) { + lv_obj_t * target = lv_event_get_target(e); + logger_.info("PRESSED: {}", fmt::ptr(target)); + // is it the settings button? + bool is_settings_button = (target == ui_settingsbutton); + if (is_settings_button) { + // TODO: DO SOMETHING HERE! + return; + } + // volume controls + bool is_volume_up_button = (target == ui_volumeupbutton); + if (is_volume_up_button) { + set_audio_level(get_audio_volume() + 10); + return; + } + bool is_volume_down_button = (target == ui_volumedownbutton); + if (is_volume_down_button) { + set_audio_level(get_audio_volume() - 10); + return; + } + bool is_mute_button = (target == ui_mutebutton); + if (is_mute_button) { + toggle_mute(); + return; + } + // haptic controls + bool is_haptic_up_button = (target == ui_hapticupbutton); + if (is_haptic_up_button) { + next_haptic_waveform(); + return; + } + bool is_haptic_down_button = (target == ui_hapticdownbutton); + if (is_haptic_down_button) { + previous_haptic_waveform(); + return; + } + bool is_hapticplay_button = (target == ui_hapticplaybutton); + if (is_hapticplay_button) { + play_haptic_(); + return; + } + // or is it the play button? + bool is_play_button = (target == ui_playbutton); + if (is_play_button) { + ready_to_play_ = true; + return; + } + // or is it one of the roms? + if (std::find(roms_.begin(), roms_.end(), target) != roms_.end()) { + // it's one of the roms, focus it! this was pressed, so don't scroll (it + // will already scroll) + focus_rom(target, false); + } +} diff --git a/components/jpegenc b/components/jpegenc new file mode 160000 index 00000000..3db39f10 --- /dev/null +++ b/components/jpegenc @@ -0,0 +1 @@ +Subproject commit 3db39f10edcfc0fed1fef286b6e54a0d7465fa72 diff --git a/components/menu/CMakeLists.txt b/components/menu/CMakeLists.txt new file mode 100644 index 00000000..71f69538 --- /dev/null +++ b/components/menu/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + INCLUDE_DIRS "include" + SRC_DIRS "src" "generated" + PRIV_INCLUDE_DIRS "generated" + REQUIRES lvgl task display logger jpeg box-emu-hal) diff --git a/components/menu/generated/ui.c b/components/menu/generated/ui.c new file mode 100644 index 00000000..cef3f1a4 --- /dev/null +++ b/components/menu/generated/ui.c @@ -0,0 +1,321 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.2.3 +// LVGL version: 8.2.0 +// Project name: menu + +#include "ui.h" +#include "ui_helpers.h" + +///////////////////// VARIABLES //////////////////// +lv_obj_t *ui_Screen1; +lv_obj_t *ui_menu_panel; +lv_obj_t *ui_menu_title; +lv_obj_t *ui_resume_btn; +lv_obj_t *ui_Label6; +lv_obj_t *ui_Panel3; +lv_obj_t *ui_volume_mute_btn; +lv_obj_t *ui_Label10; +lv_obj_t *ui_volume_dec_btn; +lv_obj_t *ui_Label11; +lv_obj_t *ui_Bar2; +lv_obj_t *ui_volume_inc_btn; +lv_obj_t *ui_Label8; +lv_obj_t *ui_Panel4; +lv_obj_t *ui_btn_slot_dec; +lv_obj_t *ui_Label2; +lv_obj_t *ui_slot_label; +lv_obj_t *ui_btn_slot_inc; +lv_obj_t *ui_Label1; +lv_obj_t *ui_Panel2; +lv_obj_t *ui_load_btn; +lv_obj_t *ui_Label4; +lv_obj_t *ui_slot_image; +lv_obj_t *ui_Panel1; +lv_obj_t *ui_save_btn; +lv_obj_t *ui_Label3; +lv_obj_t *ui_pause_image; +lv_obj_t *ui_Panel6; +lv_obj_t *ui_Label9; +lv_obj_t *ui_Dropdown2; +lv_obj_t *ui_reset_btn; +lv_obj_t *ui_Label5; +lv_obj_t *ui_quit_btn; +lv_obj_t *ui_Label7; +lv_obj_t *ui____initial_actions0; + +///////////////////// TEST LVGL SETTINGS //////////////////// +#if LV_COLOR_DEPTH != 16 + #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" +#endif +#if LV_COLOR_16_SWAP !=1 + #error "LV_COLOR_16_SWAP should be 1 to match SquareLine Studio's settings" +#endif + +///////////////////// ANIMATIONS //////////////////// + +///////////////////// FUNCTIONS //////////////////// + +///////////////////// SCREENS //////////////////// +void ui_Screen1_screen_init(void) +{ +ui_Screen1 = lv_obj_create(NULL); +lv_obj_clear_flag( ui_Screen1, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_menu_panel = lv_obj_create(ui_Screen1); +lv_obj_set_width( ui_menu_panel, lv_pct(100)); +lv_obj_set_height( ui_menu_panel, lv_pct(100)); +lv_obj_set_align( ui_menu_panel, LV_ALIGN_CENTER ); + +ui_menu_title = lv_label_create(ui_menu_panel); +lv_obj_set_width( ui_menu_title, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_menu_title, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_menu_title, LV_ALIGN_TOP_MID ); +lv_label_set_text(ui_menu_title,"Emulation Paused"); + +ui_resume_btn = lv_btn_create(ui_menu_panel); +lv_obj_set_width( ui_resume_btn, 100); +lv_obj_set_height( ui_resume_btn, 40); +lv_obj_set_x( ui_resume_btn, 0 ); +lv_obj_set_y( ui_resume_btn, 35 ); +lv_obj_set_align( ui_resume_btn, LV_ALIGN_TOP_MID ); +lv_obj_add_flag( ui_resume_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_resume_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label6 = lv_label_create(ui_resume_btn); +lv_obj_set_width( ui_Label6, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label6, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label6, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label6,"Resume"); + +ui_Panel3 = lv_obj_create(ui_menu_panel); +lv_obj_set_height( ui_Panel3, 50); +lv_obj_set_width( ui_Panel3, lv_pct(100)); +lv_obj_set_x( ui_Panel3, 0 ); +lv_obj_set_y( ui_Panel3, 80 ); +lv_obj_set_align( ui_Panel3, LV_ALIGN_TOP_MID ); +lv_obj_clear_flag( ui_Panel3, LV_OBJ_FLAG_SCROLLABLE ); /// Flags +lv_obj_set_style_pad_left(ui_Panel3, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_right(ui_Panel3, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_top(ui_Panel3, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_bottom(ui_Panel3, 0, LV_PART_MAIN| LV_STATE_DEFAULT); + +ui_volume_mute_btn = lv_btn_create(ui_Panel3); +lv_obj_set_width( ui_volume_mute_btn, 30); +lv_obj_set_height( ui_volume_mute_btn, 30); +lv_obj_set_align( ui_volume_mute_btn, LV_ALIGN_LEFT_MID ); +lv_obj_add_flag( ui_volume_mute_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_volume_mute_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label10 = lv_label_create(ui_volume_mute_btn); +lv_obj_set_width( ui_Label10, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label10, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label10, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label10,LV_SYMBOL_MUTE); + +ui_volume_dec_btn = lv_btn_create(ui_Panel3); +lv_obj_set_width( ui_volume_dec_btn, 30); +lv_obj_set_height( ui_volume_dec_btn, 30); +lv_obj_set_x( ui_volume_dec_btn, 35 ); +lv_obj_set_y( ui_volume_dec_btn, 0 ); +lv_obj_set_align( ui_volume_dec_btn, LV_ALIGN_LEFT_MID ); +lv_obj_add_flag( ui_volume_dec_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_volume_dec_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label11 = lv_label_create(ui_volume_dec_btn); +lv_obj_set_width( ui_Label11, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label11, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label11, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label11,LV_SYMBOL_VOLUME_MID); + +ui_Bar2 = lv_bar_create(ui_Panel3); +lv_bar_set_value(ui_Bar2,25,LV_ANIM_OFF); +lv_obj_set_width( ui_Bar2, 150); +lv_obj_set_height( ui_Bar2, 10); +lv_obj_set_x( ui_Bar2, -50 ); +lv_obj_set_y( ui_Bar2, 0 ); +lv_obj_set_align( ui_Bar2, LV_ALIGN_RIGHT_MID ); + +ui_volume_inc_btn = lv_btn_create(ui_Panel3); +lv_obj_set_width( ui_volume_inc_btn, 30); +lv_obj_set_height( ui_volume_inc_btn, 30); +lv_obj_set_align( ui_volume_inc_btn, LV_ALIGN_RIGHT_MID ); +lv_obj_add_flag( ui_volume_inc_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_volume_inc_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label8 = lv_label_create(ui_volume_inc_btn); +lv_obj_set_width( ui_Label8, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label8, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label8, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label8,LV_SYMBOL_VOLUME_MAX); + +ui_Panel4 = lv_obj_create(ui_menu_panel); +lv_obj_set_height( ui_Panel4, 50); +lv_obj_set_width( ui_Panel4, lv_pct(100)); +lv_obj_set_x( ui_Panel4, 0 ); +lv_obj_set_y( ui_Panel4, 130 ); +lv_obj_set_align( ui_Panel4, LV_ALIGN_TOP_MID ); +lv_obj_clear_flag( ui_Panel4, LV_OBJ_FLAG_SCROLLABLE ); /// Flags +lv_obj_set_style_pad_left(ui_Panel4, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_right(ui_Panel4, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_top(ui_Panel4, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_bottom(ui_Panel4, 0, LV_PART_MAIN| LV_STATE_DEFAULT); + +ui_btn_slot_dec = lv_btn_create(ui_Panel4); +lv_obj_set_width( ui_btn_slot_dec, 30); +lv_obj_set_height( ui_btn_slot_dec, 30); +lv_obj_set_align( ui_btn_slot_dec, LV_ALIGN_LEFT_MID ); +lv_obj_add_flag( ui_btn_slot_dec, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_btn_slot_dec, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label2 = lv_label_create(ui_btn_slot_dec); +lv_obj_set_width( ui_Label2, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label2, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label2, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label2,"-"); + +ui_slot_label = lv_label_create(ui_Panel4); +lv_obj_set_width( ui_slot_label, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_slot_label, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_slot_label, LV_ALIGN_CENTER ); +lv_label_set_text(ui_slot_label,"Save Slot 1"); + +ui_btn_slot_inc = lv_btn_create(ui_Panel4); +lv_obj_set_width( ui_btn_slot_inc, 30); +lv_obj_set_height( ui_btn_slot_inc, 30); +lv_obj_set_align( ui_btn_slot_inc, LV_ALIGN_RIGHT_MID ); +lv_obj_add_flag( ui_btn_slot_inc, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_btn_slot_inc, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label1 = lv_label_create(ui_btn_slot_inc); +lv_obj_set_width( ui_Label1, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label1, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label1, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label1,"+"); + +ui_Panel2 = lv_obj_create(ui_menu_panel); +lv_obj_set_height( ui_Panel2, 100); +lv_obj_set_width( ui_Panel2, lv_pct(100)); +lv_obj_set_x( ui_Panel2, 0 ); +lv_obj_set_y( ui_Panel2, 180 ); +lv_obj_set_align( ui_Panel2, LV_ALIGN_TOP_MID ); +lv_obj_add_flag( ui_Panel2, LV_OBJ_FLAG_EVENT_BUBBLE ); /// Flags +lv_obj_clear_flag( ui_Panel2, LV_OBJ_FLAG_SCROLLABLE ); /// Flags +lv_obj_set_style_pad_left(ui_Panel2, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_right(ui_Panel2, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_top(ui_Panel2, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_bottom(ui_Panel2, 0, LV_PART_MAIN| LV_STATE_DEFAULT); + +ui_load_btn = lv_btn_create(ui_Panel2); +lv_obj_set_width( ui_load_btn, 50); +lv_obj_set_height( ui_load_btn, 40); +lv_obj_set_align( ui_load_btn, LV_ALIGN_LEFT_MID ); +lv_obj_add_flag( ui_load_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_load_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label4 = lv_label_create(ui_load_btn); +lv_obj_set_width( ui_Label4, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label4, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label4, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label4,"Load"); + +ui_slot_image = lv_img_create(ui_Panel2); +lv_obj_set_width( ui_slot_image, 80); +lv_obj_set_height( ui_slot_image, 60); +lv_obj_set_align( ui_slot_image, LV_ALIGN_RIGHT_MID ); +lv_obj_add_flag( ui_slot_image, LV_OBJ_FLAG_ADV_HITTEST ); /// Flags +lv_obj_clear_flag( ui_slot_image, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Panel1 = lv_obj_create(ui_menu_panel); +lv_obj_set_height( ui_Panel1, 100); +lv_obj_set_width( ui_Panel1, lv_pct(100)); +lv_obj_set_x( ui_Panel1, 0 ); +lv_obj_set_y( ui_Panel1, 280 ); +lv_obj_set_align( ui_Panel1, LV_ALIGN_TOP_MID ); +lv_obj_clear_flag( ui_Panel1, LV_OBJ_FLAG_SCROLLABLE ); /// Flags +lv_obj_set_style_pad_left(ui_Panel1, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_right(ui_Panel1, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_top(ui_Panel1, 0, LV_PART_MAIN| LV_STATE_DEFAULT); +lv_obj_set_style_pad_bottom(ui_Panel1, 0, LV_PART_MAIN| LV_STATE_DEFAULT); + +ui_save_btn = lv_btn_create(ui_Panel1); +lv_obj_set_width( ui_save_btn, 50); +lv_obj_set_height( ui_save_btn, 40); +lv_obj_set_align( ui_save_btn, LV_ALIGN_LEFT_MID ); +lv_obj_add_flag( ui_save_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_save_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label3 = lv_label_create(ui_save_btn); +lv_obj_set_width( ui_Label3, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label3, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label3, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label3,"Save"); + +ui_pause_image = lv_img_create(ui_Panel1); +lv_obj_set_width( ui_pause_image, 80); +lv_obj_set_height( ui_pause_image, 60); +lv_obj_set_align( ui_pause_image, LV_ALIGN_RIGHT_MID ); +lv_obj_add_flag( ui_pause_image, LV_OBJ_FLAG_ADV_HITTEST ); /// Flags +lv_obj_clear_flag( ui_pause_image, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Panel6 = lv_obj_create(ui_menu_panel); +lv_obj_set_height( ui_Panel6, 50); +lv_obj_set_width( ui_Panel6, lv_pct(100)); +lv_obj_set_x( ui_Panel6, 0 ); +lv_obj_set_y( ui_Panel6, 380 ); +lv_obj_set_align( ui_Panel6, LV_ALIGN_TOP_MID ); +lv_obj_clear_flag( ui_Panel6, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label9 = lv_label_create(ui_Panel6); +lv_obj_set_width( ui_Label9, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label9, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label9, LV_ALIGN_LEFT_MID ); +lv_label_set_text(ui_Label9,"Video"); + +ui_Dropdown2 = lv_dropdown_create(ui_Panel6); +lv_dropdown_set_options( ui_Dropdown2, "Original\nFit\nFill" ); +lv_obj_set_width( ui_Dropdown2, 150); +lv_obj_set_height( ui_Dropdown2, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Dropdown2, LV_ALIGN_RIGHT_MID ); +lv_obj_add_flag( ui_Dropdown2, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags + +ui_reset_btn = lv_btn_create(ui_menu_panel); +lv_obj_set_width( ui_reset_btn, 100); +lv_obj_set_height( ui_reset_btn, 40); +lv_obj_set_x( ui_reset_btn, 0 ); +lv_obj_set_y( ui_reset_btn, 435 ); +lv_obj_set_align( ui_reset_btn, LV_ALIGN_TOP_MID ); +lv_obj_add_flag( ui_reset_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_reset_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label5 = lv_label_create(ui_reset_btn); +lv_obj_set_width( ui_Label5, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label5, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label5, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label5,"Reset"); + +ui_quit_btn = lv_btn_create(ui_menu_panel); +lv_obj_set_width( ui_quit_btn, 100); +lv_obj_set_height( ui_quit_btn, 40); +lv_obj_set_x( ui_quit_btn, 0 ); +lv_obj_set_y( ui_quit_btn, 485 ); +lv_obj_set_align( ui_quit_btn, LV_ALIGN_TOP_MID ); +lv_obj_add_flag( ui_quit_btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags +lv_obj_clear_flag( ui_quit_btn, LV_OBJ_FLAG_SCROLLABLE ); /// Flags + +ui_Label7 = lv_label_create(ui_quit_btn); +lv_obj_set_width( ui_Label7, LV_SIZE_CONTENT); /// 1 +lv_obj_set_height( ui_Label7, LV_SIZE_CONTENT); /// 1 +lv_obj_set_align( ui_Label7, LV_ALIGN_CENTER ); +lv_label_set_text(ui_Label7,"Quit"); + +} + +void menu_ui_init( void ) +{ +lv_disp_t *dispp = lv_disp_get_default(); +lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), true, LV_FONT_DEFAULT); +lv_disp_set_theme(dispp, theme); +ui_Screen1_screen_init(); +ui____initial_actions0 = lv_obj_create(NULL); +lv_disp_load_scr( ui_Screen1); +} diff --git a/components/menu/generated/ui.h b/components/menu/generated/ui.h new file mode 100644 index 00000000..016814a5 --- /dev/null +++ b/components/menu/generated/ui.h @@ -0,0 +1,63 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.2.3 +// LVGL version: 8.2.0 +// Project name: menu + +#ifndef _MENU_UI_H +#define _MENU_UI_H + +#ifdef __cplusplus +extern "C" { +#endif + + #include "lvgl.h" + +#include "ui_events.h" +extern lv_obj_t *ui_Screen1; +extern lv_obj_t *ui_menu_panel; +extern lv_obj_t *ui_menu_title; +extern lv_obj_t *ui_resume_btn; +extern lv_obj_t *ui_Label6; +extern lv_obj_t *ui_Panel3; +extern lv_obj_t *ui_volume_mute_btn; +extern lv_obj_t *ui_Label10; +extern lv_obj_t *ui_volume_dec_btn; +extern lv_obj_t *ui_Label11; +extern lv_obj_t *ui_Bar2; +extern lv_obj_t *ui_volume_inc_btn; +extern lv_obj_t *ui_Label8; +extern lv_obj_t *ui_Panel4; +extern lv_obj_t *ui_btn_slot_dec; +extern lv_obj_t *ui_Label2; +extern lv_obj_t *ui_slot_label; +extern lv_obj_t *ui_btn_slot_inc; +extern lv_obj_t *ui_Label1; +extern lv_obj_t *ui_Panel2; +extern lv_obj_t *ui_load_btn; +extern lv_obj_t *ui_Label4; +extern lv_obj_t *ui_slot_image; +extern lv_obj_t *ui_Panel1; +extern lv_obj_t *ui_save_btn; +extern lv_obj_t *ui_Label3; +extern lv_obj_t *ui_pause_image; +extern lv_obj_t *ui_Panel6; +extern lv_obj_t *ui_Label9; +extern lv_obj_t *ui_Dropdown2; +extern lv_obj_t *ui_reset_btn; +extern lv_obj_t *ui_Label5; +extern lv_obj_t *ui_quit_btn; +extern lv_obj_t *ui_Label7; +extern lv_obj_t *ui____initial_actions0; + + + + + + +void menu_ui_init(void); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/components/menu/generated/ui_events.h b/components/menu/generated/ui_events.h new file mode 100644 index 00000000..1b087cff --- /dev/null +++ b/components/menu/generated/ui_events.h @@ -0,0 +1,18 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.2.3 +// LVGL version: 8.2.0 +// Project name: menu + +#ifndef _UI_EVENTS_H +#define _UI_EVENTS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/components/menu/generated/ui_helpers.c b/components/menu/generated/ui_helpers.c new file mode 100644 index 00000000..7bc30be9 --- /dev/null +++ b/components/menu/generated/ui_helpers.c @@ -0,0 +1,232 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.2.3 +// LVGL version: 8.2.0 +// Project name: menu + +#include "ui_helpers.h" + +void _ui_bar_set_property( lv_obj_t *target, int id, int val) +{ + if (id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) lv_bar_set_value(target, val, LV_ANIM_ON); + if (id == _UI_BAR_PROPERTY_VALUE) lv_bar_set_value(target, val, LV_ANIM_OFF); +} + +void _ui_basic_set_property( lv_obj_t *target, int id, int val) +{ + if (id == _UI_BASIC_PROPERTY_POSITION_X) lv_obj_set_x(target, val); + if (id == _UI_BASIC_PROPERTY_POSITION_Y) lv_obj_set_y(target, val); + if (id == _UI_BASIC_PROPERTY_WIDTH) lv_obj_set_width(target, val); + if (id == _UI_BASIC_PROPERTY_HEIGHT) lv_obj_set_height(target, val); +} + + +void _ui_dropdown_set_property( lv_obj_t *target, int id, int val) +{ + if (id == _UI_DROPDOWN_PROPERTY_SELECTED) lv_dropdown_set_selected(target, val); +} + +void _ui_image_set_property( lv_obj_t *target, int id, uint8_t *val) +{ + if (id == _UI_IMAGE_PROPERTY_IMAGE) lv_img_set_src(target, val); +} + +void _ui_label_set_property( lv_obj_t *target, int id, char *val) +{ + if (id == _UI_LABEL_PROPERTY_TEXT) lv_label_set_text(target, val); +} + + +void _ui_roller_set_property( lv_obj_t *target, int id, int val) +{ + if (id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) lv_roller_set_selected(target, val, LV_ANIM_ON); + if (id == _UI_ROLLER_PROPERTY_SELECTED) lv_roller_set_selected(target, val, LV_ANIM_OFF); +} + +void _ui_slider_set_property( lv_obj_t *target, int id, int val) +{ + if (id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) lv_slider_set_value(target, val, LV_ANIM_ON); + if (id == _UI_SLIDER_PROPERTY_VALUE) lv_slider_set_value(target, val, LV_ANIM_OFF); +} + + +void _ui_screen_change( lv_obj_t *target, lv_scr_load_anim_t fademode, int spd, int delay) +{ + lv_scr_load_anim(target, fademode, spd, delay, false); +} + +void _ui_arc_increment( lv_obj_t *target, int val) +{ + int old = lv_arc_get_value(target); + lv_arc_set_value(target, old+val); + lv_event_send(target,LV_EVENT_VALUE_CHANGED, 0); +} + +void _ui_bar_increment( lv_obj_t *target, int val, int anm) +{ + int old = lv_bar_get_value(target); + lv_bar_set_value(target, old+val, anm); +} + +void _ui_slider_increment( lv_obj_t *target, int val, int anm) +{ + int old = lv_slider_get_value(target); + lv_slider_set_value(target, old+val, anm); + lv_event_send(target,LV_EVENT_VALUE_CHANGED, 0); +} + +void _ui_keyboard_set_target( lv_obj_t *keyboard, lv_obj_t *textarea) +{ + lv_keyboard_set_textarea(keyboard, textarea); +} + +void _ui_flag_modify( lv_obj_t *target, int32_t flag, int value) +{ + if (value==_UI_MODIFY_FLAG_TOGGLE) + { + if ( lv_obj_has_flag(target,flag) ) lv_obj_clear_flag(target,flag); + else lv_obj_add_flag(target,flag); + } + else if (value==_UI_MODIFY_FLAG_ADD) lv_obj_add_flag(target,flag); + else lv_obj_clear_flag(target,flag); +} +void _ui_state_modify( lv_obj_t *target, int32_t state, int value) +{ + if (value==_UI_MODIFY_STATE_TOGGLE) + { + if ( lv_obj_has_state(target,state) ) lv_obj_clear_state(target,state); + else lv_obj_add_state(target,state); + } + else if (value==_UI_MODIFY_STATE_ADD) lv_obj_add_state(target,state); + else lv_obj_clear_state(target,state); +} + +void _ui_opacity_set( lv_obj_t *target, int val) +{ + lv_obj_set_style_opa(target, val, 0); +} + +void _ui_anim_callback_free_user_data(lv_anim_t *a) +{ + lv_mem_free(a->user_data); + a->user_data=NULL; +} + +void _ui_anim_callback_set_x(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_x(usr->target, v); +} + +void _ui_anim_callback_set_y(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_y(usr->target, v); +} + +void _ui_anim_callback_set_width(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_width(usr->target, v); +} + +void _ui_anim_callback_set_height(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_height(usr->target, v); +} + +void _ui_anim_callback_set_opacity(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_style_opa(usr->target, v, 0); +} + +void _ui_anim_callback_set_image_zoom(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + lv_img_set_zoom(usr->target, v); +} + +void _ui_anim_callback_set_image_angle(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + lv_img_set_angle(usr->target, v); +} + +void _ui_anim_callback_set_image_frame(lv_anim_t* a, int32_t v) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + usr->val = v; + if ( v<0 ) v=0; + if ( v>=usr->imgset_size ) v=usr->imgset_size-1; + lv_img_set_src(usr->target, usr->imgset[v]); +} + +int32_t _ui_anim_callback_get_x(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_x_aligned(usr->target); +} + +int32_t _ui_anim_callback_get_y(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_y_aligned(usr->target); +} + +int32_t _ui_anim_callback_get_width(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_width(usr->target); +} + +int32_t _ui_anim_callback_get_height(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_height(usr->target); +} + +int32_t _ui_anim_callback_get_opacity(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_style_opa(usr->target, 0); +} + +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return lv_img_get_zoom(usr->target); +} + +int32_t _ui_anim_callback_get_image_angle(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return lv_img_get_angle(usr->target); +} + +int32_t _ui_anim_callback_get_image_frame(lv_anim_t* a) +{ + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + return usr->val; +} + +void _ui_arc_set_text_value( lv_obj_t *trg, lv_obj_t *src, char *prefix, char *postfix) +{ + char buf[_UI_TEMPORARY_STRING_BUFFER_SIZE]; + lv_snprintf(buf, sizeof(buf), "%s%d%s", prefix, (int)lv_arc_get_value(src), postfix); + lv_label_set_text(trg, buf); +} + +void _ui_slider_set_text_value( lv_obj_t *trg, lv_obj_t *src, char *prefix, char *postfix) +{ + char buf[_UI_TEMPORARY_STRING_BUFFER_SIZE]; + lv_snprintf(buf, sizeof(buf), "%s%d%s", prefix, (int)lv_slider_get_value(src), postfix); + lv_label_set_text(trg, buf); +} +void _ui_checked_set_text_value( lv_obj_t *trg, lv_obj_t *src, char *txt_on, char *txt_off) +{ + if (lv_obj_has_state(src,LV_STATE_CHECKED)) lv_label_set_text(trg,txt_on); + else lv_label_set_text(trg,txt_off); +} + + diff --git a/components/menu/generated/ui_helpers.h b/components/menu/generated/ui_helpers.h new file mode 100644 index 00000000..1fee6cf9 --- /dev/null +++ b/components/menu/generated/ui_helpers.h @@ -0,0 +1,117 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.2.3 +// LVGL version: 8.2.0 +// Project name: menu + +#ifndef _MENU_UI_HELPERS_H +#define _MENU_UI_HELPERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ui.h" + +#define _UI_TEMPORARY_STRING_BUFFER_SIZE 32 +#define _UI_BAR_PROPERTY_VALUE 0 +#define _UI_BAR_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_bar_set_property( lv_obj_t *target, int id, int val); + +#define _UI_BASIC_PROPERTY_POSITION_X 0 +#define _UI_BASIC_PROPERTY_POSITION_Y 1 +#define _UI_BASIC_PROPERTY_WIDTH 2 +#define _UI_BASIC_PROPERTY_HEIGHT 3 +void _ui_basic_set_property( lv_obj_t *target, int id, int val); + +#define _UI_DROPDOWN_PROPERTY_SELECTED 0 +void _ui_dropdown_set_property( lv_obj_t *target, int id, int val); + +#define _UI_IMAGE_PROPERTY_IMAGE 0 +void _ui_image_set_property( lv_obj_t *target, int id, uint8_t *val); + +#define _UI_LABEL_PROPERTY_TEXT 0 +void _ui_label_set_property( lv_obj_t *target, int id, char *val); + +#define _UI_ROLLER_PROPERTY_SELECTED 0 +#define _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM 1 +void _ui_roller_set_property( lv_obj_t *target, int id, int val); + +#define _UI_SLIDER_PROPERTY_VALUE 0 +#define _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_slider_set_property( lv_obj_t *target, int id, int val); + +void _ui_screen_change( lv_obj_t *target, lv_scr_load_anim_t fademode, int spd, int delay); + +void _ui_arc_increment( lv_obj_t *target, int val); + +void _ui_bar_increment( lv_obj_t *target, int val, int anm); + +void _ui_slider_increment( lv_obj_t *target, int val, int anm); + +void _ui_keyboard_set_target( lv_obj_t *keyboard, lv_obj_t *textarea); + +#define _UI_MODIFY_FLAG_ADD 0 +#define _UI_MODIFY_FLAG_REMOVE 1 +#define _UI_MODIFY_FLAG_TOGGLE 2 +void _ui_flag_modify( lv_obj_t *target, int32_t flag, int value); + +#define _UI_MODIFY_STATE_ADD 0 +#define _UI_MODIFY_STATE_REMOVE 1 +#define _UI_MODIFY_STATE_TOGGLE 2 +void _ui_state_modify( lv_obj_t *target, int32_t state, int value); + +void _ui_opacity_set( lv_obj_t *target, int val); + +/** Describes an animation*/ +typedef struct _ui_anim_user_data_t { + lv_obj_t *target; + lv_img_dsc_t **imgset; + int32_t imgset_size; + int32_t val; +} ui_anim_user_data_t; +void _ui_anim_callback_free_user_data(lv_anim_t *a); + +void _ui_anim_callback_set_x(lv_anim_t* a, int32_t v); + +void _ui_anim_callback_set_y(lv_anim_t* a, int32_t v); + +void _ui_anim_callback_set_width(lv_anim_t* a, int32_t v); + +void _ui_anim_callback_set_height(lv_anim_t* a, int32_t v); + +void _ui_anim_callback_set_opacity(lv_anim_t* a, int32_t v); + +void _ui_anim_callback_set_image_zoom(lv_anim_t* a, int32_t v); + +void _ui_anim_callback_set_image_angle(lv_anim_t* a, int32_t v); + +void _ui_anim_callback_set_image_frame(lv_anim_t* a, int32_t v); + +int32_t _ui_anim_callback_get_x(lv_anim_t* a); + +int32_t _ui_anim_callback_get_y(lv_anim_t* a); + +int32_t _ui_anim_callback_get_width(lv_anim_t* a); + +int32_t _ui_anim_callback_get_height(lv_anim_t* a); + +int32_t _ui_anim_callback_get_opacity(lv_anim_t* a); + +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t* a); + +int32_t _ui_anim_callback_get_image_angle(lv_anim_t* a); + +int32_t _ui_anim_callback_get_image_frame(lv_anim_t* a); + +void _ui_arc_set_text_value( lv_obj_t *trg, lv_obj_t *src, char *prefix, char *postfix); + +void _ui_slider_set_text_value( lv_obj_t *trg, lv_obj_t *src, char *prefix, char *postfix); + +void _ui_checked_set_text_value( lv_obj_t *trg, lv_obj_t *src, char *txt_on, char *txt_off); + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/components/menu/include/menu.hpp b/components/menu/include/menu.hpp new file mode 100644 index 00000000..61d39b30 --- /dev/null +++ b/components/menu/include/menu.hpp @@ -0,0 +1,186 @@ +#pragma once + +#include +#include +#include + +#include "event_manager.hpp" +#include "display.hpp" +#include "task.hpp" +#include "logger.hpp" + +#include "hal_events.hpp" +#include "i2s_audio.h" +#include "video_setting.hpp" + +class Menu { +public: + static constexpr size_t MAX_SLOT = 5; + enum class Action { RESUME, RESET, SAVE, LOAD, QUIT }; + + typedef std::function action_fn; + typedef std::function slot_image_fn; + + struct Config { + std::shared_ptr display; + std::string paused_image_path; + action_fn action_callback; + slot_image_fn slot_image_callback; + espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; + }; + + Menu(const Config& config) + : display_(config.display), + paused_image_path_(config.paused_image_path), + action_callback_(config.action_callback), + slot_image_callback_(config.slot_image_callback), + logger_({.tag="Menu", .level=config.log_level}) { + init_ui(); + // now start the menu updater task + using namespace std::placeholders; + task_ = espp::Task::make_unique({ + .name = "Menu Task", + .callback = std::bind(&Menu::update, this, _1, _2), + .stack_size_bytes = 6 * 1024 + }); + task_->start(); + // register events + espp::EventManager::get().add_subscriber(mute_button_topic, + "menu", + std::bind(&Menu::on_mute_button_pressed, this, _1)); + logger_.info("Menu created"); + } + + ~Menu() { + task_->stop(); + deinit_ui(); + espp::EventManager::get().remove_subscriber(mute_button_topic, "gui"); + } + + size_t get_selected_slot() const { + return selected_slot_; + } + + void select_slot(size_t slot) { + selected_slot_ = std::clamp(slot, (size_t)0, MAX_SLOT); + update_slot_display(); + } + + void next_slot() { + selected_slot_++; + // if we go too high, cycle around to 0 + if (selected_slot_ > MAX_SLOT) + selected_slot_ = 0; + update_slot_display(); + } + + void previous_slot() { + selected_slot_--; + // if we go less than 0, cycle around to the MAX + if (selected_slot_ < 0) + selected_slot_ = MAX_SLOT; + update_slot_display(); + } + + void set_mute(bool muted); + + void toggle_mute() { + set_mute(!is_muted()); + } + + void set_audio_level(int new_audio_level); + + int get_audio_level(); + + void set_video_setting(VideoSetting setting); + + bool is_paused() { return paused_; } + void pause() { paused_ = true; } + void resume() { + update_shared_state(); + update_slot_display(); + update_pause_image(); + paused_ = false; + } + +protected: + void init_ui(); + void deinit_ui(); + void update_slot_display(); + void update_slot_label(); + void update_slot_image(); + void update_pause_image(); + + void update_shared_state() { + set_mute(is_muted()); + set_audio_level(get_audio_volume()); + set_video_setting(::get_video_setting()); + } + + VideoSetting get_video_setting(); + + void on_mute_button_pressed(const std::string& data) { + set_mute(is_muted()); + } + + bool update(std::mutex& m, std::condition_variable& cv) { + if (!paused_) { + std::lock_guard lk(mutex_); + lv_task_handler(); + } + { + using namespace std::chrono_literals; + std::unique_lock lk(m); + cv.wait_for(lk, 16ms); + } + // don't want to stop the task + return false; + } + + static void event_callback(lv_event_t *e) { + lv_event_code_t event_code = lv_event_get_code(e); + auto user_data = lv_event_get_user_data(e); + auto menu = static_cast(user_data); + if (!menu) { + return; + } + switch (event_code) { + case LV_EVENT_SHORT_CLICKED: + break; + case LV_EVENT_PRESSED: + menu->on_pressed(e); + break; + case LV_EVENT_VALUE_CHANGED: + menu->on_value_changed(e); + break; + case LV_EVENT_LONG_PRESSED: + break; + case LV_EVENT_KEY: + break; + default: + break; + } + } + + void on_pressed(lv_event_t *e); + void on_value_changed(lv_event_t *e); + + // LVLG menu objects + lv_img_dsc_t state_image_; + lv_img_dsc_t paused_image_; + + std::vector state_image_data_; + std::vector paused_image_data_; + + lv_obj_t *previous_screen_{nullptr}; + + int selected_slot_{0}; + std::atomic paused_{true}; + std::shared_ptr display_; + std::string paused_image_path_; + action_fn action_callback_; + slot_image_fn slot_image_callback_; + std::unique_ptr task_; + espp::Logger logger_; + std::recursive_mutex mutex_; +}; diff --git a/components/menu/squareline/menu.sll b/components/menu/squareline/menu.sll new file mode 100644 index 00000000..6a1c6234 --- /dev/null +++ b/components/menu/squareline/menu.sll @@ -0,0 +1 @@ +{"name":"menu.spj","depth":2,"width":320,"height":240,"rotation":0,"offset_x":0,"offset_y":0,"shape":"RECTANGLE","description":"The menu that the user can open while playing a rom.","board":"ESP-BOX","board_version":"1.0.0","editor_version":"1.2.3","image":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDyaONYVCqBnufWpAxyOaRvvGgdRVi6HcWOg6bNYW0sltl3iVmO9uSQPep/+Ed0r/n1/wDIjf41R0LXrY2aWt1KsUkQ2gucBgOnNa/9p6f/AM/1t/3+X/GvqaEcJOmpWj9yPla7xcKjjeX3srf8I7pX/Pr/AORG/wAaP+Ed0r/n1/8AIjf41Z/tPT/+f62/7/L/AI0f2np//P8AW3/f5f8AGtvZYT+WP3Iy9piu8vxK3/CO6V/z6/8AkRv8aP8AhHdK/wCfX/yI3+NWf7T0/wD5/rb/AL/L/jTZNX06NC7XsBA7LIGP5Ck6WEX2Y/gHtMW+svxOR8R2kFhqEcVsnloYgxGSecn1+lY+4+tXtY1H+09QadVKoAEQHrgf5NUK+YxLhKrJw2ufU4aM40YqpvbUXcfWjcfWkorA3sLuPrRuPrSUUBYXcfWjcfWkooCwu4+tG4+tJRQFhdx9aNx9aSigLC7j60bj60lFAWF3H1o3H1pKKAsLuPrRuPrSUUBYXcfWjcfWkooCx9K6v8LfBlrot9cQ6Ntlit5HRvtUxwwUkHl6xfAPw88K634Rtr7UNL865d5Az/aJVyAxA4DAV6ne24vtPuLbdhZ4mj3dcbhjP615j4Q8XWvgyxl8O+IoprS4tZWKOIyyupOe3vnB6EYqBWOi/wCFTeCP+gJ/5NTf/F0f8Km8Ef8AQE/8mpv/AIunf8LS8J/8/wDL/wCA7/4Uf8LS8J/8/wDL/wCA7/4UBoQXPwp8GR2szw6B5kqoxRPtcw3Njgffrw1dH082fmh86h9qEQ07ypOUx13Z9fl29a95/wCFpeE/+f8Al/8AAd/8Kzx42+Ho1L+0QkP23OfP+xNvz6529fegLIx/FPw78L6c/h8W2keSbvU4YLhftMrZRs7lyW/Uc034i/D3wtoXgTUtS03S/Iu4fK8uT7RK2Myop4ZiOhParupeKIfGfibQLDQree4htL6O7uJyhVVCn39s9fYCtn4uED4Yavz18nH/AH+Smh2Kmr/C3wZa6LfXEOjbZYreR0b7VMcMFJB5euS0XwP4cu/hRfa3Pp2/UYrW6kSbz5BhkDbTtDY4wO1ezXtuL7T7i23YWeJo93XG4Yz+tePWviSLw14I13wjrcEttfpb3EcJCErJvVsc/U8Hpg0hWPFCxyeajkjWZSrAZ7H0p56mhfvCrDoDfeNA6ihvvGgdRQHQD1NJSnqaSgYUUUUwCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA+jvhv8SNN1rRrbTdSu47bVbdBERMwUTgDAZSeCcdR1zXoFxY2d8FNzawXAH3fMjD4+ma+MaKmwH2L/wAI/ov/AECNP/8AAZP8KP7A0YdNIsP/AAGT/CvjqijlA+xf+Ef0X/oEaf8A+Ayf4UDw/oo6aRYf+Ayf4V8dUUcoH2aEsdLtmYLb2kA5YgLGo+vQV4d8XfiFZa1AmgaPMJ7ZJBJc3CH5XI6Kp7gdSfYYryOihID6O+G/xI03WtGttN1K7jttVt0EREzBROAMBlJ4Jx1HXNdR41tba58F61LLBDK8en3DRuyBip8tjkHtXyTSjqKLAB6mhfvCg9TQv3hTF0BvvGgdRQ33jSUB0FPU0lPwDyeKTavrQFxtFO2r60bV9aLhcbRTtq+tG1fWi4XG0U7avrRtX1ouFxtFO2r60bV9aLhcbRTtq+tG1fWi4XG0U7avrRtX1ouFxtFO2r60bV9aLhcbRTtq+tG1fWi4XG0U7avrRtX1ouFxtFO2r60bV9aLhcbRTtq+tG1fWi4XG0U7avrRtX1ouFxtFO2r60bV9aLhcbRTtq+tG1fWi4XG0U7avrRtX1ouFxtFO2r60bV9aLhcbSjqKXavrS4A5HNAXGnqaF+8KSlX7woDoDfeNA6ihvvGgdRQHQekUs8myKN5G/uopJqb+zNQ/wCfG5/78t/hXcaFZxWmlwsijfKgkdu5J5/TNaVe5RyhSgpTlqzw6ucOM3GEdEea/wBmah/z43P/AH5b/CoJYZYH2SxvG3911INeo1ma9ZxXekzs6jfEhkRu4IGf1xRWyhRg5Qlqgo5w5TUZx0Z59RRRXiHuhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQA+KGWd9kUbyN/dRSTU/9mah/wA+Nz/35b/Cu30GzitNJgZFG+VBI7dySM/pmtOvbo5QpQUpy1Z4VbOHGbjCOiPNf7M1D/nxuf8Avy3+FQvFLBJsljeNv7rqQa9QrN12ziu9LmZ1G+JDIjdwRz+uKK2UKMHKEtUFLOHKajOOjPPj1NC/eFB6mhfvCvDPc6A33jQOoob7xoHUUB0PSdN/5BVn/wBcE/8AQRV2JFklRHkWNWIBdgSFHqcAmqWmc6VZ/wDXFP8A0EVar7Wl/DXofE1P4j9Sa6higm2RXMdwmM741YD6fMAaztT/AOQTef8AXB//AEE1bqpqnGk3n/XB/wD0E0VFam/QdPWovU82ooor4s+2CiiigAooooAKKKKACul8KxXjRXsttYaS8cezzb3U1Vo4Ac4ADnaS3ptJ4471zVauka9PpMNzbfZbS8tLnaZba6QshZc7WGCGBGTyCOppAdWJtBn12drSKya4GmANcQ2Dy2cd0JBucRFSdmzC5243HO3pVu/02wg1XS9RuLSwa3sNIN/dpBbGKK4k81xGGRlU/OxjGCBxnAxiuFm1u6Opi/sgmmTKoVBYZhCDGOCDnPqSc1BNqd/cm4M99cy/aCpn3ys3mlfulsn5sds9KAO8sdG0ybXdR1SKC0+zzaaNRsIJo3eFGZ1VwURSWEbeYNoBHygnisDxfYyQppt9IdK/0qJ9v9n20lvuCt99o2RQM5wCowdprBi1G+ga3MN5cRm2JMBSVh5RPXbg/Ln2pt3e3WoXDXF7czXM7felmkLsfqTzQB2OgeZbaTZXF7ZeHLTTHLbp9QhEst0oYhio+Z+Pu/KFGR1zmp9P0zQdTgtwsQi0+48TeQkrgCQW5XKoW6jjHfg81z1n4pmt9Ot7K50zTb9LXcLd7uFmaIE7ioKsMjJJw2epqrJrJk8OtpJt1BN8bzzVOAMpt2hccevX8KAOlvIpNR0TXjqXh610ttP2fZpILbyWSQyKvkk9ZMqWPOT8uc1neOFjs9WTS7eytre2tYYvLaOBVdy0SFi74y5yT1PGaxZtb1a5+z+fqd7L9mIaDfcO3lEdCuT8p+lWNf8AEmqeJbxbnUrmSTYAI4vMYpH8qglQxOCdoJ9TQBaFtB/wrw3Xkx/aP7VEfm7Rv2+UTtz1xnnFc/Wvd+IJLnw/b6MlhZW8EUomaSFX3yuF27mLMRyPQCsigAooopgFFFFABRRRQAUUUUAek6Z/yCbP/rgn/oIrW02xOoXscHmRoCRuMkqpxkDgt1PPSsnS+dJs/wDrgn/oIq6jtG6uhwykEEdjX2cE3SVux8TNpVXfuW9VsDp1/Lb+ZG6hm2lJVc4BIGdvQ8dKyNS/5BV5/wBcH/8AQTVySRpZGkdizuSzE9yap6nxpV5/1xf/ANBNE01SalvYINOquXa55sepoX7woPU0L94V8Wfa9Ab7xoHUUN940lAdDoNI8SGwh+zXMbSRKfkZfvL7c9a1P+Ev0/8A543P/fK//FVxuN3Io2H2rup5lXpxUE9EcFTLsPUk5Nas7L/hL9P/AOeNz/3yv/xVZes+JDfwG2to2jib77N95vbjpWDsPtRsPtRUzKvUi4t6MdPLsPTkppaobRTth9qNh9q4TuuhtFO2H2o2H2oC6G0U7YfajYfagLobRTth9qNh9qAuhtFO2H2o2H2oC6G0U7YfajYfagLobRTth9qNh9qAuhtFO2H2o2H2oC6G0U7YfajYfagLobRTth9qNh9qAuhtFO2H2o2H2oC6G0U7YfajYfagLobRTth9qNh9qAuhtFO2H2o2H2oC6N7RvEhsIBbXMbSRL9xl+8vtz1rU/wCEv0//AJ43P/fK/wDxVcbsPtRsPtXfTzKvTiop6I4amXYepJza1Z2X/CX6f/zxuf8Avlf/AIqsvV/Ehv4fs1tG0cTH52b7ze3HSsHYfajG3k0quZV6kXBvRip5dh6clJLVCHqaF+8KSlX7wrhO/oDfeNIOTSt940DqKA6CknOB0pMn1NdjoWg2ws0urqJZZJRuAcZCg9OK1/7M0/8A58bb/vyv+FerSympOCk2lc8qrm1KE3FRbseb5PqaMn1Nekf2Zp//AD423/flf8KyNe0G2NlJdWsSxSRDcQgwGA68UVcpqQg5Jp2Clm1Kc1Fxaucdk+poyfU1reH9KTU7tzNnyYgCwH8RPQfoa7JdK09VAFjbYHrEDWeGy6pXhzp2Rrisxp4efI1dnm+T6mjJ9TXpH9maf/z423/flf8ACo59F064iMZtIkz/ABRoFI/EV0PJqltJI51nNO+sWed5PqaMn1NWL+0axvprZjkxtgH1HUH8qrV5EouLcXuj14yUoqS2YuT6mjJ9TSUVJQuT6mjJ9TSUUALk+poyfU0lFAC5PqaMn1NJRQAuT6mjJ9TSUUALk+poyfU0lFAC5PqaMn1NJRQAuT6mjJ9TSUUALk+poyfU0lFAC5PqaMn1NJRQAuT6mjJ9TSUUALk+poyfU12Og6DbCyjurqJZZJRuAcZCg9OK1/7M0/8A58bb/vyv+FerSympOCk2lc8mrm1KE3FRbseb5PqaUE5welej/wBmaf8A8+Nt/wB+V/wrI13QbY2b3VrEsUkQ3EIMBgOvFFXKakIOSadgpZtSnNRcWrnGng0q/eFB6mhfvCvKPV6A33jQOoob7xoHUUB0PatE0Szaw0vzTcMj6MLx1RgGLAHgHBwPl9DT5dOsrjSri7s4ryBoGRStwwcSbjjAIUc98elLoviCzjttJkC3MCxaMlmzxAFlk2n515HrnqKdqOsxXGli0W6v7yTzllWa8wDHgEYX5mPOeeew4r6ej7a0d+n9dtj5et7G8rW6/wBd9xJ7HRdPuDZXs1690h2zSwbfLjbuADy2Omciquq6JDa6P4kF07yNZWm6JomAD7xhScg8YYHFWp77RdQuDe3sN4ly53TRQbfLkbuQTyuevQ9apazra3Oi+IzNGVkvbYLGqD5UCYwD/wABXFVU9r7N77a/etvlcmn7L2i230+57/OxyHgBrBf7R+3RXMn+r2eRKqY+9nOVOe1dcL20jyiaXbyIGO1ppJC5GeM7WUZ+gFcP4M/5ff8Atn/7NXVUsugnhovXr1fdlZlNrFSWnTouyNzR9Jt9U+0zXLm1jZxDbhPumZslV5ydoxzznpzVax06Fo7q51B5Ira2YI6xgb3c5wozwOhJJ6Ypl3fxvp9jZ2wdEgBeQngtKx5PB6ABQPpV+XWrK5muVuLeU296sck+zCsk6g5dOoIOTwcfe9q3ftdWtn+Fn+q1MF7LRdV+N1+j0PJ/Fxtz4nvDaLKsHybRKwZvuLnJAA65rErb8XC3Hie8Fo0rQfJtMqhW+4ucgEjrmsSvlsR/Gn6v8z6rD/wYei/IciNLIsaKWdiFUDuTXXQeD7YRD7RcStJ38vAH6g1yKO0UiyIxV1IZSOxFddB4wtjEPtFvKsnfy8EfqRXZgPq137f5XOPMPrVl7DbrYk/4RDT/APntc/8AfS//ABNH/CIaf/z2uf8Avpf/AImj/hL9P/543P8A3yv/AMVR/wAJfp//ADxuf++V/wDiq9L/AITvI8z/AIUfMP8AhENP/wCe1z/30v8A8TWTq/h9NOCSRyO8THHzYyDWt/wl+n/88bn/AL5X/wCKrJ1fxAmohI443SJTn5sZJrnxP1H2b5LX6WN8N9f9oue9vMyvs6erUfZ09Wo+0J6NR9oT0avJ9w9X94H2dPVqPs6erUfaE9Go+0J6NR7gfvA+zp6tR9nT1aj7Qno1H2hPRqPcD94H2dPVqPs6erUfaE9Go+0J6NR7gfvA+zp6tR9nT1aj7Qno1H2hPRqPcD94H2dPVqPs6erUfaE9Go+0J6NR7gfvA+zp6tUUsXl4IOQal+0J6NUUsvmYAGAKUuW2hUPaX1I6KKKzNz1fSriwh0fTmjsWmf7KglFzKShbavKhNpHfqT1q7FGNXvra0tbKC2eR9uYi5znudzHgcnjHesTTP+QTZ/8AXBP/AEEVtabfRWEd5Jtc3UkJigIAwm7hmznIO3IH1r7CMXGknHe3c+NnJSqtS2uWtQ0aL+1bWDSpWmtr3At5JOuc7SDgdiD26EVT1uLQotJ1GCOa+kmS3lCz4Xy3YKcfL1AJ75/CrFlq32SwSPDfaLa5W4tWxkA/xKeehwp49Peq+ty6FLpOozxw30cz28pWDKmNGKn+LqQD2x+NY1PaKDUr2Se3X1+Xy3NafI5pxtdtb/p8/nsePnqaF+8KD1NC/eFfKH1nQG+8aB1FDfeNIODQHQ7LQtetjZpa3UqxSRDaC5wGA6c1r/2np/8Az/W3/f5f8a84IOcjpSYPoa9Wlm1SEFFpOx5VXKaU5uSk1c9I/tPT/wDn+tv+/wAv+NZGva9bCyktbWVZZJRtJQ5Cg9ea47B9DRg+hoq5tUnBxSSuFLKaUJqTk3Y1vD+qppl24mz5MoAYj+Ejof1Ndkuq6eygi+tsH1lArzfB9DRg+hrPDZjUoQ5Ero1xWXU8RPnbsz0j+09P/wCf62/7/L/jUc+tadbxGQ3cT4/hjcMT+ArzvB9DRg+hroec1LaRRzrJqd9ZMsX9219fTXLDBkbIHoOgH5VWpcH0NGD6GvIlJybk92evGKjFRWyEopcH0NGD6GpKEopcH0NGD6GgBKKXB9DRg+hoASilwfQ0YPoaAEopcH0NGD6GgBKKXB9DRg+hoASilwfQ0YPoaAEopcH0NGD6GgBKKXB9DRg+hoASilwfQ0YPoaAEopcH0NGD6GgDsdB162NlHa3UqxSRDaC5wGA6c1r/ANp6f/z/AFt/3+X/ABrzfB9DRg+hr1aWbVIQUWk7Hk1cppTm5KTVz0j+09P/AOf62/7/AC/41ka7r1sLN7W1lWWSUbSUOQoPXmuOwfQ0oBzk9KKubVJwcUkrhSymlCak5N2EPU0L94VJb4Nwv40swxctj/PFeUeqRN940lK33jSUDQZIpcn1NJRQAuT6mjJ9TSUUALk+poyfU0lFAC5PqaMn1NJRQAuT6mjJ9TSUUALk+poyfU0laGhwR3OtW0Ug3IWJIPfAJ/pV04Oc1BdXYipNQg5voriwaJqdzEJIrVyh5BZgufzNS/8ACOav/wA+p/7+r/jXfUV9Asno21b/AA/yPnnnFa+kV+P+ZwP/AAjmr/8APqf+/q/40f8ACOav/wA+p/7+r/jXfUU/7Hod3+H+Qv7Yr9l+P+ZwP/COav8A8+p/7+r/AI0f8I5q/wDz6n/v6v8AjXfUUf2PQ7v8P8g/tiv2X4/5nA/8I5q//Pqf+/q/40f8I5q//Pqf+/q/4131FH9j0O7/AA/yD+2K/Zfj/mcD/wAI5q//AD6n/v6v+NH/AAjmr/8APqf+/q/4131FH9j0O7/D/IP7Yr9l+P8AmcD/AMI5q/8Az6n/AL+r/jUU+ianbRGSW1cIOSVYNj8jXodFJ5PRto3+H+Q1nFa+sV+P+Z5Zk+poyfU1f1yCO21q5ijG1AwIA7ZAP9az6+fqQcJuD6Ox9DTmpwU11Vxcn1NGT6mkoqCxcn1NGT6mkooAXJ9TRk+ppKKAFyfU0ZPqaSigBcn1NJkmiigCW2/4+F/H+VLP/wAfTf57Ult/x8L+P8qWf/j6b/PagTIm+8aSlb7xpKBoKKKKYBRRRQAUUUUAFFFFABRRRQAVq+G/+Q/bf8D/APQTWVWr4b/5D9t/wP8A9BNb4X+PD1X5mGK/gT9H+R39FFFfYnxZaTT5n01r5dpjWYQlRndkgnPTpxVpdBuzdi2Z4UdYfOm3tgQL/tnHB5HAz1Her+kTXA8Ozw2Wox2lybtXO66EJKbCDySMjOKsT61Da3aJPKl3JLaCG7uIkWQFw+5SAw2uQAoJPX14rjlWq8zjFHZGlS5VKRiNpYF2kA1CxZHQv54lOwD0ORkHjpjNS/2BcmeJI5raSGWNpVuFc+WEXhiSQCMfSrh1uwGoWri0VooUcGX7NEjszDAbYo2/LxgHPfmmTazC1xdObi9uRLZtbq06qCGLA8AEgLgdqfPX00/r+v8AhhclHW7/AK/r/hyrNoU8S2bpc200d3KYonjckZGOTkZH3vrx0qv/AGdNm+G5P9CGZOTz84Tjj1I9Ks22pww2mnRMsha2vGnfAGCp2cDnr8pq8dU0QNqDLDfEX5IcHaPJG7dlTn5jkDg4+tPnqx0av/w/+QuSlLVO3/Df5mZDo13cCy8rYxvA5QbsbQpwxbPAHBP0qO9sBZqjLeWtyrEjMDk7SPUEA/j0rUj122s7qxS1ile0toZImMoXe/mZ3HHKjGeAc9OetV9V1O0ubOO2togxEm9p2tooW6YCgIOnOeTzx0pxnWc1daf8P+lglCkoOz1/4b9bmPRRRXScpwHiT/kP3P8AwD/0EVlVq+JP+Q/c/wDAP/QRWVXx2K/jz9X+Z9phf4EPRfkFFFFYG4UUUUAFFFFABRRRQAUUUUAS23/Hwv4/ypZ/+Ppv89qS2/4+F/H+VLP/AMfTf57UhMib7xpKVvvGkoGgooopgFFFFABRRRQAUUUUAFFFFABWr4b/AOQ/bf8AA/8A0E1lVNa3MlndR3Ef342yM9/atKM1CpGb6NMyrwc6UoLdpo9OorFg8UabLEGlkaF+6shOPxAqX/hJNJ/5+/8AyG/+FfWrF0Gr86+9HyLwldO3I/uZq0Vlf8JJpP8Az9/+Q3/wo/4STSf+fv8A8hv/AIUfWqH86+9B9Vr/AMj+5mrRWV/wkmk/8/f/AJDf/Cj/AISTSf8An7/8hv8A4UfWqH86+9B9Vr/yP7matFZX/CSaT/z9/wDkN/8ACj/hJNJ/5+//ACG/+FH1qh/OvvQfVa/8j+5mrRWV/wAJJpP/AD9/+Q3/AMKP+Ek0n/n7/wDIb/4UfWqH86+9B9Vr/wAj+5mrRWV/wkmk/wDP3/5Df/Cop/FGmxRFopGmfsqoRn8SKHi6CV+dfegWErt25H9zOa8Sf8h+5/4B/wCgisqprq5kvLqS4k+/I2Tjt7VDXyVaanUlNdW2fXUIOFKMHukkFFFFZmoUUUUAFFFFABRRRQAUUUUAS23/AB8L+P8AKln/AOPpv89qS2/4+F/H+VLP/wAfTf57UhMib7xpKVvvGkoGgooopgFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBLbf8fC/j/Kln/4+m/z2pLb/AI+F/H+VLP8A8fTf57UhMib7xpKVvvGkoGgooopgFFFFABRRRQAUUUUAFT2Vt9sv7e137POlWPdjOMkDOPxqCrelzR2+rWc8rbY450d2xnADAmkBs61omgaTPfWaa7eT3trI8XlnTgiM6kgjd5pwMjrikm8K+T4mv9G+25+yWstx53lff2QmXGM8ZxjOff2rZ8Xara6r/acsHiPSJ4Jp2lit49KMcxUvkDzPJBzjqS3POSajl8e2Datc6vH4biGoXEXkO0l0zRGMqEbKAA7ioIzkDnOM0Ac/a+H5bzRba+hmBluNQFgkBX+IqCDuz6tjGK1LnwlpyWesyWmvfaLjSUzPCbQoHbzFQ7G3cqCTyQD045yIW8U2sB0uHTdKa1srG9F80T3JkeaTK9X2jAwoAGOMnrVKHXvKbXT9mz/asRj/ANZ/qsyrJnp833cdutAF+Pwgu4STX7rbLpcepTNFb75FV2C7VTcNxBYckgYyeKlPg23N7ZCPVi1lPp0moyXBtiGjjQuCNm7lvk6ZAyeuBky32uWthqeiXSGS4EWjwQsbO8MMkT85w65ww6EEHr0q7aeNdOv9UvbnWYLryl0mSytgbtndgQxKu5RiWYsfmwAvpijUDBtvCx1K1hm0y6M5uNTGnwLJF5e7K7g55O3r05x60t54csP7OvbrSdaXUGsNpuYzbmL5CwXfGSTuXcQOQDznFT2muvpmhQzacIYjb6z9rgSS4DyrhBgMu0bl7FuMnIwKgvPEVh/Z17baToq6e9/hbmQ3Bl+QMG2RggbV3BTySeAM0AOfwps8YT6B9tz5UUknn+V12QmXG3PfGOvv7Vn+HdH/ALf8QWWlef5H2mTZ5mzft4J6ZGenrW9f+NrG6vrzVINBEGq3Fu1uJ/tRZEVo/LLbNo+fbkZzjnOKyvBmoWuleMNMvr6XyraGXdJJtLbRg9gCaAK1/wCHNa0pY21HS7u0SRtqvPCyKT6ZIxWzqHg21sYdaRdVle80dAZ4XsyiuTIqHY245UFupAJ4wOchVuNJ0Lw7q1nBrg1SXUIkiSCCCRIoyHVvMYyBeQFIGAfvGm3/AI1a58PT6TbW95ElwqJJ5+oSTxoqsGxGjD5OVHUsccd6AJk8EWZu7jTpNdCapbWj3M1v9lJQbYzJsV93LdAeABzjOMVW0fwlb63pxktdSmN2sLyyJ9hfyItqltrzZwpwOuCORzUL+K9/iy9137Fj7VDNF5Pm/d8yIx53Y5xnPT2pzeKILjw3b6VeWE8jWsLwwNFetHFyzMHaLaQzAt1yM4GaAC48M2Gn2ca6hrXkalJbC4W1W1Z0UMu5FdweGII6KcZGTTLbw5Yrp9jPqmsrYz36l7aIW5kATcVDyNkbAWU9AxwM4rWtfiVf21rAyrefb7eAQRuuoSLb4C7VYwdCwGO4BIyQay7PxJYGwsINU0VL6ewBS2m+0NGNm4sEkUA71DMx4KnnGaAMzXtL/sTX7/S/O877JM0Xmbdu7BxnGTj86zq3fGlxDdeNtZuLeaOaGS7kZJI2DKwJ6gjgisKgAooopgFFFFABRRRQAUUUUAS23/Hwv4/ypZ/+Ppv89qS2/wCPhfx/lSz/APH03+e1ITIm+8aSmxyLMoZSM9x6U/afSgExKKXafSjafSgdxKKXafSjafSgLiUUu0+lG0+lAXEopdp9KNp9KAuJRS7T6UbT6UBcSil2n0o2n0oC4lFLtPpRtPpQFxKKXafSjafSgLiUUu0+lG0+lAXEopdp9KNp9KAuJRS7T6UbT6UBcSil2n0o2n0oC4lFLtPpRtPpQFxKKXafSjafSgLiUUu0+lG0+lAXEopdp9KNp9KAuJRS7T6UbT6UBcSil2n0o2n0oC5Jbf8AHwv4/wAqWf8A4+m/z2qNdysGXgimTTeWC7nLHoPWgTP/2Q==","force_export_images":false,"pointfilter":false,"theme_simplified":false,"theme_dark":true,"theme_color1":5,"theme_color2":0,"exportFolderPath":"/Users/bob/esp-cpp/esp-box-emu/components/menu/generated","projectExportFolderPath":"/Users/bob/esp-cpp/esp-box-emu/components/menu/squareline","backup_cnt":11,"autosave_cnt":0,"lvgl_version":"8.2.0","callfuncsexport":"C_FILE","lvgl_include_path":""} \ No newline at end of file diff --git a/components/menu/squareline/menu.spj b/components/menu/squareline/menu.spj new file mode 100644 index 00000000..4f41cad6 --- /dev/null +++ b/components/menu/squareline/menu.spj @@ -0,0 +1,9223 @@ +{ + "root": { + "guid": "GUID22111204-472670S796257", + "deepid": 0, + "children": [ + { + "guid": "GUID25379947-472671S269257", + "deepid": -819125744, + "children": [ + { + "guid": "GUID47601968-472863S306257", + "deepid": 1938164396, + "children": [ + { + "guid": "GUID31231652-473373S988257", + "deepid": -1759796579, + "locked": false, + "properties": [ + { + "nid": -1168951726, + "strtype": "OBJECT/Name", + "strval": "menu title", + "InheritedType": 10 + }, + { + "nid": 1951489133, + "strtype": "LABEL/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -23987501, + "strtype": "LABEL/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1138651574, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1202746772, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 596632477, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -1107605690, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": -2068611080, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 514166785, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 834090453, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -229901605, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -200733565, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1664009333, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -931222528, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1573757838, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1626510289, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1650040554, + "strtype": "LABEL/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 323297519, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 678414772, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 539332422, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -386438660, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1162762786, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1190801012, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1848773353, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -13432167, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1512601134, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2095861269, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -391340092, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -1138352299, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1293058613, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2025662424, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1868675785, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1250112172, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1372564053, + "strtype": "LABEL/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -318905041, + "strtype": "LABEL/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1539337188, + "strtype": "LABEL/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1797108554, + "strtype": "LABEL/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 304865421, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 781657167, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 578175868, + "strtype": "LABEL/Text", + "strval": "Emulation Paused", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -397118578, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": 396729725, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID88885274-130823S40299", + "deepid": 479922634, + "children": [ + { + "guid": "GUID29413501-131233S911299", + "deepid": 559763650, + "locked": false, + "properties": [ + { + "nid": -845026132, + "strtype": "OBJECT/Name", + "strval": "Label6", + "InheritedType": 10 + }, + { + "nid": -1043742543, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -194672644, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1258600113, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 232217360, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 387018032, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 1787759826, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 374896475, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 762400863, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1717422414, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 314957705, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1509928703, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -936673052, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1135872347, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1584034877, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -306044644, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 830726017, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -905095685, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -825338319, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 89789988, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -371211363, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 891303585, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -834144628, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1053130173, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -91481824, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -783554170, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -831849829, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 1920246292, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -476221975, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1713455936, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1587298178, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1118674738, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 301877554, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 647660608, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1496396698, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1876859868, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1160966353, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1627984721, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": -2111839467, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -1567556066, + "strtype": "LABEL/Text", + "strval": "Resume", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -66923358, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": 1394652811, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": 1181461751, + "strtype": "OBJECT/Name", + "strval": "resume btn", + "InheritedType": 10 + }, + { + "nid": -1128726567, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1898667341, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 352540670, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -402580376, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 35 + ], + "InheritedType": 7 + }, + { + "nid": 1169120005, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 40 + ], + "InheritedType": 7 + }, + { + "nid": -262640015, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": -510634120, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1894442145, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -594192991, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1333441936, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1012324030, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -223397467, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -344340152, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -533597132, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2000521597, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 94193184, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1260700582, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -257585286, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -94325711, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -144872061, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 835346505, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1689494582, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 188190075, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1358991350, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1448183351, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 955298056, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 862436299, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -160256378, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 634914334, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -515106069, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1158841319, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2043805450, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1536668838, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 642871156, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1014079968, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1831285925, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -1873579023, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON", + "tree_closed": true + }, + { + "guid": "GUID30826657-133251S6299", + "deepid": -702306247, + "children": [ + { + "guid": "GUID73846368-135509S89299", + "deepid": 123173724, + "children": [ + { + "guid": "GUID80905254-138672S919299", + "deepid": -82283583, + "locked": false, + "properties": [ + { + "nid": -189040679, + "strtype": "OBJECT/Name", + "strval": "Label10", + "InheritedType": 10 + }, + { + "nid": -2019623969, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1724736563, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1197205127, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -746048533, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1746358605, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 1867277056, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 919748064, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -623934078, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 608212274, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1070477847, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -897502753, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1614722586, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -867771619, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210964478, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1139308667, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2041294127, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1366956291, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1287964222, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -253734909, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -546368836, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 712348000, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1276990420, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -919690796, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1250582314, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 2122589818, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 409247979, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 115889015, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 913844338, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1284327502, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 349923231, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1187236620, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1084584241, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1581189773, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1839926175, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1025123773, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1676133045, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1996400420, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": -32523550, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -395300118, + "strtype": "LABEL/Text", + "strval": "LV_SYMBOL_MUTE", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1557579669, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": 1195661681, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": -1815037757, + "strtype": "OBJECT/Name", + "strval": "volume mute btn", + "InheritedType": 10 + }, + { + "nid": 1556428643, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 631469690, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -292557131, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1059365551, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 2104284624, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 30, + 30 + ], + "InheritedType": 7 + }, + { + "nid": 204964743, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": -437951868, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 288273759, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1436063068, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1129080569, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1360420414, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1512020584, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2050450281, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1815760534, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1543825942, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2003247016, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1179556364, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1939933609, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 932809211, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 694376735, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2113261124, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1902787117, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1715294773, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 978325489, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1752619059, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2094694053, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -565402233, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -1918084337, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -203966158, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -637126965, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1775299985, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1091369083, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1625180693, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1293512863, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -309000326, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 429581186, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1598086028, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID7050513-134689S891299", + "deepid": -2073948964, + "children": [ + { + "guid": "GUID4478623-139086S779299", + "deepid": 699198064, + "locked": false, + "properties": [ + { + "nid": -1888505009, + "strtype": "OBJECT/Name", + "strval": "Label11", + "InheritedType": 10 + }, + { + "nid": -1237064329, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 1147111819, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 864467684, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 168274207, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 598472335, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -1701345511, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": -133168589, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 2059286674, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 720049573, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 819324107, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -373744, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1107440447, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1018240859, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1455908073, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -604912349, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -953184762, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 142621398, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 247215279, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -720529281, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 546736853, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -341482726, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1773818816, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1816500137, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1247860246, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1492449250, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -546990699, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -1407816072, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -1999232657, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 802947271, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 920532091, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 647357010, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1449908122, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1337143129, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -839232500, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1730597070, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1437703321, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1101140345, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 455937775, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 78390435, + "strtype": "LABEL/Text", + "strval": "LV_SYMBOL_VOLUME_MID", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -181118045, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": 746754206, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": -1732168164, + "strtype": "OBJECT/Name", + "strval": "volume dec btn", + "InheritedType": 10 + }, + { + "nid": 299640232, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 990983983, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 177050740, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -988881668, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 35, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1781665891, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 30, + 30 + ], + "InheritedType": 7 + }, + { + "nid": -535309023, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": -742920457, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1055094551, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 840524021, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2083847781, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1983686893, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1948194400, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 315489126, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 167033587, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1472465498, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1831169412, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 419773364, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 417946543, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -484555778, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -359767932, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -725561379, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 171183498, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1513226003, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1600654678, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1891620048, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -84124277, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 2008488457, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 2092426059, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 563433045, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 535821263, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -40954611, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1799860880, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 252096033, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 717101233, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1508839347, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 299798225, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 788256277, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID81355858-134040S208299", + "deepid": 375875006, + "locked": false, + "properties": [ + { + "nid": -1645810627, + "strtype": "OBJECT/Name", + "strval": "Bar2", + "InheritedType": 10 + }, + { + "nid": -1556747599, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1535153213, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 901188133, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -67512305, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + -50, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -884264170, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 150, + 10 + ], + "InheritedType": 7 + }, + { + "nid": 212839881, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": 183748637, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 1023224544, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 810944928, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1541007046, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -926367976, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 281384218, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 513927528, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1621247174, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2026609854, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1036881274, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2028019477, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -761093918, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1032918319, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -175236971, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 594914091, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 374069549, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -201118220, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 948231493, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -120293555, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1457932850, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 45449272, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 32456423, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2049846118, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1850611047, + "strtype": "BAR/Bar", + "InheritedType": 1 + }, + { + "nid": 1189833652, + "strtype": "BAR/Range", + "intarray": [ + 0, + 100 + ], + "InheritedType": 7 + }, + { + "nid": -1728056213, + "strtype": "BAR/Value", + "integer": 25, + "InheritedType": 6 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 2103774511, + "strtype": "BAR/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Anim1", + "InheritedType": 11 + }, + { + "part": "lv.PART.INDICATOR", + "childs": [], + "nid": -441354831, + "strtype": "BAR/Style_indicator", + "strval": "lv.PART.INDICATOR, Rectangle", + "InheritedType": 11 + }, + { + "nid": 1049614181, + "strtype": "BAR/Mode", + "strval": "NORMAL", + "InheritedType": 3 + }, + { + "nid": 2022888677, + "strtype": "BAR/Value_start", + "InheritedType": 6 + } + ], + "saved_objtypeKey": "BAR" + }, + { + "guid": "GUID65628620-135099S10299", + "deepid": 1225835062, + "children": [ + { + "guid": "GUID58270544-139500S202299", + "deepid": -1561809669, + "locked": false, + "properties": [ + { + "nid": 927158065, + "strtype": "OBJECT/Name", + "strval": "Label8", + "InheritedType": 10 + }, + { + "nid": 459836000, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1354252479, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1943126612, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 1087061818, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 900975819, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 36935426, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 1582989857, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 1922117356, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -325899534, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -120163198, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1338536994, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -281496500, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1864519423, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -897418722, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1255439781, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1191853263, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1824478595, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2142612522, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1269266212, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1293258544, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1426528410, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2115861097, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1643323921, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2100898914, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1635850945, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1857110622, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 809663134, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1533087491, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -948898370, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 691726443, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -358118556, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 374966570, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1485314161, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 58474545, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1724542843, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -74982269, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2075058219, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 666171643, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -151981974, + "strtype": "LABEL/Text", + "strval": "LV_SYMBOL_VOLUME_MAX", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1903773183, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": 238882901, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": -980265541, + "strtype": "OBJECT/Name", + "strval": "volume inc btn", + "InheritedType": 10 + }, + { + "nid": 126728937, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1997275036, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1324795251, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -635430922, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -1454446224, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 30, + 30 + ], + "InheritedType": 7 + }, + { + "nid": 149591139, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": -471086467, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 1601615942, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 557100117, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -958738535, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1965407799, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1878424152, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 253228330, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1023533314, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1264097759, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 942154535, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -953324922, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1766308302, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1421426157, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -565026292, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -13688090, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -647575169, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1829117657, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1996828995, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1656540353, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1008545670, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 492000527, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1430108121, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1601862148, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 872999560, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -978794353, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1727527879, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -405802686, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -578212366, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 761285539, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2050004668, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1729975837, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON" + } + ], + "locked": false, + "properties": [ + { + "nid": -1935501909, + "strtype": "OBJECT/Name", + "strval": "Panel3", + "InheritedType": 10 + }, + { + "nid": -555685535, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1474629275, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1010952861, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -164437180, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 80 + ], + "InheritedType": 7 + }, + { + "nid": 125975943, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 50 + ], + "InheritedType": 7 + }, + { + "nid": 1607358348, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 765479077, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1388562560, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1046249536, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -584224912, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -172879404, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 237997394, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1001860694, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -108755640, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1977944801, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 323129948, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 924771643, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 609857522, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 995812907, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 926547690, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1090012780, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 425422311, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1685852431, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1778935738, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -708964845, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 302254654, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -484953791, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 806820214, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -943677037, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 988558104, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 812323821, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -200914435, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 875242211, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1189644299, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1877276442, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -964637946, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": -1204029681, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 1054687074, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1660966457, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1791932306, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID14849953-130034S306299", + "deepid": 2102878093, + "children": [ + { + "guid": "GUID84480385-124078S334299", + "deepid": 1121655234, + "children": [ + { + "guid": "GUID411170-124488S549299", + "deepid": 786933571, + "locked": false, + "properties": [ + { + "nid": -1794856552, + "strtype": "OBJECT/Name", + "strval": "Label2", + "InheritedType": 10 + }, + { + "nid": 1615456357, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 759000707, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 489210118, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 1185684955, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -1077049720, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -578160026, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": -666770409, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 173656062, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1989791426, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1381303332, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1707863542, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 101073862, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -124239370, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 997032442, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1616517129, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1106816858, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1031263617, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1701402071, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2009406068, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1158303947, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1301561569, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1414932561, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1134683958, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1292693245, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -239928474, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1454205368, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 1324048338, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -574634751, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 115623345, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 517223856, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 772443644, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1798583136, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 726311761, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -253720710, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1386829165, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -425928284, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1060538733, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1525324622, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -1998086580, + "strtype": "LABEL/Text", + "strval": "-", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -1069228358, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": -569953567, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "locked": false, + "properties": [ + { + "nid": 751258151, + "strtype": "OBJECT/Name", + "strval": "btn slot dec", + "InheritedType": 10 + }, + { + "nid": -1622183966, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 1170567136, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 30603279, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 1745221705, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -593622746, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 30, + 30 + ], + "InheritedType": 7 + }, + { + "nid": -2370035, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 1442043068, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 378374579, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1031009750, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 361442153, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -577026512, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -342895367, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 393590498, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1187422033, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1885789236, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1033372217, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -226580211, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1559749418, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -51201389, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1463731702, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -521527970, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -965126478, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 256434271, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1153532580, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1448831858, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1162020846, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 1999692782, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -1894805329, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1136399953, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1110373989, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -658922424, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 784156436, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1184718918, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -403207503, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2089672498, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1493319803, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -1680523171, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON", + "tree_closed": true + }, + { + "guid": "GUID80175977-125704S103299", + "deepid": -783675679, + "locked": false, + "properties": [ + { + "nid": 1131689539, + "strtype": "OBJECT/Name", + "strval": "slot label", + "InheritedType": 10 + }, + { + "nid": 2116783957, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 1143097003, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 856975084, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 116410332, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -1805229339, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 409776084, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": -745035449, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 1127888750, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2070649641, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1944820086, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -713216409, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 84262571, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1711037188, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1079603776, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1958030511, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -369385396, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -560818196, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1961204583, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 648465368, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1608503994, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 605370966, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1522126373, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1101915888, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 518747749, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -963126060, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 388910500, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -285207895, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 568220885, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1840058959, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1066731575, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1935507218, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1921034321, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1209197144, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1694799773, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1779240460, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1142473150, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -993332413, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": -1497727308, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -707365498, + "strtype": "LABEL/Text", + "strval": "Save Slot 1", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1064804657, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": -651003914, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID38681331-125703S227299", + "deepid": 1121655234, + "children": [ + { + "guid": "GUID46342883-125702S227299", + "deepid": 786933571, + "locked": false, + "properties": [ + { + "nid": 564034494, + "strtype": "OBJECT/Name", + "strval": "Label1", + "InheritedType": 10 + }, + { + "nid": -961466252, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 51771896, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1605941196, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 1923009400, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -1333051030, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 479643917, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": -179180821, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1192707816, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1745015894, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 432616121, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1224863721, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1768876166, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1632922841, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -205792931, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1051293191, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2115254503, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -927749892, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1845213204, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1840586130, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -559102290, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1676394086, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -457871683, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 263550594, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1589091123, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 909119536, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1259632182, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -387386211, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1291445933, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 863060774, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1361841965, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1995055274, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 177109259, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -475168752, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1044651461, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1657084064, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -685932079, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1871891440, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": -403397023, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -27978500, + "strtype": "LABEL/Text", + "strval": "+", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 647022102, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": -60094814, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "locked": false, + "properties": [ + { + "nid": 362402032, + "strtype": "OBJECT/Name", + "strval": "btn slot inc", + "InheritedType": 10 + }, + { + "nid": -2089718589, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 797849949, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1324947441, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1913103091, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1960794609, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 30, + 30 + ], + "InheritedType": 7 + }, + { + "nid": 1716955858, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": -350811210, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 868320197, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1371396314, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -621808814, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1556973921, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2116396598, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -467476563, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -576057365, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 534462785, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 865627150, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 346472310, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 796907578, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1397015639, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -362400621, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2012174404, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 508334529, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1645847327, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 797008814, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1256068173, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 111452652, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 1309958993, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -1441463966, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1880542431, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1513608440, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 349403326, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 339745932, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -994384928, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 272117473, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1701550690, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -362470330, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1240147662, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON", + "tree_closed": true + } + ], + "locked": false, + "properties": [ + { + "nid": 1031669420, + "strtype": "OBJECT/Name", + "strval": "Panel4", + "InheritedType": 10 + }, + { + "nid": -534076315, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 25652530, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1862725350, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1384021265, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 130 + ], + "InheritedType": 7 + }, + { + "nid": -1556912651, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 50 + ], + "InheritedType": 7 + }, + { + "nid": -2034610555, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": -1014485673, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -509300964, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -677658216, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 909216146, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1241845622, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -298716315, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -353797403, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 58597554, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -466081053, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 664219397, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 728517566, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2141569999, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -837144286, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 2097492349, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 790332020, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -346448888, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 2147475945, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -259056014, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -704365564, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240880221, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 336700091, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1793953271, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1682625306, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1323769438, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1504766049, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -888381042, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1933678888, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1713540864, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 557169513, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 291122165, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 1160312398, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": -616413077, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": -920564256, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1938139788, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID27307571-128456S842299", + "deepid": 571551604, + "children": [ + { + "guid": "GUID71657942-126118S627299", + "deepid": 1986988131, + "children": [ + { + "guid": "GUID85023895-127628S796299", + "deepid": 1655588144, + "locked": false, + "properties": [ + { + "nid": -1849114166, + "strtype": "OBJECT/Name", + "strval": "Label4", + "InheritedType": 10 + }, + { + "nid": -1807327892, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 95441548, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1505115267, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 6013168, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1858884832, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 1791504318, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 1061926988, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 539171975, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -20435328, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 863997628, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 918320284, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 923774488, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 264362091, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 647836547, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1076348974, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1215646869, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 746783897, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -483230618, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 243108915, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 419907247, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 726893255, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 614651314, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -593258900, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 873930613, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1944532903, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1036949534, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -1820414033, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1714240814, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -894754197, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1393738842, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -836041064, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -80821728, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1081148549, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1794231190, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1574652306, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1356143417, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 609821165, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": -2019124541, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1990173391, + "strtype": "LABEL/Text", + "strval": "Load", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -610060857, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": -178799888, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": -1234844372, + "strtype": "OBJECT/Name", + "strval": "load btn", + "InheritedType": 10 + }, + { + "nid": 720236300, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 609615554, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 909179969, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 540757992, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -1523880134, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 40 + ], + "InheritedType": 7 + }, + { + "nid": 1101462027, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 118760421, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 1605733162, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1205108070, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -382516486, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -75616937, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -103856342, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1942266439, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1840489132, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1690457211, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -260908847, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1408259052, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1497002484, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 268417963, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 208257222, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -51553671, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1896943307, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1221986740, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2118183992, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1177868887, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1640094264, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 831934959, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1530381626, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -590574806, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -836109982, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1058134761, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 134780385, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2116596838, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1471963135, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1076574742, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -284355021, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 485226801, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID77420628-126938S414299", + "deepid": -813190415, + "locked": false, + "properties": [ + { + "nid": -944979729, + "strtype": "OBJECT/Name", + "strval": "slot image", + "InheritedType": 10 + }, + { + "nid": 507011323, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -374684674, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 2020112493, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1118646098, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -4729905, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 80, + 60 + ], + "InheritedType": 7 + }, + { + "nid": 521087960, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": 1544821543, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -2140524488, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 62681703, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2020311463, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1517058561, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 693422039, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 589144019, + "strtype": "OBJECT/Adv_hittest", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -445326313, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -411779030, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -947386439, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1560491750, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1301788901, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 2089430410, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1409825794, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1594198766, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1362049051, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -483745692, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1732730288, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 385431926, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1023618919, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -1691199598, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -1783415493, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1427363374, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1201955509, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1012089952, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1282120638, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 269245964, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1548961403, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 223649906, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1754884457, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -231651350, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": -2050705194, + "strtype": "IMAGE/Asset", + "strval": "", + "InheritedType": 5 + }, + { + "nid": 960222923, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -492228363, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": 292539395, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 175830251, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE" + } + ], + "locked": false, + "properties": [ + { + "nid": 1954961402, + "strtype": "OBJECT/Name", + "strval": "Panel2", + "InheritedType": 10 + }, + { + "nid": -475437284, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 1560132997, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1697487470, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -84544582, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 180 + ], + "InheritedType": 7 + }, + { + "nid": -694474548, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 100 + ], + "InheritedType": 7 + }, + { + "nid": -1871701624, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 1654751696, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1358271616, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 105361340, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1752332875, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1755982591, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1570443407, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -435754163, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -576864439, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1356723777, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1005344478, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 293006226, + "strtype": "OBJECT/Event_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 359334318, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1718255933, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 2108064889, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 109246308, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -173825737, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -413969415, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 55467155, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1709286551, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1164944417, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -812088775, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 960931613, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -493935470, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1977368832, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -844147654, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1350109941, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 528348720, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1675341445, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -557891231, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -416228926, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": -691931610, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 393345103, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": -112075408, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1628582034, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID34105632-129245S529299", + "deepid": 230058804, + "children": [ + { + "guid": "GUID35540961-126528S586299", + "deepid": -831510616, + "children": [ + { + "guid": "GUID62145645-128042S280299", + "deepid": 805111392, + "locked": false, + "properties": [ + { + "nid": -220641910, + "strtype": "OBJECT/Name", + "strval": "Label3", + "InheritedType": 10 + }, + { + "nid": 325354257, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 1410376908, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1386016379, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1837189068, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1545477439, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -342528538, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": -1047199605, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 507035540, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -82854385, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -714218294, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 679379644, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1747860727, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -694278052, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1166332945, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1613269205, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 263689383, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 423288221, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1506996868, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -546454511, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 974090236, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1429441470, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 451423375, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1690964258, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1420515943, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 400777389, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 121596566, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 1671942986, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 2114342705, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1066084161, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 913905287, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1994249556, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1714277626, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 782929326, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -665138506, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1685689626, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 422671635, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1588371302, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": -971600157, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 622171650, + "strtype": "LABEL/Text", + "strval": "Save", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 267231932, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": 1236560273, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": -1313230266, + "strtype": "OBJECT/Name", + "strval": "save btn", + "InheritedType": 10 + }, + { + "nid": 56773562, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 1959689196, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 979606826, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -362269121, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1467456074, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 40 + ], + "InheritedType": 7 + }, + { + "nid": 705930869, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 1429672914, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1307006328, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 147593720, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -599930746, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -777236749, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1898919746, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 666913382, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -312848358, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -946843489, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 488992088, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 617586462, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1742749106, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -978750609, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1252015254, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -679235227, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 659291425, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1798039458, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1032984594, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1363305812, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 729703777, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 1002654332, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1082952574, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -662467479, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1324160724, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -900957403, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -165074589, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1713832652, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -780267033, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2123574323, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -82789200, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -1363469521, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID2792267-127283S873299", + "deepid": 760566260, + "locked": false, + "properties": [ + { + "nid": -1136637976, + "strtype": "OBJECT/Name", + "strval": "pause image", + "InheritedType": 10 + }, + { + "nid": -1800556420, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1323831125, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1299043724, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1086344040, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 74691571, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 80, + 60 + ], + "InheritedType": 7 + }, + { + "nid": 675608179, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": -1737163119, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 27969832, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1055883433, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 954239523, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1193899087, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 651861246, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 512042393, + "strtype": "OBJECT/Adv_hittest", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1779503286, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1126179222, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1298870175, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1451375813, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1966489114, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2135172707, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1086474948, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 55198902, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1156012085, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1047127148, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 558848466, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2065037924, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1983586716, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 2004461390, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -253687849, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -168030038, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -236797597, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1233578232, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1498510680, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -194903997, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 432235501, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1836841002, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 528267103, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2117686798, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": 417204619, + "strtype": "IMAGE/Asset", + "strval": "", + "InheritedType": 5 + }, + { + "nid": 735910598, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 713938855, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": -1192259511, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1959191573, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE" + } + ], + "locked": false, + "properties": [ + { + "nid": 871690000, + "strtype": "OBJECT/Name", + "strval": "Panel1", + "InheritedType": 10 + }, + { + "nid": -2027886378, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -2052651854, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1318822937, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 1970800750, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 280 + ], + "InheritedType": 7 + }, + { + "nid": -1640895691, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 100 + ], + "InheritedType": 7 + }, + { + "nid": -1747459353, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 521363727, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -77200297, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1092311100, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 336368894, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1412215045, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1173526622, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 77219477, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 956921496, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 896696650, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1787790616, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 557685536, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 430410193, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 117142153, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 630622524, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 473201697, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 468194100, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1739466381, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1635437181, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1476336814, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1912341068, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -1914795192, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -42116671, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1560615091, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 757024782, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -913210780, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -460374941, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -481378079, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -896486375, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -491814874, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1502679729, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": -1845967441, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": -1582926030, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": -602170567, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": -320969518, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID53639927-135919S184299", + "deepid": -1248278987, + "children": [ + { + "guid": "GUID52711323-136708S559299", + "deepid": -1946560130, + "locked": false, + "properties": [ + { + "nid": -696992679, + "strtype": "OBJECT/Name", + "strval": "Label9", + "InheritedType": 10 + }, + { + "nid": -200742212, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 563860562, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 2020699637, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 502855357, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -1323261642, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -497727259, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": -108524514, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1326832372, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1959811664, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -999859188, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2030594104, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -943637503, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 539483975, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1367909068, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1275492117, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1529096836, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1886623262, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -955787728, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2016756723, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1201232039, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2044508132, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 2019865294, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1676917078, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2010631288, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 972589137, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1927475857, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 893251433, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -716738262, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -730207867, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 450590324, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1647713306, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1125265554, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 897653180, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1766974802, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2024851093, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1389837203, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 436761027, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": -1671105651, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -146471694, + "strtype": "LABEL/Text", + "strval": "Video", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1543584379, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": 5302283, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID55009636-137122S413299", + "deepid": -1747014191, + "locked": false, + "properties": [ + { + "nid": 641452043, + "strtype": "OBJECT/Name", + "strval": "Dropdown2", + "InheritedType": 10 + }, + { + "nid": 1528853182, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -123618464, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1080033049, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 1527395850, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 325038886, + "flags": 49, + "strtype": "OBJECT/Size", + "intarray": [ + 150, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -2137689278, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": 1345682299, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -577032063, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1495103705, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 592482883, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -60490764, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1607286629, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 856533935, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1847249983, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1427438399, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1205717321, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -895910871, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -379967437, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1449091188, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -907215371, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1578608054, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -82190872, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1359777169, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1148451514, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 571218055, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -446186025, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 199626732, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -1987596542, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 516152232, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -580326880, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 197589881, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1085951753, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -839181544, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 651377717, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1414633765, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1031413387, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -829039333, + "strtype": "DROPDOWN/Label", + "InheritedType": 1 + }, + { + "nid": -241919767, + "strtype": "DROPDOWN/Options", + "strval": "Original\\nFit\\nFill", + "InheritedType": 10 + }, + { + "nid": -238409571, + "strtype": "DROPDOWN/List_align", + "strval": "BOTTOM", + "InheritedType": 3 + }, + { + "nid": -229763116, + "strtype": "DROPDOWN/Show_selected", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 395906784, + "strtype": "DROPDOWN/Base_text", + "strval": "", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -1908874092, + "strtype": "DROPDOWN/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "part": "lv.PART.INDICATOR", + "childs": [], + "nid": -121722741, + "strtype": "DROPDOWN/Style_indicator", + "strval": "lv.PART.INDICATOR, Text", + "InheritedType": 11 + }, + { + "part": " lv.PART.MAIN", + "childs": [], + "nid": -1300610885, + "strtype": "DROPDOWN/Style_list_main", + "strval": "{\"python\":\"{0}.get_list()\",\"c\":\"lv_dropdown_get_list({0})\"} lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "part": " lv.PART.SCROLLBAR", + "childs": [], + "nid": 1727164872, + "strtype": "DROPDOWN/Style_list_scrollbar", + "strval": "{\"python\":\"{0}.get_list()\",\"c\":\"lv_dropdown_get_list({0})\"} lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + }, + { + "part": " lv.PART.SELECTED", + "childs": [], + "nid": 319800648, + "strtype": "DROPDOWN/Style_list_selected", + "strval": "{\"python\":\"{0}.get_list()\",\"c\":\"lv_dropdown_get_list({0})\"} lv.PART.SELECTED, Text, Rectangle", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "DROPDOWN" + } + ], + "locked": false, + "properties": [ + { + "nid": -1376134393, + "strtype": "OBJECT/Name", + "strval": "Panel6", + "InheritedType": 10 + }, + { + "nid": 2089469209, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 419791360, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -305024974, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -676163115, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 380 + ], + "InheritedType": 7 + }, + { + "nid": 1868742590, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 50 + ], + "InheritedType": 7 + }, + { + "nid": 1301681870, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 101193066, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 1735909440, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 550797422, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1045184587, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2013566538, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2056465014, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1830744722, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1917055911, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 898621350, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -890719697, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1684391728, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -462698581, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1564673739, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1414640549, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2140318770, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1456031403, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1801951408, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 251150028, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -752171892, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1656522347, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -138564831, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -910385663, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1050027908, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1936465057, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1893206136, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -619049336, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -678210922, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1895702098, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2035180280, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1589004164, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1909039013, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1808002810, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID92498944-132448S454299", + "deepid": 479922634, + "children": [ + { + "guid": "GUID30031233-132447S454299", + "deepid": 559763650, + "locked": false, + "properties": [ + { + "nid": -1142101124, + "strtype": "OBJECT/Name", + "strval": "Label5", + "InheritedType": 10 + }, + { + "nid": 2013152407, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -2113558393, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -359161127, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1768987781, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 171119804, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -484366993, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": -731292191, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1952791592, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -468078302, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 660390685, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -494234139, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1507447465, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -690133949, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2134346171, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1456231736, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1742967484, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 813586615, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -760134358, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1470953752, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 869281870, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 6376291, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -652730976, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 591595731, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1563431644, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 741563537, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -254633451, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -1373674816, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1724872945, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1503810698, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1054102994, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1981900542, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1689154124, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -514342001, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -542299334, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -694275674, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -941515908, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1701365359, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 629532456, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -481962867, + "strtype": "LABEL/Text", + "strval": "Reset", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1983242286, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": -1049192882, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": 1262213678, + "strtype": "OBJECT/Name", + "strval": "reset btn", + "InheritedType": 10 + }, + { + "nid": 758827053, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -235042114, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 1073214382, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 663136051, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 435 + ], + "InheritedType": 7 + }, + { + "nid": -405204904, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 40 + ], + "InheritedType": 7 + }, + { + "nid": 1278386887, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": -2128400475, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -805863504, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1326076309, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1372871868, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -16974319, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 181565583, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -804200871, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -2064936616, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 486177466, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 565104370, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -51624596, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 645286923, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1313601662, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1834692483, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 284897667, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2023546181, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -630731047, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -7520655, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -2073144545, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1781310417, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 915789193, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -853491589, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1907687893, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -410416953, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1729359975, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 809472399, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1072890025, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1076603025, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1592918075, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 247204141, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -197971304, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON", + "tree_closed": true + }, + { + "guid": "GUID89381137-133250S1299", + "deepid": 479922634, + "children": [ + { + "guid": "GUID42025939-133249S1299", + "deepid": 559763650, + "locked": false, + "properties": [ + { + "nid": 1692563952, + "strtype": "OBJECT/Name", + "strval": "Label7", + "InheritedType": 10 + }, + { + "nid": 1352995289, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 370336578, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -144735206, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -1626639012, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": -1806378749, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": -448800777, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 672664006, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -174956271, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1327552587, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 520336200, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1498914767, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 336657493, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -958086973, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1830013066, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -766296682, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1235739100, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1635629084, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -22348976, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1597783255, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 659512912, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1600303815, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 186960432, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1452373533, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1145736090, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -147026014, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1123472083, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 202279057, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 560535966, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1625901687, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1082121300, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -141494540, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -818374481, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 901588131, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1370542072, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -607656179, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1251863245, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 419058420, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 653475344, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": -1350833151, + "strtype": "LABEL/Text", + "strval": "Quit", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -385966658, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad", + "InheritedType": 11 + }, + { + "nid": -1707496824, + "strtype": "LABEL/Recolor", + "strval": "False", + "InheritedType": 2 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "locked": false, + "properties": [ + { + "nid": 1490511283, + "strtype": "OBJECT/Name", + "strval": "quit btn", + "InheritedType": 10 + }, + { + "nid": 1121320493, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -896121232, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 365845787, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -88239515, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 485 + ], + "InheritedType": 7 + }, + { + "nid": -514116028, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 40 + ], + "InheritedType": 7 + }, + { + "nid": 1266737301, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": -1700686800, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 1750355218, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1623541156, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 106337428, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1632860770, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1721306735, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 839086779, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 849629389, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -816808629, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 260934745, + "strtype": "OBJECT/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1891472317, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1091445661, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 287962760, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -280992572, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -959123714, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1288103498, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 468805802, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1596154451, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1346759211, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1356966402, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 984669438, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 1213735835, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -2118822958, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1358236173, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 328396209, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1862744379, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 929062255, + "strtype": "OBJECT/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1041243473, + "strtype": "OBJECT/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 224765040, + "strtype": "OBJECT/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1364822061, + "strtype": "OBJECT/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": -1547655441, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text ", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON", + "tree_closed": true + } + ], + "locked": false, + "properties": [ + { + "nid": 1060048278, + "strtype": "OBJECT/Name", + "strval": "menu panel", + "InheritedType": 10 + }, + { + "nid": 1910631663, + "strtype": "PANEL/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 502715906, + "strtype": "PANEL/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -2025841205, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -2061658148, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 978299534, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 100 + ], + "InheritedType": 7 + }, + { + "nid": -1089531758, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 745158710, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -940560030, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2062724236, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 511052200, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1853206676, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 680238069, + "strtype": "OBJECT/Click_focusable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -560561600, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1714656683, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1345955359, + "strtype": "OBJECT/Floating", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1171824480, + "strtype": "PANEL/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 984729607, + "strtype": "OBJECT/Event_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1122877811, + "strtype": "OBJECT/Gesture_bubble", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1056036387, + "strtype": "OBJECT/Snappable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1534892930, + "strtype": "OBJECT/Scrollable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1783341989, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -768945641, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1287967185, + "strtype": "OBJECT/Scroll_on_focus", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -410941831, + "strtype": "OBJECT/Scroll_chain", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -164225548, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -799716301, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 702783682, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -557976984, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -759140455, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -596930945, + "strtype": "OBJECT/Disabled", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1998830205, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1330125201, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 2033022967, + "strtype": "PANEL/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1018407769, + "strtype": "PANEL/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 552981383, + "strtype": "PANEL/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1757601062, + "strtype": "PANEL/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 452821406, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, BGimg, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": -1206387834, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + } + ], + "isPage": true, + "locked": false, + "properties": [ + { + "nid": -5353643, + "strtype": "OBJECT/Name", + "strval": "Screen1", + "InheritedType": 10 + }, + { + "nid": 1439939602, + "strtype": "SCREEN/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": -1242080811, + "strtype": "SCREEN/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": -1860967741, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": -694951182, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": -1136818168, + "strtype": "OBJECT/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -351537127, + "strtype": "OBJECT/Clickable", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1922461541, + "strtype": "OBJECT/Checkable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1937980856, + "strtype": "OBJECT/Press_lock", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 878510987, + "strtype": "OBJECT/Adv_hittest", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -93124590, + "strtype": "OBJECT/Ignore_layout", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -556465343, + "strtype": "SCREEN/Flex_in_new_track", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -875288209, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 497052241, + "strtype": "OBJECT/Scroll_elastic", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 1898139584, + "strtype": "OBJECT/Scroll_momentum", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": -1490906168, + "strtype": "OBJECT/Scroll_one", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -371289485, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": -2112555101, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": -2003495827, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": -1329901090, + "strtype": "OBJECT/Checked", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -21624806, + "strtype": "OBJECT/Focused", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -687479388, + "strtype": "OBJECT/Pressed", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -4459963, + "strtype": "SCREEN/User_1", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -1346607160, + "strtype": "SCREEN/User_2", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 1092550315, + "strtype": "SCREEN/User_3", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": -671483688, + "strtype": "SCREEN/User_4", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 120568296, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 695593437, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": -811131639, + "strtype": "_style/StyleState", + "strval": "CHECKED", + "childs": [ + { + "nid": -1203749700, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": 312618742, + "strtype": "_style/StyleState", + "strval": "PRESSED", + "childs": [ + { + "nid": -824389495, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": 779970414, + "strtype": "_style/StyleState", + "strval": "CHECKED|PRESSED", + "childs": [ + { + "nid": -70467517, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": 316176925, + "strtype": "_style/StyleState", + "strval": "DISABLED", + "childs": [ + { + "nid": -940136977, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": 1421906761, + "strtype": "_style/StyleState", + "strval": "USER_1", + "childs": [ + { + "nid": 836136070, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": -40234646, + "strtype": "_style/StyleState", + "strval": "USER_2", + "childs": [ + { + "nid": -1008824185, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": -2029459867, + "strtype": "_style/StyleState", + "strval": "USER_3", + "childs": [ + { + "nid": 1652237425, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + }, + { + "nid": 2007554717, + "strtype": "_style/StyleState", + "strval": "USER_4", + "childs": [ + { + "nid": 1488044526, + "strtype": "_style/Paddings", + "InheritedType": 1 + } + ], + "InheritedType": 1 + } + ], + "nid": -723309363, + "strtype": "SCREEN/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 770090579, + "strtype": "SCREEN/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "SCREEN" + } + ], + "locked": false, + "properties": [ + { + "nid": 1544103435, + "strtype": "STARTEVENTS/Name", + "strval": "___initial_actions0", + "InheritedType": 10 + } + ], + "saved_objtypeKey": "STARTEVENTS" + }, + "animations": [], + "info": { + "name": "menu.spj", + "depth": 2, + "width": 320, + "height": 240, + "rotation": 0, + "offset_x": 0, + "offset_y": 0, + "shape": "RECTANGLE", + "description": "The menu that the user can open while playing a rom.", + "board": "ESP-BOX", + "board_version": "1.0.0", + "editor_version": "1.2.3", + "image": "", + "force_export_images": false, + "pointfilter": false, + "theme_simplified": false, + "theme_dark": true, + "theme_color1": 5, + "theme_color2": 0, + "exportFolderPath": "/Users/bob/esp-cpp/esp-box-emu/components/menu/generated", + "projectExportFolderPath": "/Users/bob/esp-cpp/esp-box-emu/components/menu/squareline", + "backup_cnt": 10, + "autosave_cnt": 0, + "lvgl_version": "8.2.0", + "callfuncsexport": "C_FILE", + "lvgl_include_path": "", + "BitDepth": 16, + "Name": "menu" + } +} \ No newline at end of file diff --git a/components/menu/src/menu.cpp b/components/menu/src/menu.cpp new file mode 100644 index 00000000..bd2f6732 --- /dev/null +++ b/components/menu/src/menu.cpp @@ -0,0 +1,240 @@ +#include "menu.hpp" +#include + +extern "C" { +#include "ui.h" +} + +void Menu::init_ui() { + logger_.info("Loading UI"); + // save the previous screen to return to it when we destroy ourselves. + previous_screen_ = lv_scr_act(); + + // now initialize our UI + menu_ui_init(); + + // now set up the event callbacks + + // emulation controls + lv_obj_add_event_cb(ui_resume_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_reset_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_quit_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_load_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_save_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + + // save state slot + lv_obj_add_event_cb(ui_btn_slot_dec, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_btn_slot_inc, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + + // volume settings + lv_obj_add_event_cb(ui_volume_inc_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_volume_dec_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + lv_obj_add_event_cb(ui_volume_mute_btn, &Menu::event_callback, LV_EVENT_PRESSED, static_cast(this)); + + // video settings + lv_obj_add_event_cb(ui_Dropdown2, &Menu::event_callback, LV_EVENT_VALUE_CHANGED, static_cast(this)); +} + +void Menu::deinit_ui() { + lv_scr_load(previous_screen_); + lv_obj_del(ui_Screen1); +} + +void Menu::update_slot_display() { + update_slot_label(); + update_slot_image(); +} + +void Menu::update_slot_label() { + auto slot = fmt::format("Save Slot {}", selected_slot_); + lv_label_set_text(ui_slot_label, slot.c_str()); +} + +void Menu::update_slot_image() { + // clear the image in case we don't have a new one to set + lv_img_set_src(ui_slot_image, nullptr); + if (slot_image_callback_) { + auto image = slot_image_callback_(); + logger_.info("Updating slot image to '{}'", image); + if (image.empty()) { + logger_.info("No slot image to display"); + return; + } + // load the image data + std::ifstream file(image, std::ios::binary); + if (!file) { + logger_.error("Failed to open image file {}", image); + return; + } + file.seekg(0, std::ios::end); + size_t size = file.tellg(); + file.seekg(0, std::ios::beg); + uint16_t width, height; + static constexpr int header_size = 4; + uint8_t header[header_size]; + file.read((char*)header, header_size); + width = (header[0] << 8) | (header[1]); + height = (header[2] << 8) | (header[3]); + logger_.info("Slot image is {}x{}", width, height); + int state_image_data_size = size - header_size; + state_image_data_.resize(state_image_data_size); + file.read((char*)state_image_data_.data(), state_image_data_size); + file.close(); + state_image_.header.cf = LV_IMG_CF_TRUE_COLOR; + state_image_.header.always_zero = 0; + state_image_.header.reserved = 0; + state_image_.header.w = width; + state_image_.header.h = height; + state_image_.data_size = width * height * 2; + state_image_.data = (const uint8_t*)state_image_data_.data(); + lv_img_set_src(ui_slot_image, &state_image_); + lv_img_set_size_mode(ui_slot_image, LV_IMG_SIZE_MODE_REAL); + // set the scaling so that the image fits in the slot + auto scale = std::min(80.0f / width, 60.0f / height); + logger_.info("Scaling image by {}", scale); + lv_img_set_zoom(ui_slot_image, (uint16_t)(scale * 256.)); + lv_obj_set_size(ui_slot_image, width * scale, height * scale); + } else { + logger_.warn("No slot image callback set"); + } +} + +void Menu::update_pause_image() { + // clear the image in case we don't have a new one to set + lv_img_set_src(ui_pause_image, nullptr); + logger_.info("Updating pause image to '{}'", paused_image_path_); + // load the image data + std::ifstream file(paused_image_path_, std::ios::binary); + if (!file) { + logger_.error("Failed to open image file {}", paused_image_path_); + return; + } + file.seekg(0, std::ios::end); + size_t size = file.tellg(); + file.seekg(0, std::ios::beg); + uint16_t width, height; + static constexpr int header_size = 4; + uint8_t header[header_size]; + file.read((char*)header, header_size); + width = (header[0] << 8) | (header[1]); + height = (header[2] << 8) | (header[3]); + logger_.info("Paused image is {}x{}", width, height); + int paused_image_data_size = size - header_size; + paused_image_data_.resize(paused_image_data_size); + file.read((char*)paused_image_data_.data(), paused_image_data_size); + file.close(); + paused_image_.header.cf = LV_IMG_CF_TRUE_COLOR; + paused_image_.header.always_zero = 0; + paused_image_.header.reserved = 0; + paused_image_.header.w = width; + paused_image_.header.h = height; + paused_image_.data_size = width * height * 2; + paused_image_.data = (const uint8_t*)paused_image_data_.data(); + lv_img_set_src(ui_pause_image, &paused_image_); + lv_img_set_size_mode(ui_pause_image, LV_IMG_SIZE_MODE_REAL); + // lv_img_set_size(ui_pause_image, width, height); + // set the scaling so that the image fits in the slot + auto scale = std::min(80.0f / width, 60.0f / height); + logger_.info("Setting pause image scale to {}", scale); + lv_img_set_zoom(ui_pause_image, uint16_t(scale * 256.)); + lv_obj_set_size(ui_pause_image, width * scale, height * scale); +} + +void Menu::set_mute(bool muted) { + set_muted(muted); + if (muted) { + lv_obj_add_state(ui_volume_mute_btn, LV_STATE_CHECKED); + } else { + lv_obj_clear_state(ui_volume_mute_btn, LV_STATE_CHECKED); + } +} + +void Menu::set_audio_level(int new_audio_level) { + new_audio_level = std::clamp(new_audio_level, 0, 100); + lv_bar_set_value(ui_Bar2, new_audio_level, LV_ANIM_ON); + set_audio_volume(new_audio_level); +} + +void Menu::set_video_setting(VideoSetting setting) { + ::set_video_setting(setting); + lv_dropdown_set_selected(ui_Dropdown2, (int)setting); +} + +VideoSetting Menu::get_video_setting() { + return (VideoSetting)(lv_dropdown_get_selected(ui_Dropdown2)); +} + +void Menu::on_value_changed(lv_event_t *e) { + lv_obj_t * target = lv_event_get_target(e); + logger_.info("Value changed: {}", fmt::ptr(target)); + // is it the settings button? + bool is_video_setting = (target == ui_Dropdown2); + if (is_video_setting) { + set_video_setting(this->get_video_setting()); + return; + } +} + +void Menu::on_pressed(lv_event_t *e) { + lv_obj_t * target = lv_event_get_target(e); + logger_.info("PRESSED: {}", fmt::ptr(target)); + // emulation controls + bool is_resume = (target == ui_resume_btn); + if (is_resume) { + action_callback_(Action::RESUME); + return; + } + bool is_reset = (target == ui_reset_btn); + if (is_reset) { + action_callback_(Action::RESET); + return; + } + bool is_quit = (target == ui_quit_btn); + if (is_quit) { + action_callback_(Action::QUIT); + return; + } + bool is_save = (target == ui_save_btn); + if (is_save) { + action_callback_(Action::SAVE); + // when we save, the paused state is now the saved state + update_slot_display(); + return; + } + bool is_load = (target == ui_load_btn); + if (is_load) { + action_callback_(Action::LOAD); + // when we load, the paused state is now the loaded state + update_pause_image(); + return; + } + // slot controls + bool is_slot_up = (target == ui_btn_slot_inc); + if (is_slot_up) { + next_slot(); + update_slot_display(); + return; + } + bool is_slot_down = (target == ui_btn_slot_dec); + if (is_slot_down) { + previous_slot(); + update_slot_display(); + return; + } + // volume controls + bool is_volume_up_button = (target == ui_volume_inc_btn); + if (is_volume_up_button) { + set_audio_level(get_audio_volume() + 10); + return; + } + bool is_volume_down_button = (target == ui_volume_dec_btn); + if (is_volume_down_button) { + set_audio_level(get_audio_volume() - 10); + return; + } + bool is_mute_button = (target == ui_volume_mute_btn); + if (is_mute_button) { + toggle_mute(); + return; + } +} diff --git a/components/mt6701/CMakeLists.txt b/components/mt6701/CMakeLists.txt deleted file mode 100644 index a244e047..00000000 --- a/components/mt6701/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register( - INCLUDE_DIRS "include" - REQUIRES "logger" "task" - ) diff --git a/components/mt6701/example/CMakeLists.txt b/components/mt6701/example/CMakeLists.txt deleted file mode 100644 index 1c33d1e5..00000000 --- a/components/mt6701/example/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) - -# add the component directories that we want to use -set(EXTRA_COMPONENT_DIRS - "../../../components/" - "../../../components/espp/components" -) - -set( - COMPONENTS - "main esptool_py filters driver task mt6701" - CACHE STRING - "List of components to include" - ) - -project(mt6701_example) - -set(CMAKE_CXX_STANDARD 20) diff --git a/components/mt6701/example/README.md b/components/mt6701/example/README.md deleted file mode 100644 index ffe0beb9..00000000 --- a/components/mt6701/example/README.md +++ /dev/null @@ -1,67 +0,0 @@ -_Note that this is a template for an ESP-IDF example README.md file. When using this template, replace all these emphasised placeholders with example-specific content._ - -| Supported Targets | _Supported target, e.g. ESP32_ | _Another supported target, e.g. ESP32-S3_ | -| ----------------- | ------------------------------ | ----------------------------------------- | - -_If the example supports all targets supported by ESP-IDF then the table can be omitted_ -# _Example Title_ - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -_What is this example? What does it do?_ - -_What features of ESP-IDF does it use?_ - -_What could someone create based on this example? ie applications/use cases/etc_ - -_If there are any acronyms or Espressif-only words used here, explain them or mention where in the datasheet/TRM this information can be found._ - -## How to use example - -### Hardware Required - -_If possible, example should be able to run on any commonly available ESP32 development board. Otherwise, describe what specific hardware should be used._ - -_If any other items (server, BLE device, app, second chip, whatever) are needed, mention them here. Include links if applicable. Explain how to set them up._ - -### Configure the project - -``` -idf.py menuconfig -``` - -* _If there is any project configuration that the user must set for this example, mention this here._ - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(Replace PORT with the name of the serial port to use.) - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -_Include an example of the console output from the running example, here:_ - -``` -Use this style for pasting the log. -``` - -_If the user is supposed to interact with the example at this point (read/write GATT attribute, send HTTP request, press button, etc. then mention it here)_ - -_For examples where ESP32 is connected with some other hardware, include a table or schematics with connection details._ - -## Troubleshooting - -_If there are any likely problems or errors which many users might encounter, mention them here. Remove this section for very simple examples where nothing is likely to go wrong._ - -## Example Breakdown - -_If the example source code is lengthy, complex, or cannot be easily understood, use this section to break down and explain the source code. This can be done by breaking down the execution path step by step, or explaining what each major function/task/source file does. Add sub titles if necessary. Remove this section for very simple examples where the source code is self explanatory._ \ No newline at end of file diff --git a/components/mt6701/example/main/CMakeLists.txt b/components/mt6701/example/main/CMakeLists.txt deleted file mode 100644 index a941e22b..00000000 --- a/components/mt6701/example/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRC_DIRS "." - INCLUDE_DIRS ".") diff --git a/components/mt6701/example/main/mt6701_example.cpp b/components/mt6701/example/main/mt6701_example.cpp deleted file mode 100644 index cb604b8f..00000000 --- a/components/mt6701/example/main/mt6701_example.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include - -#include "driver/i2c.h" - -#include "butterworth_filter.hpp" -#include "task.hpp" -#include "mt6701.hpp" - -using namespace std::chrono_literals; - -#define I2C_NUM (I2C_NUM_1) -#define I2C_SCL_IO (GPIO_NUM_40) -#define I2C_SDA_IO (GPIO_NUM_41) -#define I2C_FREQ_HZ (400 * 1000) -#define I2C_TIMEOUT_MS (10) - -extern "C" void app_main(void) { - { - std::atomic quit_test = false; - fmt::print("Starting mt6701 example, rotate to -720 degrees to quit!\n"); - //! [mt6701 example] - // make the I2C that we'll use to communicate - i2c_config_t i2c_cfg; - fmt::print("initializing i2c driver...\n"); - memset(&i2c_cfg, 0, sizeof(i2c_cfg)); - i2c_cfg.sda_io_num = I2C_SDA_IO; - i2c_cfg.scl_io_num = I2C_SCL_IO; - i2c_cfg.mode = I2C_MODE_MASTER; - i2c_cfg.sda_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.scl_pullup_en = GPIO_PULLUP_ENABLE; - i2c_cfg.master.clk_speed = I2C_FREQ_HZ; - auto err = i2c_param_config(I2C_NUM, &i2c_cfg); - if (err != ESP_OK) printf("config i2c failed\n"); - err = i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0); - if (err != ESP_OK) printf("install i2c driver failed\n"); - // make some lambda functions we'll use to read/write to the mt6701 - auto mt6701_write = [](uint8_t reg_addr, uint8_t value) { - uint8_t data[] = {reg_addr, value}; - i2c_master_write_to_device(I2C_NUM, - Mt6701::ADDRESS, - data, - 2, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - }; - - auto mt6701_read = [](uint8_t reg_addr) -> uint8_t{ - uint8_t data; - i2c_master_write_read_device(I2C_NUM, - Mt6701::ADDRESS, - ®_addr, - 1, - &data, - 1, - I2C_TIMEOUT_MS / portTICK_PERIOD_MS); - return data; - }; - // make the velocity filter - static constexpr float filter_cutoff_hz = 4.0f; - static constexpr float encoder_update_period = 0.01f; // seconds - espp::ButterworthFilter<2, espp::BiquadFilterDf2> filter({ - .normalized_cutoff_frequency = 2.0f * filter_cutoff_hz * encoder_update_period - }); - auto filter_fn = [&filter](float raw) -> float { - return filter.update(raw); - }; - // now make the mt6701 which decodes the data - Mt6701 mt6701({ - .write = mt6701_write, - .read = mt6701_read, - .velocity_filter = filter_fn, - .update_period = std::chrono::duration(encoder_update_period), - .log_level = espp::Logger::Verbosity::WARN - }); - // and finally, make the task to periodically poll the mt6701 and print the - // state. NOTE: the Mt6701 runs its own task to maintain state, so we're - // just polling the current state. - auto task_fn = [&quit_test, &mt6701](std::mutex& m, std::condition_variable& cv) { - static auto start = std::chrono::high_resolution_clock::now(); - auto now = std::chrono::high_resolution_clock::now(); - auto seconds = std::chrono::duration(now-start).count(); - auto count = mt6701.get_count(); - auto radians = mt6701.get_radians(); - auto degrees = mt6701.get_degrees(); - auto rpm = mt6701.get_rpm(); - fmt::print("{:.3f}, {}, {:.3f}, {:.3f}, {:.3f}\n", - seconds, - count, - radians, - degrees, - rpm - ); - quit_test = degrees <= -720.0f; - // NOTE: sleeping in this way allows the sleep to exit early when the - // task is being stopped / destroyed - { - std::unique_lock lk(m); - cv.wait_for(lk, 50ms); - } - }; - auto task = espp::Task({ - .name = "Mt6701 Task", - .callback = task_fn, - .stack_size_bytes = 5*1024, - .log_level = espp::Logger::Verbosity::WARN - }); - fmt::print("%time(s), count, radians, degrees, rpm\n"); - task.start(); - //! [mt6701 example] - while (!quit_test) { - std::this_thread::sleep_for(100ms); - } - // now clean up the i2c driver - i2c_driver_delete(I2C_NUM); - } - - fmt::print("Mt6701 example complete!\n"); - - while (true) { - std::this_thread::sleep_for(1s); - } -} diff --git a/components/mt6701/example/sdkconfig.defaults b/components/mt6701/example/sdkconfig.defaults deleted file mode 100644 index 7d75f8d0..00000000 --- a/components/mt6701/example/sdkconfig.defaults +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_FREERTOS_HZ=1000 - -# ESP32-specific -# -CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y -CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 - -# Common ESP-related -# -CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096 -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 diff --git a/components/mt6701/include/mt6701.hpp b/components/mt6701/include/mt6701.hpp deleted file mode 100644 index 34f8457e..00000000 --- a/components/mt6701/include/mt6701.hpp +++ /dev/null @@ -1,238 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "logger.hpp" -#include "task.hpp" - -/** - * @brief Class for position and velocity measurement using a MT6701 magnetic - * encoder. This class starts its own measurement task at the specified - * frequency which reads the current angle, updates the accumulator, and - * filters / updates the velocity measurement. - * - * @note There is an implicit assumption in this class regarding the maximum - * velocity it can measure (above which there will be aliasing). The - * fastest velocity it can measure will be (0.5f * update_period * 60.0f) - * which is half a rotation in one update period. - * - * @note The assumption above also affects the reliability of the accumulator, - * since it is based on accumulating position differences every update - * period. - * - * \section mt6701_ex1 Mt6701 Example - * \snippet mt6701_example.cpp mt6701 example - */ -class Mt6701 { -public: - static constexpr uint8_t ADDRESS = (0b0000110); ///< I2C address of the MT6701 - - /** - * @brief Function to write a byte to a register for Mt6701. - * @param reg_addr Register address to write to. - * @param data Data to be written. - */ - typedef std::function write_fn; - - /** - * @brief Function to read a byte from a register for Mt6701. - * @param reg_addr Register address to read from. - * @return Byte read from register. - */ - typedef std::function read_fn; - - /** - * @brief Filter the input raw velocity and return it. - * @param raw Most recent raw velocity measured. - * @return Filtered velocity. - */ - typedef std::function velocity_filter_fn; - - static constexpr int COUNTS_PER_REVOLUTION = 16384; ///< Int number of counts per revolution for the magnetic encoder. - static constexpr float COUNTS_PER_REVOLUTION_F = 16384.0f; ///< Float number of counts per revolution for the magnetic encoder. - static constexpr float COUNTS_TO_RADIANS = 2.0f * M_PI / COUNTS_PER_REVOLUTION_F; ///< Conversion factor to convert from count value to radians. - static constexpr float COUNTS_TO_DEGREES = 360.0f / COUNTS_PER_REVOLUTION_F; ///< Conversion factor to convert from count value to degrees. - static constexpr float SECONDS_PER_MINUTE = 60.0f; ///< Conversion factor to convert from seconds to minutes. - - /** - * @brief Configuration information for the Mt6701. - */ - struct Config { - write_fn write; ///< Function to write to the device. - read_fn read; ///< Function to read from the device. - velocity_filter_fn velocity_filter; ///< Function to filter the veolcity. @note Will be called once every update_period seconds. - std::chrono::duration update_period{.01f}; ///< Update period (1/sample rate) in seconds. This determines the periodicity of the task which will read the position, update the accumulator, and update/filter velocity. - espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; - }; - - /** - * @brief Construct the Mt6701 and start the update task. - */ - Mt6701(const Config& config) - : write_(config.write), - read_(config.read), - velocity_filter_(config.velocity_filter), - update_period_(config.update_period), - logger_({.tag = "Mt6701", .level = config.log_level}) { - logger_.info("Initializing. Fastest measurable velocity will be {:.3f} RPM", - // half a rotation in one update period is the fastest we can - // measure - 0.5f / update_period_.count() * SECONDS_PER_MINUTE); - init(); - } - - /** - * @brief Get the most recently updated raw count value from the encoder. - * @note This value always represents the angle of the encoder modulo one - * rotation, meaning it only represents the range 0 to 360 degrees. It - * is not recommended to use this function, but is provided for edge use - * cases. - * @return Raw count value in the range [0, 16384] (0 to 360 degrees). - */ - int get_count() const { - return count_.load(); - } - - /** - * @brief Return the accumulated count that the encoder has generated since it - * was initialized. - * @note This value is a raw counter value that can be +/-, meaning - * COUNTS_PER_REVOLUTION can be used to convert it to revolutions. - * @return Raw accumulator value. - */ - int get_accumulator() const { - return accumulator_.load(); - } - - /** - * @brief Return the accumulated position of the encoder, in radians. - * @note This can be any value, it is not restricted to [-2pi, 2pi]. - * @return Position in radians of the encoder. - */ - float get_radians() const { - return (float)get_accumulator() * COUNTS_TO_RADIANS; - } - - /** - * @brief Return the accumulated position of the encoder, in degrees. - * @note This can be any value, it is not restricted to [-360, 360]. - * @return Position in degrees of the encoder. - */ - float get_degrees() const { - return (float)get_accumulator() * COUNTS_TO_DEGREES; - } - - /** - * @brief Return the filtered velocity of the encoder, in RPM. - * @return Filtered velocity (revolutions / minute, RPM). - */ - float get_rpm() const { - return velocity_rpm_.load(); - } - -protected: - int read_count() { - logger_.info("read_count"); - // read the angle count registers - uint8_t angle_h = read_((uint8_t)Registers::ANGLE_H); - uint8_t angle_l = read_((uint8_t)Registers::ANGLE_L) >> 2; - return (int)((angle_h << 6) | angle_l); - } - - void update() { - logger_.info("update"); - // update raw count - count_ = read_count(); - static int prev_count = count_; - // compute diff - int diff = count_ - prev_count; - // update prev_count - prev_count = count_; - // check for zero crossing - if (diff > COUNTS_PER_REVOLUTION/2) { - // we crossed zero going clockwise (1 -> 359) - diff -= COUNTS_PER_REVOLUTION; - } else if (diff < -COUNTS_PER_REVOLUTION/2) { - // we crossed zero going counter-clockwise (359 -> 1) - diff += COUNTS_PER_REVOLUTION; - } - // update accumulator - accumulator_ += diff; - logger_.debug("CDA: {}, {}, {}", count_, diff, accumulator_); - // update velocity (filtering it) - static auto prev_time = std::chrono::high_resolution_clock::now(); - auto now = std::chrono::high_resolution_clock::now(); - float elapsed = std::chrono::duration(now - prev_time).count(); - prev_time = now; - float seconds = elapsed ? elapsed : update_period_.count(); - float raw_velocity = (float)(diff) / COUNTS_PER_REVOLUTION_F / seconds * SECONDS_PER_MINUTE; - velocity_rpm_ = velocity_filter_(raw_velocity); - static float max_velocity = 0.5f / update_period_.count() * SECONDS_PER_MINUTE; - if (raw_velocity >= max_velocity) { - logger_.warn("Velocity nearing measurement limit ({:.3f} RPM), consider decreasing your update period!", - max_velocity); - } - } - - void update_task(std::mutex &m, std::condition_variable &cv) { - auto start = std::chrono::high_resolution_clock::now(); - update(); - { - std::unique_lock lk(m); - cv.wait_until(lk, start + update_period_); - } - } - - void init() { - // initialize the accumulator to have the current angle - accumulator_ = read_count(); - // start the task - using namespace std::placeholders; - task_ = espp::Task::make_unique({ - .name = "Mt6701", - .callback = std::bind(&Mt6701::update_task, this, _1, _2) - }); - task_->start(); - } - - /** - * @brief Register map for the MT6701. - * - * @note The MT6701 contains a push-button output (pin 5) with configuration - * (mentioned on page 25) via PUSH_THRD register, PUSH_DIFF_DLY - * register, and PUSH_TIME_OUT register. However, the register addresses - * for these configurations (and their bitfields) are not provided in - * the datasheet and must be provided by the manufacturer. - * - * @note The push button can only be read from the MT6701 when using SSI - * communications, and is returned as part of the magnetic field status - * truth table (page 24). - */ - enum class Registers : uint8_t { - ANGLE_H = 0x03, ///< Angle[13:6] - ANGLE_L = 0x04, ///< Angle[5:0] (bit 2-7) - MUX_1 = 0x25, ///< UVW MUX (bit 7) - MUX_2 = 0x29, ///< ABZ MUX (bit 6), DIR (bit 1) - RES_1 = 0x30, ///< UVW_RES (bit 4-7), ABZ_RES[9:8] (bit 0-1) - RES_2 = 0x31, ///< ABZ_RES[7:0] - CONFIG_1= 0x32, ///< HYST[2] (bit 7), Z_PULSE_WIDTH (bit 4-6), ZERO[11:8] (bit 0-3) - CONFIG_2= 0x33, ///< ZERO[7:0] - CONFIG_3= 0x34, ///< HYST[1:0] (bit 6-7) - CONFIG_4= 0x38, ///< PWM_FREQ (bit 7), PWM_POL (bit 6), OUT_MODE (bit 5) - A_SS_HIGH = 0x3E, ///< A_STOP[11:8] (bit 4-7), A_START[11:8] (bit 0-3) - A_START_LOW = 0x3F, ///< A_START[7:0] - A_STOP_LOW = 0x40, ///< A_STOP[7:0] - }; - - write_fn write_; - read_fn read_; - velocity_filter_fn velocity_filter_{nullptr}; - std::chrono::duration update_period_; - std::atomic count_{0}; - std::atomic accumulator_{0}; - std::atomic velocity_rpm_{0}; - std::unique_ptr task_; - espp::Logger logger_; -}; diff --git a/components/nes/CMakeLists.txt b/components/nes/CMakeLists.txt new file mode 100644 index 00000000..d2fb3702 --- /dev/null +++ b/components/nes/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_component_register( + INCLUDE_DIRS "include" + SRC_DIRS "src" "nofrendo/cpu" "nofrendo/libsnss" "nofrendo/nes" "nofrendo/sndhrdw" "nofrendo/mappers" "nofrendo" + PRIV_INCLUDE_DIRS "nofrendo/cpu" "nofrendo/libsnss" "nofrendo/nes" "nofrendo/sndhrdw" "nofrendo" + REQUIRES box-emu-hal + ) +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts -Wno-attributes) diff --git a/main/nes.hpp b/components/nes/include/nes.hpp similarity index 50% rename from main/nes.hpp rename to components/nes/include/nes.hpp index 940b4066..a6c6a4d0 100644 --- a/main/nes.hpp +++ b/components/nes/include/nes.hpp @@ -1,10 +1,18 @@ #pragma once #include +#include +#include +void reset_nes(); void init_nes(const std::string& rom_filename, uint8_t *romdata, size_t rom_data_size); +void load_nes(std::string_view save_path); +void save_nes(std::string_view save_path); +void start_nes_tasks(); +void stop_nes_tasks(); void run_nes_rom(); void deinit_nes(); void set_nes_video_original(); void set_nes_video_fit(); void set_nes_video_fill(); +std::vector get_nes_video_buffer(); diff --git a/components/nofrendo/AUTHORS b/components/nes/nofrendo/AUTHORS similarity index 100% rename from components/nofrendo/AUTHORS rename to components/nes/nofrendo/AUTHORS diff --git a/components/nofrendo/bitmap.c b/components/nes/nofrendo/bitmap.c similarity index 100% rename from components/nofrendo/bitmap.c rename to components/nes/nofrendo/bitmap.c diff --git a/components/nofrendo/bitmap.h b/components/nes/nofrendo/bitmap.h similarity index 100% rename from components/nofrendo/bitmap.h rename to components/nes/nofrendo/bitmap.h diff --git a/components/nofrendo/cpu/dis6502.c b/components/nes/nofrendo/cpu/dis6502.c similarity index 100% rename from components/nofrendo/cpu/dis6502.c rename to components/nes/nofrendo/cpu/dis6502.c diff --git a/components/nofrendo/cpu/dis6502.h b/components/nes/nofrendo/cpu/dis6502.h similarity index 100% rename from components/nofrendo/cpu/dis6502.h rename to components/nes/nofrendo/cpu/dis6502.h diff --git a/components/nofrendo/cpu/nes6502.c b/components/nes/nofrendo/cpu/nes6502.c similarity index 100% rename from components/nofrendo/cpu/nes6502.c rename to components/nes/nofrendo/cpu/nes6502.c diff --git a/components/nofrendo/cpu/nes6502.h b/components/nes/nofrendo/cpu/nes6502.h similarity index 100% rename from components/nofrendo/cpu/nes6502.h rename to components/nes/nofrendo/cpu/nes6502.h diff --git a/components/nofrendo/event.c b/components/nes/nofrendo/event.c similarity index 91% rename from components/nofrendo/event.c rename to components/nes/nofrendo/event.c index b2a56b4a..74c7326e 100644 --- a/components/nofrendo/event.c +++ b/components/nes/nofrendo/event.c @@ -27,7 +27,6 @@ #include #include #include -#include #include /* TODO: put system specific stuff in their own files... */ @@ -81,14 +80,10 @@ static void func_event_hard_reset(int code) static void func_event_snapshot(int code) { - if (INP_STATE_MAKE == code) - gui_savesnap(); } static void func_event_toggle_frameskip(int code) { - if (INP_STATE_MAKE == code) - gui_togglefs(); } static void func_event_state_save(int code) @@ -165,110 +160,74 @@ static void func_event_state_slot_9(int code) static void func_event_gui_toggle_oam(int code) { - if (INP_STATE_MAKE == code) - gui_toggleoam(); } static void func_event_gui_toggle_wave(int code) { - if (INP_STATE_MAKE == code) - gui_togglewave(); } static void func_event_gui_toggle_pattern(int code) { - if (INP_STATE_MAKE == code) - gui_togglepattern(); } static void func_event_gui_pattern_color_up(int code) { - if (INP_STATE_MAKE == code) - gui_incpatterncol(); } static void func_event_gui_pattern_color_down(int code) { - if (INP_STATE_MAKE == code) - gui_decpatterncol(); } static void func_event_gui_toggle_fps(int code) { - if (INP_STATE_MAKE == code) - gui_togglefps(); } static void func_event_gui_display_info(int code) { - if (INP_STATE_MAKE == code) - gui_displayinfo(); } static void func_event_gui_toggle(int code) { - if (INP_STATE_MAKE == code) - gui_togglegui(); } static void func_event_toggle_channel_0(int code) { - if (INP_STATE_MAKE == code) - gui_toggle_chan(0); } static void func_event_toggle_channel_1(int code) { - if (INP_STATE_MAKE == code) - gui_toggle_chan(1); } static void func_event_toggle_channel_2(int code) { - if (INP_STATE_MAKE == code) - gui_toggle_chan(2); } static void func_event_toggle_channel_3(int code) { - if (INP_STATE_MAKE == code) - gui_toggle_chan(3); } static void func_event_toggle_channel_4(int code) { - if (INP_STATE_MAKE == code) - gui_toggle_chan(4); } static void func_event_toggle_channel_5(int code) { - if (INP_STATE_MAKE == code) - gui_toggle_chan(5); } static void func_event_set_filter_0(int code) { - if (INP_STATE_MAKE == code) - gui_setfilter(0); } static void func_event_set_filter_1(int code) { - if (INP_STATE_MAKE == code) - gui_setfilter(1); } static void func_event_set_filter_2(int code) { - if (INP_STATE_MAKE == code) - gui_setfilter(2); } static void func_event_toggle_sprites(int code) { - if (INP_STATE_MAKE == code) - gui_togglesprites(); } static void func_event_palette_hue_up(int code) diff --git a/components/nofrendo/event.h b/components/nes/nofrendo/event.h similarity index 100% rename from components/nofrendo/event.h rename to components/nes/nofrendo/event.h diff --git a/components/nofrendo/intro.c b/components/nes/nofrendo/intro.c similarity index 100% rename from components/nofrendo/intro.c rename to components/nes/nofrendo/intro.c diff --git a/components/nofrendo/intro.h b/components/nes/nofrendo/intro.h similarity index 100% rename from components/nofrendo/intro.h rename to components/nes/nofrendo/intro.h diff --git a/components/nofrendo/libsnss/libsnss.c b/components/nes/nofrendo/libsnss/libsnss.c similarity index 100% rename from components/nofrendo/libsnss/libsnss.c rename to components/nes/nofrendo/libsnss/libsnss.c diff --git a/components/nofrendo/libsnss/libsnss.h b/components/nes/nofrendo/libsnss/libsnss.h similarity index 100% rename from components/nofrendo/libsnss/libsnss.h rename to components/nes/nofrendo/libsnss/libsnss.h diff --git a/components/nofrendo/log.c b/components/nes/nofrendo/log.c similarity index 100% rename from components/nofrendo/log.c rename to components/nes/nofrendo/log.c diff --git a/components/nofrendo/log.h b/components/nes/nofrendo/log.h similarity index 100% rename from components/nofrendo/log.h rename to components/nes/nofrendo/log.h diff --git a/components/nofrendo/mappers/map000.c b/components/nes/nofrendo/mappers/map000.c similarity index 100% rename from components/nofrendo/mappers/map000.c rename to components/nes/nofrendo/mappers/map000.c diff --git a/components/nofrendo/mappers/map001.c b/components/nes/nofrendo/mappers/map001.c similarity index 100% rename from components/nofrendo/mappers/map001.c rename to components/nes/nofrendo/mappers/map001.c diff --git a/components/nofrendo/mappers/map002.c b/components/nes/nofrendo/mappers/map002.c similarity index 100% rename from components/nofrendo/mappers/map002.c rename to components/nes/nofrendo/mappers/map002.c diff --git a/components/nofrendo/mappers/map003.c b/components/nes/nofrendo/mappers/map003.c similarity index 100% rename from components/nofrendo/mappers/map003.c rename to components/nes/nofrendo/mappers/map003.c diff --git a/components/nofrendo/mappers/map004.c b/components/nes/nofrendo/mappers/map004.c similarity index 100% rename from components/nofrendo/mappers/map004.c rename to components/nes/nofrendo/mappers/map004.c diff --git a/components/nofrendo/mappers/map005.c b/components/nes/nofrendo/mappers/map005.c similarity index 100% rename from components/nofrendo/mappers/map005.c rename to components/nes/nofrendo/mappers/map005.c diff --git a/components/nofrendo/mappers/map007.c b/components/nes/nofrendo/mappers/map007.c similarity index 100% rename from components/nofrendo/mappers/map007.c rename to components/nes/nofrendo/mappers/map007.c diff --git a/components/nofrendo/mappers/map008.c b/components/nes/nofrendo/mappers/map008.c similarity index 100% rename from components/nofrendo/mappers/map008.c rename to components/nes/nofrendo/mappers/map008.c diff --git a/components/nofrendo/mappers/map009.c b/components/nes/nofrendo/mappers/map009.c similarity index 100% rename from components/nofrendo/mappers/map009.c rename to components/nes/nofrendo/mappers/map009.c diff --git a/components/nofrendo/mappers/map010.c b/components/nes/nofrendo/mappers/map010.c similarity index 100% rename from components/nofrendo/mappers/map010.c rename to components/nes/nofrendo/mappers/map010.c diff --git a/components/nofrendo/mappers/map011.c b/components/nes/nofrendo/mappers/map011.c similarity index 100% rename from components/nofrendo/mappers/map011.c rename to components/nes/nofrendo/mappers/map011.c diff --git a/components/nofrendo/mappers/map015.c b/components/nes/nofrendo/mappers/map015.c similarity index 100% rename from components/nofrendo/mappers/map015.c rename to components/nes/nofrendo/mappers/map015.c diff --git a/components/nofrendo/mappers/map016.c b/components/nes/nofrendo/mappers/map016.c similarity index 100% rename from components/nofrendo/mappers/map016.c rename to components/nes/nofrendo/mappers/map016.c diff --git a/components/nofrendo/mappers/map018.c b/components/nes/nofrendo/mappers/map018.c similarity index 100% rename from components/nofrendo/mappers/map018.c rename to components/nes/nofrendo/mappers/map018.c diff --git a/components/nofrendo/mappers/map019.c b/components/nes/nofrendo/mappers/map019.c similarity index 100% rename from components/nofrendo/mappers/map019.c rename to components/nes/nofrendo/mappers/map019.c diff --git a/components/nofrendo/mappers/map024.c b/components/nes/nofrendo/mappers/map024.c similarity index 100% rename from components/nofrendo/mappers/map024.c rename to components/nes/nofrendo/mappers/map024.c diff --git a/components/nofrendo/mappers/map032.c b/components/nes/nofrendo/mappers/map032.c similarity index 100% rename from components/nofrendo/mappers/map032.c rename to components/nes/nofrendo/mappers/map032.c diff --git a/components/nofrendo/mappers/map033.c b/components/nes/nofrendo/mappers/map033.c similarity index 100% rename from components/nofrendo/mappers/map033.c rename to components/nes/nofrendo/mappers/map033.c diff --git a/components/nofrendo/mappers/map034.c b/components/nes/nofrendo/mappers/map034.c similarity index 100% rename from components/nofrendo/mappers/map034.c rename to components/nes/nofrendo/mappers/map034.c diff --git a/components/nofrendo/mappers/map040.c b/components/nes/nofrendo/mappers/map040.c similarity index 100% rename from components/nofrendo/mappers/map040.c rename to components/nes/nofrendo/mappers/map040.c diff --git a/components/nofrendo/mappers/map041.c b/components/nes/nofrendo/mappers/map041.c similarity index 100% rename from components/nofrendo/mappers/map041.c rename to components/nes/nofrendo/mappers/map041.c diff --git a/components/nofrendo/mappers/map042.c b/components/nes/nofrendo/mappers/map042.c similarity index 100% rename from components/nofrendo/mappers/map042.c rename to components/nes/nofrendo/mappers/map042.c diff --git a/components/nofrendo/mappers/map046.c b/components/nes/nofrendo/mappers/map046.c similarity index 100% rename from components/nofrendo/mappers/map046.c rename to components/nes/nofrendo/mappers/map046.c diff --git a/components/nofrendo/mappers/map050.c b/components/nes/nofrendo/mappers/map050.c similarity index 100% rename from components/nofrendo/mappers/map050.c rename to components/nes/nofrendo/mappers/map050.c diff --git a/components/nofrendo/mappers/map064.c b/components/nes/nofrendo/mappers/map064.c similarity index 100% rename from components/nofrendo/mappers/map064.c rename to components/nes/nofrendo/mappers/map064.c diff --git a/components/nofrendo/mappers/map065.c b/components/nes/nofrendo/mappers/map065.c similarity index 100% rename from components/nofrendo/mappers/map065.c rename to components/nes/nofrendo/mappers/map065.c diff --git a/components/nofrendo/mappers/map066.c b/components/nes/nofrendo/mappers/map066.c similarity index 100% rename from components/nofrendo/mappers/map066.c rename to components/nes/nofrendo/mappers/map066.c diff --git a/components/nofrendo/mappers/map070.c b/components/nes/nofrendo/mappers/map070.c similarity index 100% rename from components/nofrendo/mappers/map070.c rename to components/nes/nofrendo/mappers/map070.c diff --git a/components/nofrendo/mappers/map073.c b/components/nes/nofrendo/mappers/map073.c similarity index 100% rename from components/nofrendo/mappers/map073.c rename to components/nes/nofrendo/mappers/map073.c diff --git a/components/nofrendo/mappers/map075.c b/components/nes/nofrendo/mappers/map075.c similarity index 100% rename from components/nofrendo/mappers/map075.c rename to components/nes/nofrendo/mappers/map075.c diff --git a/components/nofrendo/mappers/map078.c b/components/nes/nofrendo/mappers/map078.c similarity index 100% rename from components/nofrendo/mappers/map078.c rename to components/nes/nofrendo/mappers/map078.c diff --git a/components/nofrendo/mappers/map079.c b/components/nes/nofrendo/mappers/map079.c similarity index 100% rename from components/nofrendo/mappers/map079.c rename to components/nes/nofrendo/mappers/map079.c diff --git a/components/nofrendo/mappers/map085.c b/components/nes/nofrendo/mappers/map085.c similarity index 100% rename from components/nofrendo/mappers/map085.c rename to components/nes/nofrendo/mappers/map085.c diff --git a/components/nofrendo/mappers/map087.c b/components/nes/nofrendo/mappers/map087.c similarity index 100% rename from components/nofrendo/mappers/map087.c rename to components/nes/nofrendo/mappers/map087.c diff --git a/components/nofrendo/mappers/map093.c b/components/nes/nofrendo/mappers/map093.c similarity index 100% rename from components/nofrendo/mappers/map093.c rename to components/nes/nofrendo/mappers/map093.c diff --git a/components/nofrendo/mappers/map094.c b/components/nes/nofrendo/mappers/map094.c similarity index 100% rename from components/nofrendo/mappers/map094.c rename to components/nes/nofrendo/mappers/map094.c diff --git a/components/nofrendo/mappers/map099.c b/components/nes/nofrendo/mappers/map099.c similarity index 100% rename from components/nofrendo/mappers/map099.c rename to components/nes/nofrendo/mappers/map099.c diff --git a/components/nofrendo/mappers/map160.c b/components/nes/nofrendo/mappers/map160.c similarity index 100% rename from components/nofrendo/mappers/map160.c rename to components/nes/nofrendo/mappers/map160.c diff --git a/components/nofrendo/mappers/map229.c b/components/nes/nofrendo/mappers/map229.c similarity index 100% rename from components/nofrendo/mappers/map229.c rename to components/nes/nofrendo/mappers/map229.c diff --git a/components/nofrendo/mappers/map231.c b/components/nes/nofrendo/mappers/map231.c similarity index 100% rename from components/nofrendo/mappers/map231.c rename to components/nes/nofrendo/mappers/map231.c diff --git a/components/nofrendo/mappers/mapvrc.c b/components/nes/nofrendo/mappers/mapvrc.c similarity index 100% rename from components/nofrendo/mappers/mapvrc.c rename to components/nes/nofrendo/mappers/mapvrc.c diff --git a/components/nofrendo/memguard.c b/components/nes/nofrendo/memguard.c similarity index 100% rename from components/nofrendo/memguard.c rename to components/nes/nofrendo/memguard.c diff --git a/components/nofrendo/memguard.h b/components/nes/nofrendo/memguard.h similarity index 100% rename from components/nofrendo/memguard.h rename to components/nes/nofrendo/memguard.h diff --git a/components/nofrendo/nes/mmclist.c b/components/nes/nofrendo/nes/mmclist.c similarity index 100% rename from components/nofrendo/nes/mmclist.c rename to components/nes/nofrendo/nes/mmclist.c diff --git a/components/nofrendo/nes/mmclist.h b/components/nes/nofrendo/nes/mmclist.h similarity index 100% rename from components/nofrendo/nes/mmclist.h rename to components/nes/nofrendo/nes/mmclist.h diff --git a/components/nofrendo/nes/nes.c b/components/nes/nofrendo/nes/nes.c similarity index 99% rename from components/nofrendo/nes/nes.c rename to components/nes/nofrendo/nes/nes.c index 336f39ca..e0244c23 100644 --- a/components/nofrendo/nes/nes.c +++ b/components/nes/nofrendo/nes/nes.c @@ -31,7 +31,6 @@ #include "nes6502.h" #include #include -#include #include #include #include @@ -459,8 +458,8 @@ void nes_reset(int reset_type) nes.scanline = 241; - gui_sendmsg(GUI_GREEN, "NES %s", - (HARD_RESET == reset_type) ? "powered on" : "reset"); + /* gui_sendmsg(GUI_GREEN, "NES %s", */ + /* (HARD_RESET == reset_type) ? "powered on" : "reset"); */ } void nes_destroy(nes_t **machine) diff --git a/components/nofrendo/nes/nes.h b/components/nes/nofrendo/nes/nes.h similarity index 100% rename from components/nofrendo/nes/nes.h rename to components/nes/nofrendo/nes/nes.h diff --git a/components/nofrendo/nes/nes_mmc.c b/components/nes/nofrendo/nes/nes_mmc.c similarity index 100% rename from components/nofrendo/nes/nes_mmc.c rename to components/nes/nofrendo/nes/nes_mmc.c diff --git a/components/nofrendo/nes/nes_mmc.h b/components/nes/nofrendo/nes/nes_mmc.h similarity index 100% rename from components/nofrendo/nes/nes_mmc.h rename to components/nes/nofrendo/nes/nes_mmc.h diff --git a/components/nofrendo/nes/nes_pal.c b/components/nes/nofrendo/nes/nes_pal.c similarity index 96% rename from components/nofrendo/nes/nes_pal.c rename to components/nes/nofrendo/nes/nes_pal.c index 5756ba5e..0c9d917a 100644 --- a/components/nofrendo/nes/nes_pal.c +++ b/components/nes/nofrendo/nes/nes_pal.c @@ -67,30 +67,24 @@ rgb_t nes_palette[64]; static float hue = 334.0f; static float tint = 0.4f; -#include - void pal_dechue(void) { hue -= 0.5f; - gui_sendmsg(GUI_GREEN, "hue: %.02f", hue); pal_generate(); } void pal_inchue(void) { hue += 0.5f; - gui_sendmsg(GUI_GREEN, "hue: %.02f", hue); pal_generate(); } void pal_dectint(void) { tint -= 0.01f; - gui_sendmsg(GUI_GREEN, "tint: %.02f", tint); pal_generate(); } void pal_inctint(void) { tint += 0.01f; - gui_sendmsg(GUI_GREEN, "tint: %.02f", tint); pal_generate(); } diff --git a/components/nofrendo/nes/nes_pal.h b/components/nes/nofrendo/nes/nes_pal.h similarity index 100% rename from components/nofrendo/nes/nes_pal.h rename to components/nes/nofrendo/nes/nes_pal.h diff --git a/components/nofrendo/nes/nes_ppu.c b/components/nes/nofrendo/nes/nes_ppu.c similarity index 92% rename from components/nofrendo/nes/nes_ppu.c rename to components/nes/nofrendo/nes/nes_ppu.c index a3386f3f..dcef6527 100644 --- a/components/nofrendo/nes/nes_ppu.c +++ b/components/nes/nofrendo/nes/nes_ppu.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "nes6502.h" #include #include @@ -541,13 +540,6 @@ static void ppu_buildpalette(ppu_t *src_ppu, rgb_t *pal) src_ppu->curpal[i].b = src_ppu->curpal[i + 64].b = src_ppu->curpal[i + 128].b = pal[i].b; } - - for (i = 0; i < GUI_TOTALCOLORS; i++) - { - src_ppu->curpal[i + 192].r = gui_pal[i].r; - src_ppu->curpal[i + 192].g = gui_pal[i].g; - src_ppu->curpal[i + 192].b = gui_pal[i].b; - } } /* build the emulator specific palette based on a 64-entry palette @@ -1117,51 +1109,6 @@ bool ppu_checkzapperhit(bitmap_t *bmp, int x, int y) /*************************************************/ /* TODO: all this stuff should go somewhere else */ /*************************************************/ -INLINE void draw_box(bitmap_t *bmp, int x, int y, int height) -{ - int i; - uint8 *vid; - - vid = bmp->line[y] + x; - - for (i = 0; i < 10; i++) - *vid++ = GUI_GRAY; - vid += (bmp->pitch - 10); - for (i = 0; i < height; i++) - { - vid[0] = vid[9] = GUI_GRAY; - vid += bmp->pitch; - } - for (i = 0; i < 10; i++) - *vid++ = GUI_GRAY; -} - -INLINE void draw_deadsprite(bitmap_t *bmp, int x, int y, int height) -{ - int i, j, index; - uint8 *vid; - uint8 colbuf[8] = { GUI_BLACK, GUI_BLACK, GUI_BLACK, GUI_BLACK, - GUI_BLACK, GUI_BLACK, GUI_BLACK, GUI_DKGRAY }; - - vid = bmp->line[y] + x; - - for (i = 0; i < height; i++) - { - index = i; - - if (height == 16) - index >>= 1; - - for (j = 0; j < 8; j++) - { - *(vid + j) = colbuf[index++]; - index &= 7; - } - - vid += bmp->pitch; - } -} - /* Stuff for the OAM viewer */ static void draw_sprite(bitmap_t *bmp, int x, int y, uint8 tile_num, uint8 attrib) @@ -1198,68 +1145,6 @@ static void draw_sprite(bitmap_t *bmp, int x, int y, uint8 tile_num, uint8 attri } } -void ppu_dumpoam(bitmap_t *bmp, int x_loc, int y_loc) -{ - int sprite, x_pos, y_pos, height; - obj_t *spr_ptr; - - spr_ptr = (obj_t *) ppu.oam; - height = ppu.obj_height; - - for (sprite = 0; sprite < 64; sprite++) - { - x_pos = ((sprite & 0x0F) << 3) + (sprite & 0x0F) + x_loc; - if (height == 16) - y_pos = (sprite & 0xF0) + (sprite >> 4) + y_loc; - else - y_pos = ((sprite & 0xF0) >> 1) + (sprite >> 4) + y_loc; - - draw_box(bmp, x_pos, y_pos, height); - - if (spr_ptr->y_loc && spr_ptr->y_loc < 240) - draw_sprite(bmp, x_pos + 1, y_pos + 1, spr_ptr->tile, spr_ptr->atr); - else - draw_deadsprite(bmp, x_pos + 1, y_pos + 1, height); - - spr_ptr++; - } -} - -/* More of a debugging thing than anything else */ -void ppu_dumppattern(bitmap_t *bmp, int table_num, int x_loc, int y_loc, int col) -{ - int x_tile, y_tile; - uint8 *bmp_ptr, *data_ptr, *ptr; - int tile_num, line; - uint8 col_high; - - tile_num = 0; - col_high = col << 2; - - for (y_tile = 0; y_tile < 16; y_tile++) - { - /* Get our pointer to the bitmap */ - bmp_ptr = bmp->line[y_loc] + x_loc; - - for (x_tile = 0; x_tile < 16; x_tile++) - { - data_ptr = &PPU_MEM((table_num << 12) + (tile_num << 4)); - ptr = bmp_ptr; - - for (line = 0; line < 8; line ++) - { - draw_bgtile(ptr, data_ptr[0], data_ptr[8], ppu.palette + col_high); - data_ptr++; - ptr += bmp->pitch; - } - - bmp_ptr += 8; - tile_num++; - } - y_loc += 8; - } -} - /* ** $Log: nes_ppu.c,v $ ** Revision 1.2 2001/04/27 14:37:11 neil diff --git a/components/nofrendo/nes/nes_ppu.h b/components/nes/nofrendo/nes/nes_ppu.h similarity index 100% rename from components/nofrendo/nes/nes_ppu.h rename to components/nes/nofrendo/nes/nes_ppu.h diff --git a/components/nofrendo/nes/nes_rom.c b/components/nes/nofrendo/nes/nes_rom.c similarity index 96% rename from components/nofrendo/nes/nes_rom.c rename to components/nes/nofrendo/nes/nes_rom.c index b414e0bd..c2b56d75 100644 --- a/components/nofrendo/nes/nes_rom.c +++ b/components/nes/nofrendo/nes/nes_rom.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -94,7 +93,11 @@ static void rom_savesram(rominfo_t *rominfo) if (rominfo->flags & ROM_FLAG_BATTERY) { memcpy(fn, rominfo->filename, PATH_MAX); - osd_newextension(fn, ".sav"); + + // TODO: see if this was actually running since the implementation of this + // function was actually just returning fn... + + // osd_newextension(fn, ".sav"); fp = fopen(fn, "wb"); if (NULL != fp) @@ -117,7 +120,11 @@ static void rom_loadsram(rominfo_t *rominfo) if (rominfo->flags & ROM_FLAG_BATTERY) { memcpy(fn, rominfo->filename, PATH_MAX); - osd_newextension(fn, ".sav"); + + // TODO: see if this was actually running since the implementation of this + // function was actually just returning fn... + + // osd_newextension(fn, ".sav"); fp = fopen(fn, "rb"); if (NULL != fp) @@ -170,7 +177,6 @@ static int rom_loadrom(unsigned char **rom, rominfo_t *rominfo) rominfo->rom = _my_malloc((rominfo->rom_banks * ROM_BANK_LENGTH)); if (NULL == rominfo->rom) { - gui_sendmsg(GUI_RED, "Could not allocate space for ROM image"); return -1; } _fread(rominfo->rom, ROM_BANK_LENGTH, rominfo->rom_banks, fp); @@ -186,7 +192,6 @@ static int rom_loadrom(unsigned char **rom, rominfo_t *rominfo) rominfo->vrom = _my_malloc((rominfo->vrom_banks * VROM_BANK_LENGTH)); if (NULL == rominfo->vrom) { - gui_sendmsg(GUI_RED, "Could not allocate space for VROM"); return -1; } _fread(rominfo->vrom, VROM_BANK_LENGTH, rominfo->vrom_banks, fp); @@ -220,7 +225,8 @@ static void rom_checkforpal(rominfo_t *rominfo) ASSERT(rominfo); memcpy(filename, rominfo->filename, PATH_MAX); - osd_newextension(filename, ".pal"); + + // osd_newextension(filename, ".pal"); fp = fopen(filename, "rb"); if (NULL == fp) @@ -343,7 +349,6 @@ static int rom_getheader(unsigned char **rom, rominfo_t *rominfo) if (memcmp(head.ines_magic, ROM_INES_MAGIC, 4)) { - gui_sendmsg(GUI_RED, "%s is not a valid ROM image", rominfo->filename); return -1; } @@ -458,7 +463,6 @@ rominfo_t *nes_rom_load(const char *filename) /* Make sure we really support the mapper */ if (false == mmc_peek(rominfo->mapper_number)) { - gui_sendmsg(GUI_RED, "Mapper %d not yet implemented", rominfo->mapper_number); goto _fail; } @@ -479,8 +483,6 @@ rominfo_t *nes_rom_load(const char *filename) /* See if there's a palette we can load up */ // rom_checkforpal(rominfo); - gui_sendmsg(GUI_GREEN, "ROM loaded: %s", rom_getinfo(rominfo)); - return rominfo; _fail: @@ -493,7 +495,6 @@ void rom_free(rominfo_t **rominfo) { if (NULL == *rominfo) { - gui_sendmsg(GUI_GREEN, "ROM not loaded"); return; } @@ -518,7 +519,6 @@ void rom_free(rominfo_t **rominfo) free(*rominfo); - gui_sendmsg(GUI_GREEN, "ROM freed"); } /* diff --git a/components/nofrendo/nes/nes_rom.h b/components/nes/nofrendo/nes/nes_rom.h similarity index 100% rename from components/nofrendo/nes/nes_rom.h rename to components/nes/nofrendo/nes/nes_rom.h diff --git a/components/nofrendo/nes/nesinput.c b/components/nes/nofrendo/nes/nesinput.c similarity index 100% rename from components/nofrendo/nes/nesinput.c rename to components/nes/nofrendo/nes/nesinput.c diff --git a/components/nofrendo/nes/nesinput.h b/components/nes/nofrendo/nes/nesinput.h similarity index 100% rename from components/nofrendo/nes/nesinput.h rename to components/nes/nofrendo/nes/nesinput.h diff --git a/components/nofrendo/nes/nesstate.c b/components/nes/nofrendo/nes/nesstate.c similarity index 89% rename from components/nofrendo/nes/nesstate.c rename to components/nes/nofrendo/nes/nesstate.c index 8e411d83..36b09bb4 100644 --- a/components/nofrendo/nes/nesstate.c +++ b/components/nes/nofrendo/nes/nesstate.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -52,7 +51,6 @@ void state_setslot(int slot) && slot <= LAST_STATE_SLOT) { state_slot = slot; - gui_sendmsg(GUI_WHITE, "State slot set to %d", slot); } } @@ -528,7 +526,6 @@ static int state_load(char* fn, nes_t* machine) return 0; _error: - gui_sendmsg(GUI_RED, "error: %s", SNSS_GetErrorString(status)); SNSS_CloseFile(&snssFile); abort(); } @@ -536,76 +533,18 @@ static int state_load(char* fn, nes_t* machine) void save_sram(char* filename, nes_t *machine) { -#if 0 - char* romPath = odroid_settings_RomFilePath_get(); - if (romPath) - { - esp_err_t r = odroid_sdcard_open(SD_BASE_PATH); - if (r != ESP_OK) - { - odroid_display_show_sderr(ODROID_SD_ERR_NOCARD); - abort(); - } - - char* fileName = odroid_util_GetFileName(romPath); - if (!fileName) abort(); - - char* pathName = odroid_sdcard_create_savefile_path(SD_BASE_PATH, fileName); - if (!pathName) abort(); - - state_save(pathName); - - free(pathName); - free(fileName); - free(romPath); - - r = odroid_sdcard_close(); - if (r != ESP_OK) - { - odroid_display_show_sderr(ODROID_SD_ERR_NOCARD); - abort(); - } - } -#else + if (!filename) { + return; + } state_save(filename, machine); -#endif } void load_sram(char* filename, nes_t *machine) { -#if 0 - char* romName = odroid_settings_RomFilePath_get(); - if (romName) - { - esp_err_t r = odroid_sdcard_open(SD_BASE_PATH); - if (r != ESP_OK) - { - odroid_display_show_sderr(ODROID_SD_ERR_NOCARD); - abort(); - } - - char* fileName = odroid_util_GetFileName(romName); - if (!fileName) abort(); - - char* pathName = odroid_sdcard_create_savefile_path(SD_BASE_PATH, fileName); - if (!pathName) abort(); - - state_load(pathName); - - free(pathName); - free(fileName); - free(romName); - - r = odroid_sdcard_close(); - if (r != ESP_OK) - { - odroid_display_show_sderr(ODROID_SD_ERR_NOCARD); - abort(); - } - } -#else + if (!filename) { + return; + } state_load(filename, machine); -#endif } /* diff --git a/components/nofrendo/nes/nesstate.h b/components/nes/nofrendo/nes/nesstate.h similarity index 100% rename from components/nofrendo/nes/nesstate.h rename to components/nes/nofrendo/nes/nesstate.h diff --git a/components/nofrendo/nofconfig.h b/components/nes/nofrendo/nofconfig.h similarity index 100% rename from components/nofrendo/nofconfig.h rename to components/nes/nofrendo/nofconfig.h diff --git a/components/nofrendo/nofrendo.c b/components/nes/nofrendo/nofrendo.c similarity index 98% rename from components/nofrendo/nofrendo.c rename to components/nes/nofrendo/nofrendo.c index 45b06253..31c3dfd8 100644 --- a/components/nofrendo/nofrendo.c +++ b/components/nes/nofrendo/nofrendo.c @@ -32,7 +32,6 @@ #include #include #include -#include #include /* emulated system includes */ @@ -82,7 +81,6 @@ static void shutdown_everything(void) config.close(); osd_shutdown(); - gui_shutdown(); vid_shutdown(); log_shutdown(); } @@ -162,8 +160,6 @@ static int internal_insert(const char *filename, system_t type) switch (console.type) { case system_nes: - gui_setrefresh(NES_REFRESH_RATE); - console.machine.nes = nes_create(); console_nes = console.machine.nes; @@ -238,9 +234,6 @@ int main_loop(const char *filename, system_t type) if (osd_init()) return -1; - if (gui_init()) - return -1; - osd_getvideoinfo(&video); if (vid_init(video.default_width, video.default_height, video.driver)) return -1; diff --git a/components/nofrendo/nofrendo.h b/components/nes/nofrendo/nofrendo.h similarity index 100% rename from components/nofrendo/nofrendo.h rename to components/nes/nofrendo/nofrendo.h diff --git a/components/nofrendo/noftypes.h b/components/nes/nofrendo/noftypes.h similarity index 100% rename from components/nofrendo/noftypes.h rename to components/nes/nofrendo/noftypes.h diff --git a/components/nofrendo/osd.h b/components/nes/nofrendo/osd.h similarity index 99% rename from components/nofrendo/osd.h rename to components/nes/nofrendo/osd.h index ad0a77f2..8957997a 100644 --- a/components/nofrendo/osd.h +++ b/components/nes/nofrendo/osd.h @@ -74,6 +74,7 @@ typedef struct sndinfo_s extern void osd_set_video_scale(bool new_video_scale); +extern uint16_t* get_nes_palette(); /* get info */ extern void osd_getvideoinfo(vidinfo_t *info); extern void osd_getsoundinfo(sndinfo_t *info); diff --git a/components/nofrendo/pcx.c b/components/nes/nofrendo/pcx.c similarity index 100% rename from components/nofrendo/pcx.c rename to components/nes/nofrendo/pcx.c diff --git a/components/nofrendo/pcx.h b/components/nes/nofrendo/pcx.h similarity index 100% rename from components/nofrendo/pcx.h rename to components/nes/nofrendo/pcx.h diff --git a/components/nofrendo/sndhrdw/fds_snd.c b/components/nes/nofrendo/sndhrdw/fds_snd.c similarity index 100% rename from components/nofrendo/sndhrdw/fds_snd.c rename to components/nes/nofrendo/sndhrdw/fds_snd.c diff --git a/components/nofrendo/sndhrdw/fds_snd.h b/components/nes/nofrendo/sndhrdw/fds_snd.h similarity index 100% rename from components/nofrendo/sndhrdw/fds_snd.h rename to components/nes/nofrendo/sndhrdw/fds_snd.h diff --git a/components/nofrendo/sndhrdw/mmc5_snd.c b/components/nes/nofrendo/sndhrdw/mmc5_snd.c similarity index 100% rename from components/nofrendo/sndhrdw/mmc5_snd.c rename to components/nes/nofrendo/sndhrdw/mmc5_snd.c diff --git a/components/nofrendo/sndhrdw/mmc5_snd.h b/components/nes/nofrendo/sndhrdw/mmc5_snd.h similarity index 100% rename from components/nofrendo/sndhrdw/mmc5_snd.h rename to components/nes/nofrendo/sndhrdw/mmc5_snd.h diff --git a/components/nofrendo/sndhrdw/nes_apu.c b/components/nes/nofrendo/sndhrdw/nes_apu.c similarity index 99% rename from components/nofrendo/sndhrdw/nes_apu.c rename to components/nes/nofrendo/sndhrdw/nes_apu.c index 44480980..c09dee05 100644 --- a/components/nofrendo/sndhrdw/nes_apu.c +++ b/components/nes/nofrendo/sndhrdw/nes_apu.c @@ -30,7 +30,7 @@ #include "nes6502.h" -#define APU_OVERSAMPLE +// #define APU_OVERSAMPLE #define APU_VOLUME_DECAY(x) ((x) -= ((x) >> 7)) /* the following seem to be the correct (empirically determined) @@ -402,7 +402,7 @@ static int32 apu_noise(void) #if defined(APU_OVERSAMPLE) && defined(REALTIME_NOISE) #else /* !(APU_OVERSAMPLE && REALTIME_NOISE) */ - int32 noise_bit; + int32 noise_bit=0; #endif /* !(APU_OVERSAMPLE && REALTIME_NOISE) */ #ifdef APU_OVERSAMPLE int num_times; diff --git a/components/nofrendo/sndhrdw/nes_apu.h b/components/nes/nofrendo/sndhrdw/nes_apu.h similarity index 100% rename from components/nofrendo/sndhrdw/nes_apu.h rename to components/nes/nofrendo/sndhrdw/nes_apu.h diff --git a/components/nofrendo/sndhrdw/vrcvisnd.c b/components/nes/nofrendo/sndhrdw/vrcvisnd.c similarity index 100% rename from components/nofrendo/sndhrdw/vrcvisnd.c rename to components/nes/nofrendo/sndhrdw/vrcvisnd.c diff --git a/components/nofrendo/sndhrdw/vrcvisnd.h b/components/nes/nofrendo/sndhrdw/vrcvisnd.h similarity index 100% rename from components/nofrendo/sndhrdw/vrcvisnd.h rename to components/nes/nofrendo/sndhrdw/vrcvisnd.h diff --git a/components/nofrendo/version.h b/components/nes/nofrendo/version.h similarity index 100% rename from components/nofrendo/version.h rename to components/nes/nofrendo/version.h diff --git a/components/nofrendo/vid_drv.c b/components/nes/nofrendo/vid_drv.c similarity index 97% rename from components/nofrendo/vid_drv.c rename to components/nes/nofrendo/vid_drv.c index 6c42c6a9..8f3c2611 100644 --- a/components/nofrendo/vid_drv.c +++ b/components/nes/nofrendo/vid_drv.c @@ -28,10 +28,11 @@ #include #include #include -#include #include +#define COLOR_BLACK 0x00 + /* hardware surface */ static bitmap_t *screen = NULL; @@ -379,16 +380,7 @@ int vid_setmode(int width, int height) } /* Create our backbuffer */ -#if 0 - back_buffer = bmp_create(width, height, 0); /* no overdraw */ - if (NULL == back_buffer) - { - bmp_destroy(&primary_buffer); - return -1; - } - bmp_clear(back_buffer, GUI_BLACK); -#endif - bmp_clear(primary_buffer, GUI_BLACK); + bmp_clear(primary_buffer, COLOR_BLACK); return 0; } @@ -409,9 +401,9 @@ static int vid_findmode(int width, int height, viddriver_t *osd_driver) /* use custom pageclear, if necessary */ if (driver->clear) - driver->clear(GUI_BLACK); + driver->clear(COLOR_BLACK); else - bmp_clear(screen, GUI_BLACK); + bmp_clear(screen, COLOR_BLACK); /* release surface */ if (driver->free_write) diff --git a/components/nofrendo/vid_drv.h b/components/nes/nofrendo/vid_drv.h similarity index 100% rename from components/nofrendo/vid_drv.h rename to components/nes/nofrendo/vid_drv.h diff --git a/main/nes.cpp b/components/nes/src/nes.cpp similarity index 55% rename from main/nes.cpp rename to components/nes/src/nes.cpp index c7197184..54ea90f8 100644 --- a/main/nes.cpp +++ b/components/nes/src/nes.cpp @@ -1,22 +1,18 @@ #include "nes.hpp" -#ifdef USE_NES_NOFRENDO extern "C" { #include "event.h" -#include "gui.h" #include #include } static nes_t* console_nes; -#endif #include #include "fs_init.hpp" #include "format.hpp" #include "spi_lcd.h" -#include "input.h" #include "st7789.hpp" static std::atomic scaled = false; @@ -40,31 +36,16 @@ void set_nes_video_fill() { osd_set_video_scale(true); } -static std::string nes_savedir = "/sdcard/saves"; -static std::string current_cart = ""; - -static std::string get_save_path(bool bypass_exist_check=false) { - namespace fs = std::filesystem; - fmt::print("creating: {}\n", nes_savedir); - // fs::create_directories(nes_savedir); - mkdirp(nes_savedir.c_str()); - auto save_path = nes_savedir + "/" + fs::path(current_cart).stem().string() + "_nes.sav"; - if (bypass_exist_check || fs::exists(save_path)) { - fmt::print("found: {}\n", save_path); - return save_path; - } else { - fmt::print("Could not find {}\n", save_path); - } - return ""; +void reset_nes() { + nes_reset(SOFT_RESET); } +static uint8_t first_frame = 0; void init_nes(const std::string& rom_filename, uint8_t *romdata, size_t rom_data_size) { -#ifdef USE_NES_NOFRENDO static bool initialized = false; if (!initialized) { event_init(); osd_init(); - gui_init(); vidinfo_t video; osd_getvideoinfo(&video); vid_init(video.default_width, video.default_height, video.driver); @@ -74,32 +55,50 @@ void init_nes(const std::string& rom_filename, uint8_t *romdata, size_t rom_data nes_reset(HARD_RESET); } initialized = true; - current_cart = rom_filename; nes_insertcart(rom_filename.c_str(), console_nes); vid_setmode(NES_SCREEN_WIDTH, NES_VISIBLE_HEIGHT); - nes_prep_emulation((char*)get_save_path().c_str(), console_nes); -#endif + nes_prep_emulation(nullptr, console_nes); + first_frame = 1; } void run_nes_rom() { - // we have to call touchpad_read to determine if the user needs to quit... - uint8_t _num_touches, _btn_state; - uint16_t _x,_y; - touchpad_read(&_num_touches, &_x, &_y, &_btn_state); -#ifdef USE_NES_NOFRENDO auto start = std::chrono::high_resolution_clock::now(); - nes_emulateframe(0); + nes_emulateframe(first_frame); + first_frame = 0; // frame rate should be 60 FPS, so 1/60th second is what we want to sleep for auto delay = std::chrono::duration(1.0f/60.0f); std::this_thread::sleep_until(start + delay); -#endif +} + +void load_nes(std::string_view save_path) { + nes_prep_emulation((char *)save_path.data(), console_nes); +} + +void save_nes(std::string_view save_path) { + save_sram((char *)save_path.data(), console_nes); +} + +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(); + for (int i = 0; i < NES_SCREEN_WIDTH * NES_VISIBLE_HEIGHT; i++) { + uint8_t index = frame_buffer0[i]; + uint16_t color = palette[index]; + frame[i * 2] = color & 0xFF; + frame[i * 2 + 1] = color >> 8; + } + return frame; +} + +void stop_nes_tasks() { +} + +void start_nes_tasks() { } void deinit_nes() { - // save state here - save_sram((char*)get_save_path(true).c_str(), console_nes); -#ifdef USE_NES_NOFRENDO nes_poweroff(); - // nes_destroy(&console_nes); -#endif } diff --git a/components/nofrendo-esp32/osd.c b/components/nes/src/osd.c similarity index 78% rename from components/nofrendo-esp32/osd.c rename to components/nes/src/osd.c index 9a06f1a3..f6addd4d 100644 --- a/components/nofrendo-esp32/osd.c +++ b/components/nes/src/osd.c @@ -82,25 +82,25 @@ int osd_main(int argc, char *argv[]) // } - config.filename = configfilename; + // config.filename = configfilename; return main_loop(argv[0], system_nes); } -/* File system interface */ -void osd_fullname(char *fullname, const char *shortname) -{ - strncpy(fullname, shortname, PATH_MAX); -} +/* /\* File system interface *\/ */ +/* void osd_fullname(char *fullname, const char *shortname) */ +/* { */ +/* strncpy(fullname, shortname, PATH_MAX); */ +/* } */ -/* This gives filenames for storage of saves */ -char *osd_newextension(char *string, char *ext) -{ - return string; -} +/* /\* This gives filenames for storage of saves *\/ */ +/* char *osd_newextension(char *string, char *ext) */ +/* { */ +/* return string; */ +/* } */ -/* This gives filenames for storage of PCX snapshots */ -int osd_makesnapname(char *filename, int len) -{ - return -1; -} +/* /\* This gives filenames for storage of PCX snapshots *\/ */ +/* int osd_makesnapname(char *filename, int len) */ +/* { */ +/* return -1; */ +/* } */ diff --git a/components/nofrendo-esp32/video_audio.c b/components/nes/src/video_audio.c similarity index 96% rename from components/nofrendo-esp32/video_audio.c rename to components/nes/src/video_audio.c index e005c443..9324cfa5 100644 --- a/components/nofrendo-esp32/video_audio.c +++ b/components/nes/src/video_audio.c @@ -42,7 +42,7 @@ #include "i2s_audio.h" #include "input.h" -#define DEFAULT_FRAGSIZE 4096 +#define DEFAULT_FRAGSIZE AUDIO_BUFFER_SIZE #define DEFAULT_WIDTH 256 #define DEFAULT_HEIGHT NES_VISIBLE_HEIGHT @@ -143,6 +143,7 @@ static bool prev_scale_video = false; void osd_set_video_scale(bool new_video_scale) { scale_video = new_video_scale; } + void ili9341_write_frame_nes(const uint8_t* buffer, uint16_t* myPalette) { short x, y; int x_offset = (320-256)/2; @@ -160,7 +161,7 @@ void ili9341_write_frame_nes(const uint8_t* buffer, uint16_t* myPalette) { if (scale_video) { uint8_t* framePtr = buffer; static int buffer_index = 0; - static const int LINE_COUNT = 50; + static const int LINE_COUNT = NUM_ROWS_IN_FRAME_BUFFER; float x_scale = 1.25f; float y_scale = 1.0f; for (y = 0; y < 240; y+= LINE_COUNT) { @@ -183,7 +184,7 @@ void ili9341_write_frame_nes(const uint8_t* buffer, uint16_t* myPalette) { } else { uint8_t* framePtr = buffer; static int buffer_index = 0; - static const int LINE_COUNT = 50; + static const int LINE_COUNT = NUM_ROWS_IN_FRAME_BUFFER; 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; @@ -252,6 +253,10 @@ static void set_palette(rgb_t *pal) } +uint16_t* get_nes_palette() { + return (uint16_t*)myPalette; +} + /* clear all frames to a particular color */ static void clear(uint8 color) { @@ -262,6 +267,8 @@ static bitmap_t *lock_write(void) { // SDL_LockSurface(mySurface); myBitmap = bmp_createhw((uint8*)get_frame_buffer1(), DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_WIDTH*2); + // make sure they don't try to delete the frame buffer lol + myBitmap->hardware = true; return myBitmap; } @@ -282,6 +289,8 @@ static void custom_blit(bitmap_t *bmp, int num_dirties, rect_t *dirty_rects) { } } + + //This runs on core 1. volatile bool exitVideoTaskFlag = false; static void videoTask(void *arg) { @@ -312,7 +321,6 @@ static void videoTask(void *arg) { static void osd_initinput() { - init_input(); } @@ -333,16 +341,6 @@ static void PowerDown() // state printf("PowerDown: Saving state.\n"); SaveState(); - - /* - // LCD - printf("PowerDown: Powerdown LCD panel.\n"); - - printf("PowerDown: Entering deep sleep.\n"); - - // Should never reach here - abort(); - */ } static int ConvertJoystickInput() @@ -378,14 +376,11 @@ extern nes6502_context cpu; void osd_getinput(void) { - const int ev[16]={ + static const int ev[16]={ event_joypad1_select,0,0,event_joypad1_start,event_joypad1_up,event_joypad1_right,event_joypad1_down,event_joypad1_left, 0,0,0,0,event_soft_reset,event_joypad1_a,event_joypad1_b,event_hard_reset }; static int oldb=0xffff; - if (user_quit()) { - nes_poweroff(); - } int b=ConvertJoystickInput(); int chg=b^oldb; int x; diff --git a/components/nofrendo-esp32/CMakeLists.txt b/components/nofrendo-esp32/CMakeLists.txt deleted file mode 100644 index 3b05dcbc..00000000 --- a/components/nofrendo-esp32/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRC_DIRS "." - INCLUDE_DIRS "." - REQUIRES nofrendo box-emu-hal - ) diff --git a/components/nofrendo/CMakeLists.txt b/components/nofrendo/CMakeLists.txt deleted file mode 100644 index a46981d1..00000000 --- a/components/nofrendo/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -idf_component_register( - SRC_DIRS "cpu" "libsnss" "nes" "sndhrdw" "mappers" "." - INCLUDE_DIRS "cpu" "libsnss" "nes" "sndhrdw" "." - REQUIRES box-emu-hal - ) -target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts -Wno-attributes) -target_compile_definitions(${COMPONENT_LIB} PUBLIC USE_NES_NOFRENDO) diff --git a/components/nofrendo/config.c b/components/nofrendo/config.c deleted file mode 100644 index a3c5f3dd..00000000 --- a/components/nofrendo/config.c +++ /dev/null @@ -1,465 +0,0 @@ -/* Nofrendo Configuration Braindead Sample Implementation -** -** $Id: config.c,v 1.2 2001/04/27 14:37:11 neil Exp $ -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -typedef struct myvar_s -{ - struct myvar_s *less, *greater; - char *group, *key, *value; -} myvar_t; - -static myvar_t *myVars = NULL; -static bool mySaveNeeded = false; - - -static void my_destroy(myvar_t **var) -{ - ASSERT(*var); - - if ((*var)->group) - free((*var)->group); - if ((*var)->key) - free((*var)->key); - if ((*var)->value) - free((*var)->value); - free(*var); -} - -static myvar_t *my_create(const char *group, const char *key, const char *value) -{ - myvar_t *var; - - var = _my_malloc(sizeof(*var)); - if (NULL == var) - { - return 0; - } - - var->less = var->greater = NULL; - var->group = var->key = var->value = NULL; - - if ((var->group = _my_malloc(strlen(group) + 1)) - && (var->key = _my_malloc(strlen(key) + 1)) - && (var->value = _my_malloc(strlen(value) + 1))) - { - strcpy(var->group, group); - strcpy(var->key, key); - strcpy(var->value, value); - return var; - } - - my_destroy(&var); - return NULL; -} - -static myvar_t *my_lookup(const char *group, const char *key) -{ - int cmp; - myvar_t *current = myVars; - - while (current - && ((cmp = stricmp(group, current->group)) - || (cmp = stricmp(key, current->key)))) - { - if (cmp < 0) - current = current->less; - else - current = current->greater; - } - - return current; -} - -static void my_insert(myvar_t *var) -{ - int cmp; - myvar_t **current = &myVars; - - while (*current - && ((cmp = stricmp(var->group, (*current)->group)) - || (cmp = stricmp(var->key, (*current)->key)))) - { - current = (cmp < 0) ? &(*current)->less : &(*current)->greater; - } - - if (*current) - { - var->less = (*current)->less; - var->greater = (*current)->greater; - my_destroy(current); - } - else - { - var->less = var->greater = NULL; - } - - *current = var; -} - -static void my_save(FILE *stream, myvar_t *var, char **group) -{ - if (NULL == var) - return; - - my_save(stream, var->less, group); - - if (stricmp(*group, var->group)) - { - fprintf(stream, "\n[%s]\n", var->group); - *group = var->group; - } - - fprintf(stream, "%s=%s\n", var->key, var->value); - - my_save(stream, var->greater, group); -} - -static void my_cleanup(myvar_t *var) -{ - if (NULL == var) - return; - - my_cleanup(var->less); - my_cleanup(var->greater); - my_destroy(&var); -} - -static char *my_getline(FILE *stream) -{ - char buf[1024]; - char *dynamic = NULL; - - do - { - if (NULL == (fgets(buf, sizeof(buf), stream))) - { - if (dynamic) - free(dynamic); - return 0; - } - - if (NULL == dynamic) - { - dynamic = _my_malloc(strlen(buf) + 1); - if (NULL == dynamic) - { - return 0; - } - strcpy(dynamic, buf); - } - else - { - /* a mini-version of realloc that works with our memory manager */ - char *temp = NULL; - temp = _my_malloc(strlen(dynamic) + strlen(buf) + 1); - if (NULL == temp) - return 0; - - strcpy(temp, dynamic); - free(dynamic); - dynamic = temp; - - strcat(dynamic, buf); - } - - if (feof(stream)) - { - return dynamic; - } - } - while (dynamic[strlen(dynamic) - 1] != '\n'); - - return dynamic; -} - -/* load_config loads from the disk the saved configuration. */ -static int load_config(char *filename) -{ - FILE *config_file; - - if ((config_file = fopen(filename, "r"))) - { - char *line; - char *group = NULL, *key = NULL, *value = NULL; - - mySaveNeeded = true; - while ((line = my_getline(config_file))) - { - char *s; - - if ('\n' == line[strlen(line) - 1]) - line[strlen(line) - 1] = '\0'; - - s = line; - - do - { - /* eat up whitespace */ - while (isspace(*s)) - s++; - - switch (*s) - { - case ';': - case '#': - case '\0': - *s = '\0'; - break; - - case '[': - if (group) - free(group); - - group = ++s; - - s = strchr(s, ']'); - if (NULL == s) - { - log_printf("load_config: missing ']' after group\n"); - s = group + strlen(group); - } - else - { - *s++ = '\0'; - } - - if ((value = _my_malloc(strlen(group) + 1))) - { - strcpy(value, group); - } - group = value; - break; - - default: - key = s; - s = strchr(s, '='); - if (NULL == s) - { - log_printf("load_config: missing '=' after key\n"); - s = key + strlen(key); - } - else - { - *s++ = '\0'; - } - - while (strlen(key) && isspace(key[strlen(key) - 1])) - key[strlen(key) - 1] = '\0'; - - while (isspace(*s)) - s++; - - while (strlen(s) && isspace(s[strlen(s) - 1])) - s[strlen(s) - 1]='\0'; - - { - myvar_t *var = my_create(group ? group : "", key, s); - if (NULL == var) - { - log_printf("load_config: my_create failed\n"); - return -1; - } - - my_insert(var); - } - s += strlen(s); - } - } while (*s); - - free(line); - } - - if (group) - free(group); - - fclose(config_file); - } - - return 0; -} - -/* save_config saves the current configuration to disk.*/ -static int save_config(char *filename) -{ - FILE *config_file; - char *group = ""; - - config_file = fopen(filename, "w"); - if (NULL == config_file) - { - log_printf("save_config failed\n"); - return -1; - } - - fprintf(config_file, ";; " APP_STRING " " APP_VERSION "\n"); - fprintf(config_file, ";; NOTE: comments are not preserved.\n"); - my_save(config_file, myVars, &group); - fclose(config_file); - - return 0; -} - -static bool open_config(void) -{ - return load_config(config.filename); -} - -static void close_config(void) -{ - if (true == mySaveNeeded) - { - save_config(config.filename); - } - - my_cleanup(myVars); -} - -static void write_int(const char *group, const char *key, int value) -{ - char buf[24]; - static myvar_t *var; - - sprintf(buf, "%d", value); - buf[sizeof(buf) - 1] = '\0'; - - var = my_create(group, key, buf); - if (NULL == var) - { - log_printf("write_int failed\n"); - return; - } - - my_insert(var); - mySaveNeeded = true; -} - -/* read_int loads an integer from the configuration into "value" -** -** If the specified "key" does not exist, the "def"ault is returned -*/ -static int read_int(const char *group, const char *key, int def) -{ - static myvar_t *var; - - var = my_lookup(group, key); - if (NULL == var) - { - write_int(group, key, def); - - return def; - } - - return strtoul(var->value, 0, 0); -} - -static void write_string(const char *group, const char *key, const char *value) -{ - static myvar_t *var; - - var = my_create(group, key, value); - if (NULL == var) - { - log_printf("write_string failed\n"); - return; - } - - my_insert(var); - mySaveNeeded = true; -} - -/* read_string copies a string from the configuration into "value" -** -** If the specified "key" does not exist, the "def"ault is returned -*/ -static const char *read_string(const char *group, const char *key, const char *def) -{ - static myvar_t *var; - - var = my_lookup(group, key); - if (NULL == var) - { - if (def != NULL) - write_string(group, key, def); - - return def; - } - - return var->value; -} - -/* interface */ -config_t config = -{ - open_config, - close_config, - read_int, - read_string, - write_int, - write_string, - CONFIG_FILE -}; - -/* -** $Log: config.c,v $ -** Revision 1.2 2001/04/27 14:37:11 neil -** wheeee -** -** Revision 1.1.1.1 2001/04/27 07:03:54 neil -** initial -** -** Revision 1.14 2000/11/05 06:23:10 matt -** realloc was incompatible with memguard -** -** Revision 1.13 2000/10/10 13:58:13 matt -** stroustrup squeezing his way in the door -** -** Revision 1.12 2000/09/20 01:13:28 matt -** damn tabs -** -** Revision 1.11 2000/08/04 12:41:04 neil -** current not a bug -** -** Revision 1.10 2000/07/31 04:28:46 matt -** one million cleanups -** -** Revision 1.9 2000/07/24 04:30:42 matt -** slight cleanup -** -** Revision 1.8 2000/07/23 15:16:08 matt -** changed strcasecmp to stricmp -** -** Revision 1.7 2000/07/19 15:58:55 neil -** config file now configurable (ha) -** -** Revision 1.6 2000/07/18 03:28:32 matt -** help me! I'm a complete mess! -** -** Revision 1.5 2000/07/12 11:03:08 neil -** Always write a config, even if no defaults are changed -** -** Revision 1.4 2000/07/11 15:09:30 matt -** suppressed all warnings -** -** Revision 1.3 2000/07/11 14:59:27 matt -** minor cosmetics.. =) -** -** Revision 1.2 2000/07/11 13:35:38 bsittler -** Changed the config API, implemented config file "nofrendo.cfg". The -** GGI drivers use the group [GGI]. Visual= and Mode= keys are understood. -** -** Revision 1.1 2000/07/11 09:21:10 bsittler -** This is a skeletal configuration system. -** -*/ diff --git a/components/nofrendo/gui.c b/components/nofrendo/gui.c deleted file mode 100644 index e553a799..00000000 --- a/components/nofrendo/gui.c +++ /dev/null @@ -1,697 +0,0 @@ -/* -** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) -** -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of version 2 of the GNU Library General -** Public License as published by the Free Software Foundation. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Library General Public License for more details. To obtain a -** copy of the GNU Library General Public License, write to the Free -** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Any permitted reproduction of these routines, in whole or in part, -** must bear this legend. -** -** -** gui.c -** -** GUI routines -** $Id: gui.c,v 1.2 2001/04/27 14:37:11 neil Exp $ -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -/* TODO: oh god */ -/* 8-bit GUI color table */ -rgb_t gui_pal[GUI_TOTALCOLORS] = -{ - { 0x00, 0x00, 0x00 }, /* black */ - { 0x3F, 0x3F, 0x3F }, /* dark gray */ - { 0x7F, 0x7F, 0x7F }, /* gray */ - { 0xBF, 0xBF, 0xBF }, /* light gray */ - { 0xFF, 0xFF, 0xFF }, /* white */ - { 0xFF, 0x00, 0x00 }, /* red */ - { 0x00, 0xFF, 0x00 }, /* green */ - { 0x00, 0x00, 0xFF }, /* blue */ - { 0xFF, 0xFF, 0x00 }, /* yellow */ - { 0xFF, 0xAF, 0x00 }, /* orange */ - { 0xFF, 0x00, 0xFF }, /* purple */ - { 0x3F, 0x7F, 0x7F }, /* teal */ - { 0x00, 0x2A, 0x00 }, /* dk. green */ - { 0x00, 0x00, 0x3F } /* dark blue */ -}; - -/**************************************************************/ -#include -#include -static bool option_drawsprites = true; - -/* save a PCX snapshot */ -void gui_savesnap(void) -{ - char filename[PATH_MAX]; - nes_t *nes = nes_getcontextptr(); - - if (osd_makesnapname(filename, PATH_MAX) < 0) - return; - - if (pcx_write(filename, nes->vidbuf, nes->ppu->curpal)) - return; - - gui_sendmsg(GUI_GREEN, "Screen saved to %s", filename); -} - -/* Show/hide sprites (hiding sprites useful for making maps) */ -void gui_togglesprites(void) -{ - option_drawsprites ^= true; - ppu_displaysprites(option_drawsprites); - gui_sendmsg(GUI_GREEN, "Sprites %s", option_drawsprites ? "displayed" : "hidden"); -} - -/* Set the frameskip policy */ -void gui_togglefs(void) -{ - nes_t *machine = nes_getcontextptr(); - - machine->autoframeskip ^= true; - if (machine->autoframeskip) - gui_sendmsg(GUI_YELLOW, "automatic frameskip"); - else - gui_sendmsg(GUI_YELLOW, "unthrottled emulation"); -} - -/* display rom information */ -void gui_displayinfo() -{ - gui_sendmsg(GUI_ORANGE, (char *) rom_getinfo(nes_getcontextptr()->rominfo)); -} - -void gui_toggle_chan(int chan) -{ -#define FILL_CHAR 0x7C /* ASCII 124 '|' */ -#define BLANK_CHAR 0x7F /* ASCII 127 [delta] */ - static bool chan_enabled[6] = { true, true, true, true, true, true }; - - chan_enabled[chan] ^= true; - apu_setchan(chan, chan_enabled[chan]); - - gui_sendmsg(GUI_ORANGE, "%ca %cb %cc %cd %ce %cext", - chan_enabled[0] ? FILL_CHAR : BLANK_CHAR, - chan_enabled[1] ? FILL_CHAR : BLANK_CHAR, - chan_enabled[2] ? FILL_CHAR : BLANK_CHAR, - chan_enabled[3] ? FILL_CHAR : BLANK_CHAR, - chan_enabled[4] ? FILL_CHAR : BLANK_CHAR, - chan_enabled[5] ? FILL_CHAR : BLANK_CHAR); -} - -void gui_setfilter(int filter_type) -{ - char *types[3] = { "no", "lowpass", "weighted" }; - static int last_filter = 2; - - if (last_filter == filter_type || filter_type < 0 || filter_type > 2) - return; - - apu_setfilter(filter_type); - gui_sendmsg(GUI_ORANGE, "%s filter", types[filter_type]); - last_filter = filter_type; -} -/**************************************************************/ - - -enum -{ - GUI_WAVENONE, - GUI_WAVELINE, - GUI_WAVESOLID, - GUI_NUMWAVESTYLES -}; - -enum -{ - BUTTON_UP, - BUTTON_DOWN -}; - - -/* TODO: roll options into a structure */ -static message_t msg; -static bool option_showfps = false; -static bool option_showgui = false; -static int option_wavetype = GUI_WAVENONE; -static bool option_showpattern = false; -static bool option_showoam = false; -static int pattern_col = 0; - -/* timimg variables */ -static bool gui_fpsupdate = false; -static int gui_ticks = 0; -static int gui_fps = 0; -static int gui_refresh = 60; /* default to 60Hz */ - -static int mouse_x, mouse_y, mouse_button; - -static bitmap_t *gui_surface; - - -/* Put a pixel on our bitmap- just for GUI use */ -INLINE void gui_putpixel(int x_pos, int y_pos, uint8 color) -{ - gui_surface->line[y_pos][x_pos] = color; -} - -/* Line drawing */ -static void gui_hline(int x_pos, int y_pos, int length, uint8 color) -{ - while (length--) - gui_putpixel(x_pos++, y_pos, color); -} - -static void gui_vline(int x_pos, int y_pos, int height, uint8 color) -{ - while (height--) - gui_putpixel(x_pos, y_pos++, color); -} - -/* Rectangles */ -static void gui_rect(int x_pos, int y_pos, int width, int height, uint8 color) -{ - gui_hline(x_pos, y_pos, width, color); - gui_hline(x_pos, y_pos + height - 1, width, color); - gui_vline(x_pos, y_pos + 1, height - 2, color); - gui_vline(x_pos + width - 1, y_pos + 1, height - 2, color); -} - -static void gui_rectfill(int x_pos, int y_pos, int width, int height, uint8 color) -{ - while (height--) - gui_hline(x_pos, y_pos++, width, color); -} - -/* Draw the outline of a button */ -static void gui_buttonrect(int x_pos, int y_pos, int width, int height, bool down) -{ - uint8 color1, color2; - - if (down) - { - color1 = GUI_GRAY; - color2 = GUI_WHITE; - } - else - { - color1 = GUI_WHITE; - color2 = GUI_GRAY; - } - - gui_hline(x_pos, y_pos, width - 1, color1); - gui_vline(x_pos, y_pos + 1, height - 2, color1); - gui_hline(x_pos, y_pos + height - 1, width, color2); - gui_vline(x_pos + width - 1, y_pos, height - 1, color2); -} - -/* Text blitting */ -INLINE void gui_charline(char ch, int x_pos, int y_pos, uint8 color) -{ - int count = 8; - while (count--) - { - if (ch & (1 << count)) - gui_putpixel(x_pos, y_pos, color); - x_pos++; - } -} - -static void gui_putchar(const uint8 *dat, int height, int x_pos, int y_pos, uint8 color) -{ - while (height--) - gui_charline(*dat++, x_pos, y_pos++, color); -} - -/* Return length of text in pixels */ -static int gui_textlen(char *str, font_t *font) -{ - int pixels = 0; - int num_chars = strlen(str); - - while (num_chars--) - pixels += font->character[(*str++ - 32)].spacing; - - return pixels; -} - -/* Simple textout() type function */ -static int gui_textout(char *str, int x_pos, int y_pos, font_t *font, uint8 color) -{ - int x_new; - int num_chars = strlen(str); - int code; - - x_new = x_pos; - - while (num_chars--) - { - /* Turn ASCII code into letter */ - code = *str++; - if (code > 0x7F) - code = 0x7F; - code -= 32; /* normalize */ - gui_putchar(font->character[code].lines, font->height, x_new, y_pos, color); - x_new += font->character[code].spacing; - } - - /* Return the length in pixels */ - return (x_new - x_pos); -} - -/* Draw bar-/button-type text */ -static int gui_textbar(char *str, int x_pos, int y_pos, font_t *font, - uint8 color, uint8 bgcolor, bool buttonstate) -{ - int width = gui_textlen(str, &small); - - /* Fill the 'button' */ - gui_buttonrect(x_pos, y_pos, width + 3, font->height + 3, buttonstate); - gui_rectfill(x_pos + 1, y_pos + 1, width + 1, font->height + 1, bgcolor); - - /* Print the text */ - return gui_textout(str, x_pos + 2, y_pos + 2, font, color); -} - -/* Draw the mouse pointer */ -static void gui_drawmouse(void) -{ - int ythresh, xthresh; - int i, j, color; - - ythresh = gui_surface->height - mouse_y - 1; - for (j = 0; j < CURSOR_HEIGHT; j++) - { - if (ythresh < 0) - continue; - - xthresh = gui_surface->width - mouse_x - 1; - for (i = 0; i < CURSOR_WIDTH; i++) - { - if (xthresh < 0) - continue; - - color = cursor[(j * CURSOR_WIDTH) + i]; - - if (color) - gui_putpixel(mouse_x + i, mouse_y + j, cursor_color[color]); - xthresh--; - } - ythresh--; - } -} - -void gui_tick(int ticks) -{ - - static int fps_counter = 0; - - gui_ticks += ticks; - fps_counter += ticks; - - if (fps_counter >= gui_refresh) - { - fps_counter -= gui_refresh; - gui_fpsupdate = true; - } -} - -/* updated in sync with the timer interrupt */ -static void gui_tickdec(void) -{ -#ifdef NOFRENDO_DEBUG - static int hertz_ticks = 0; -#endif - int ticks = gui_ticks; - - if (0 == ticks) - return; - - gui_ticks = 0; - -#ifdef NOFRENDO_DEBUG - /* Check for corrupt memory block every 10 seconds */ - hertz_ticks += ticks; - if (hertz_ticks >= (10 * gui_refresh)) - { - hertz_ticks -= (10 * gui_refresh); - mem_checkblocks(); - } -#endif - - /* TODO: bleh */ - if (msg.ttl > 0) - { - msg.ttl -= ticks; - if (msg.ttl < 0) - msg.ttl = 0; - } -} - -/* Update the FPS display */ -static void gui_updatefps(void) -{ - static char fpsbuf[20]; - - /* Check to see if we need to do an sprintf or not */ - if (true == gui_fpsupdate) - { - sprintf(fpsbuf, "%4d FPS /%4d%%", gui_fps, (gui_fps * 100) / gui_refresh); - gui_fps = 0; - gui_fpsupdate = false; - } - - gui_textout(fpsbuf, gui_surface->width - 1 - 90, 1, &small, GUI_GREEN); -} - -/* Turn FPS on/off */ -void gui_togglefps(void) -{ - option_showfps ^= true; -} - -/* Turn GUI on/off */ -void gui_togglegui(void) -{ - option_showgui ^= true; -} - -void gui_togglewave(void) -{ - option_wavetype = (option_wavetype + 1) % GUI_NUMWAVESTYLES; -} - -void gui_toggleoam(void) -{ - option_showoam ^= true; -} - -/* TODO: hack! */ -void gui_togglepattern(void) -{ - option_showpattern ^= true; -} - -/* TODO: hack! */ -void gui_decpatterncol(void) -{ - if (pattern_col && option_showpattern) - pattern_col--; -} - -/* TODO: hack! */ -void gui_incpatterncol(void) -{ - if ((pattern_col < 7) && option_showpattern) - pattern_col++; -} - -/* Downward-scrolling message display */ -static void gui_updatemsg(void) -{ - if (msg.ttl) - gui_textbar(msg.text, 2, gui_surface->height - 10, &small, msg.color, GUI_DKGRAY, BUTTON_UP); -} - -/* Little thing to display the waveform */ -static void gui_updatewave(int wave_type) -{ -#define WAVEDISP_WIDTH 128 - int loop, xofs, yofs; - int difference, offset; - float scale; - uint8 val, oldval; - int vis_length = 0; - void *vis_buffer = NULL; - int vis_bps; - apu_t apu; - - apu_getcontext(&apu); - vis_buffer = apu.buffer; - vis_length = apu.num_samples; - vis_bps = apu.sample_bits; - - xofs = (NES_SCREEN_WIDTH - WAVEDISP_WIDTH); - yofs = 1; - scale = (float) (vis_length / (float) WAVEDISP_WIDTH); - - if (NULL == vis_buffer) - { - /* draw centerline */ - gui_hline(xofs, yofs + 0x20, WAVEDISP_WIDTH, GUI_GRAY); - gui_textbar("no sound", xofs + 40, yofs + 0x20 - 4, &small, GUI_RED, GUI_DKGRAY, BUTTON_UP); - - } - else if (GUI_WAVELINE == wave_type) - { - /* draw centerline */ - gui_hline(xofs, yofs + 0x20, WAVEDISP_WIDTH, GUI_GRAY); - - /* initial old value */ - if (16 == vis_bps) - oldval = 0x40 - (((((uint16 *) vis_buffer)[0] >> 8) ^ 0x80) >> 2); - else - oldval = 0x40 - (((uint8 *) vis_buffer)[0] >> 2); - - for (loop = 1; loop < WAVEDISP_WIDTH; loop++) - { - //val = 0x40 - (vis_buffer[(uint32) (loop * scale)] >> 2); - if (16 == vis_bps) - val = 0x40 - (((((uint16 *) vis_buffer)[(uint32) (loop * scale)] >> 8) ^ 0x80) >> 2); - else - val = 0x40 - (((uint8 *) vis_buffer)[(uint32) (loop * scale)] >> 2); - if (oldval < val) - { - offset = oldval; - difference = (val - oldval) + 1; - } - else - { - offset = val; - difference = (oldval - val) + 1; - } - - gui_vline(xofs + loop, yofs + offset, difference, GUI_GREEN); - oldval = val; - } - } - /* solid wave */ - else if (GUI_WAVESOLID == wave_type) - { - for (loop = 0; loop < WAVEDISP_WIDTH; loop++) - { - //val = vis_buffer[(uint32) (loop * scale)] >> 2; - if (16 == vis_bps) - val = ((((uint16 *) vis_buffer)[(uint32) (loop * scale)] >> 8) ^ 0x80) >> 2; - else - val = ((uint8 *) vis_buffer)[(uint32) (loop * scale)] >> 2; - if (val == 0x20) - gui_putpixel(xofs + loop, yofs + 0x20, GUI_GREEN); - else if (val < 0x20) - gui_vline(xofs + loop, yofs + 0x20, 0x20 - val, GUI_GREEN); - else - gui_vline(xofs + loop, yofs + 0x20 - (val - 0x20), val - 0x20, - GUI_GREEN); - } - } - - gui_rect(xofs, yofs - 1, WAVEDISP_WIDTH, 66, GUI_DKGRAY); -} - - -static void gui_updatepattern(void) -{ - /* Pretty it up a bit */ - gui_textbar("Pattern Table 0", 0, 0, &small, GUI_GREEN, GUI_DKGRAY, BUTTON_UP); - gui_textbar("Pattern Table 1", 128, 0, &small, GUI_GREEN, GUI_DKGRAY, BUTTON_UP); - gui_hline(0, 9, 256, GUI_DKGRAY); - gui_hline(0, 138, 256, GUI_DKGRAY); - - /* Dump the actual tables */ - ppu_dumppattern(gui_surface, 0, 0, 10, pattern_col); - ppu_dumppattern(gui_surface, 1, 128, 10, pattern_col); -} - -static void gui_updateoam(void) -{ - int y; - - y = option_showpattern ? 140 : 0; - gui_textbar("Current OAM", 0, y, &small, GUI_GREEN, GUI_DKGRAY, BUTTON_UP); - ppu_dumpoam(gui_surface, 0, y + 9); -} - - -/* The GUI overlay */ -void gui_frame(bool draw) -{ - gui_fps++; - if (false == draw) - return; - - gui_surface = vid_getbuffer(); - - ASSERT(gui_surface); - - gui_tickdec(); - - if (option_showfps) - gui_updatefps(); - - if (option_wavetype != GUI_WAVENONE) - gui_updatewave(option_wavetype); - - if (option_showpattern) - gui_updatepattern(); - - if (option_showoam) - gui_updateoam(); - - if (msg.ttl) - gui_updatemsg(); - - if (option_showgui) - { - osd_getmouse(&mouse_x, &mouse_y, &mouse_button); - gui_drawmouse(); - } -} - -void gui_sendmsg(int color, char *format, ...) -{ - va_list arg; - va_start(arg, format); - vsprintf(msg.text, format, arg); - -#ifdef NOFRENDO_DEBUG - log_print("GUI: "); - log_print(msg.text); - log_print("\n"); -#endif - - va_end(arg); - - msg.ttl = gui_refresh * 2; /* 2 second delay */ - msg.color = color; -} - -void gui_setrefresh(int frequency) -{ - gui_refresh = frequency; -} - -int gui_init(void) -{ - gui_refresh = 60; - memset(&msg, 0, sizeof(message_t)); - - return 0; /* can't fail */ -} - -void gui_shutdown(void) -{ -} - -/* -** $Log: gui.c,v $ -** Revision 1.2 2001/04/27 14:37:11 neil -** wheeee -** -** Revision 1.1.1.1 2001/04/27 07:03:54 neil -** initial -** -** Revision 1.26 2000/11/25 20:26:05 matt -** removed fds "system" -** -** Revision 1.25 2000/11/09 14:05:43 matt -** state load fixed, state save mostly fixed -** -** Revision 1.24 2000/11/05 16:37:18 matt -** rolled rgb.h into bitmap.h -** -** Revision 1.23 2000/10/27 12:57:49 matt -** fixed pcx snapshots -** -** Revision 1.22 2000/10/25 00:23:16 matt -** makefiles updated for new directory structure -** -** Revision 1.21 2000/10/23 17:50:47 matt -** adding fds support -** -** Revision 1.20 2000/10/23 15:52:04 matt -** better system handling -** -** Revision 1.19 2000/10/22 19:15:39 matt -** more sane timer ISR / autoframeskip -** -** Revision 1.18 2000/10/17 03:22:37 matt -** cleaning up rom module -** -** Revision 1.17 2000/10/10 13:58:13 matt -** stroustrup squeezing his way in the door -** -** Revision 1.16 2000/10/10 13:03:53 matt -** Mr. Clean makes a guest appearance -** -** Revision 1.15 2000/10/08 17:59:12 matt -** gui_ticks is volatile -** -** Revision 1.14 2000/09/15 04:58:06 matt -** simplifying and optimizing APU core -** -** Revision 1.13 2000/07/31 04:28:46 matt -** one million cleanups -** -** Revision 1.12 2000/07/30 04:29:59 matt -** no more apu_getpcmdata hack -** -** Revision 1.11 2000/07/25 02:20:47 matt -** moved gui palette filth here, for the time being -** -** Revision 1.10 2000/07/24 04:32:05 matt -** bugfix on message delay -** -** Revision 1.9 2000/07/23 15:16:25 matt -** moved non-osd code here -** -** Revision 1.8 2000/07/17 01:52:27 matt -** made sure last line of all source files is a newline -** -** Revision 1.7 2000/07/11 04:40:23 matt -** updated for new screen dimension defines -** -** Revision 1.6 2000/07/09 03:39:33 matt -** small gui_frame cleanup -** -** Revision 1.5 2000/07/06 16:47:18 matt -** new video driver interface -** -** Revision 1.4 2000/06/09 15:12:25 matt -** initial revision -** -*/ diff --git a/components/nofrendo/gui.h b/components/nofrendo/gui.h deleted file mode 100644 index 4875e773..00000000 --- a/components/nofrendo/gui.h +++ /dev/null @@ -1,146 +0,0 @@ -/* -** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) -** -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of version 2 of the GNU Library General -** Public License as published by the Free Software Foundation. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Library General Public License for more details. To obtain a -** copy of the GNU Library General Public License, write to the Free -** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Any permitted reproduction of these routines, in whole or in part, -** must bear this legend. -** -** -** gui.h -** -** GUI defines / prototypes -** $Id: gui.h,v 1.2 2001/04/27 14:37:11 neil Exp $ -*/ - -#ifndef _GUI_H_ -#define _GUI_H_ - -/* GUI colors - the last 64 of a 256-color palette */ - -#define GUI_FIRSTENTRY 192 - -enum -{ - GUI_BLACK = GUI_FIRSTENTRY, - GUI_DKGRAY, - GUI_GRAY, - GUI_LTGRAY, - GUI_WHITE, - GUI_RED, - GUI_GREEN, - GUI_BLUE, - GUI_YELLOW, - GUI_ORANGE, - GUI_PURPLE, - GUI_TEAL, - GUI_DKGREEN, - GUI_DKBLUE, - GUI_LASTENTRY -}; - -#define GUI_TOTALCOLORS (GUI_LASTENTRY - GUI_FIRSTENTRY) - -/* TODO: bleh */ -#include -extern rgb_t gui_pal[GUI_TOTALCOLORS]; - -#define MAX_MSG_LENGTH 256 - -typedef struct message_s -{ - int ttl; - char text[MAX_MSG_LENGTH]; - uint8 color; -} message_t; - -extern void gui_tick(int ticks); -extern void gui_setrefresh(int frequency); - -extern void gui_sendmsg(int color, char *format, ...); - -extern int gui_init(void); -extern void gui_shutdown(void); - -extern void gui_frame(bool draw); - -extern void gui_togglefps(void); -extern void gui_togglegui(void); -extern void gui_togglewave(void); -extern void gui_togglepattern(void); -extern void gui_toggleoam(void); - -extern void gui_decpatterncol(void); -extern void gui_incpatterncol(void); - -extern void gui_savesnap(void); -extern void gui_togglesprites(void); -extern void gui_togglefs(void); -extern void gui_displayinfo(); -extern void gui_toggle_chan(int chan); -extern void gui_setfilter(int filter_type); - - -#endif /* _GUI_H_ */ - -/* -** $Log: gui.h,v $ -** Revision 1.2 2001/04/27 14:37:11 neil -** wheeee -** -** Revision 1.1.1.1 2001/04/27 07:03:54 neil -** initial -** -** Revision 1.17 2000/11/05 16:37:18 matt -** rolled rgb.h into bitmap.h -** -** Revision 1.16 2000/10/27 12:57:49 matt -** fixed pcx snapshots -** -** Revision 1.15 2000/10/23 17:50:47 matt -** adding fds support -** -** Revision 1.14 2000/10/23 15:52:04 matt -** better system handling -** -** Revision 1.13 2000/10/22 19:15:39 matt -** more sane timer ISR / autoframeskip -** -** Revision 1.12 2000/10/10 13:58:13 matt -** stroustrup squeezing his way in the door -** -** Revision 1.11 2000/10/10 13:03:53 matt -** Mr. Clean makes a guest appearance -** -** Revision 1.10 2000/10/08 17:59:12 matt -** gui_ticks is volatile -** -** Revision 1.9 2000/07/31 04:28:46 matt -** one million cleanups -** -** Revision 1.8 2000/07/25 02:20:47 matt -** moved gui palette filth here, for the time being -** -** Revision 1.7 2000/07/23 15:16:25 matt -** moved non-osd code here -** -** Revision 1.6 2000/07/17 01:52:27 matt -** made sure last line of all source files is a newline -** -** Revision 1.5 2000/07/09 03:39:33 matt -** small gui_frame cleanup -** -** Revision 1.4 2000/06/09 15:12:25 matt -** initial revision -** -*/ diff --git a/components/nofrendo/gui_elem.c b/components/nofrendo/gui_elem.c deleted file mode 100644 index 5592b6c8..00000000 --- a/components/nofrendo/gui_elem.c +++ /dev/null @@ -1,200 +0,0 @@ -/* -** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) -** -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of version 2 of the GNU Library General -** Public License as published by the Free Software Foundation. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Library General Public License for more details. To obtain a -** copy of the GNU Library General Public License, write to the Free -** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Any permitted reproduction of these routines, in whole or in part, -** must bear this legend. -** -** -** gui_elem.c -** -** GUI elements (font, mouse pointer, etc.) -** $Id: gui_elem.c,v 1.2 2001/04/27 14:37:11 neil Exp $ -*/ - -#include -#include -#include -#include - -#define SMALL_FONT_KERN 6 -#define SMALL_FONT_HEIGHT 6 - -static const fontchar_t small_data[] = -{ - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, SMALL_FONT_KERN }, /* space */ - { { 0x20, 0x20, 0x20, 0x00, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x50, 0x50, 0x00, 0x00, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x00 }, SMALL_FONT_KERN }, - { { 0x20, 0x78, 0x20, 0xF0, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0xC8, 0xD0, 0x20, 0x58, 0x98, 0x00 }, SMALL_FONT_KERN }, - { { 0x40, 0xA0, 0x58, 0x90, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0x20, 0x40, 0x00, 0x00, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x20, 0x40, 0x40, 0x40, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x20, 0x10, 0x10, 0x10, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x50, 0x20, 0x50, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x20, 0x70, 0x20, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x00, 0x00, 0x20, 0x40, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x00, 0x70, 0x00, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x08, 0x10, 0x20, 0x40, 0x80, 0x00 }, SMALL_FONT_KERN }, - - /* 0-9 */ - { { 0x70, 0x98, 0xA8, 0xC8, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x60, 0x20, 0x20, 0x20, 0xF8, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x08, 0x70, 0x80, 0xF8, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x88, 0x30, 0x88, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x30, 0x50, 0x90, 0xF8, 0x10, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x80, 0x70, 0x08, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x80, 0xF0, 0x88, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x08, 0x10, 0x20, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x88, 0x70, 0x88, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x88, 0x78, 0x08, 0x70, 0x00 }, SMALL_FONT_KERN }, - - { { 0x00, 0x20, 0x00, 0x20, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x20, 0x00, 0x20, 0x40, 0x00 }, SMALL_FONT_KERN }, - { { 0x10, 0x20, 0x40, 0x20, 0x10, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x70, 0x00, 0x70, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x40, 0x20, 0x10, 0x20, 0x40, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x88, 0x30, 0x00, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x88, 0xA8, 0xB0, 0x78, 0x00 }, SMALL_FONT_KERN }, - - /* A-Z */ - { { 0x70, 0x88, 0xF8, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0xF0, 0x88, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0x80, 0x80, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0x88, 0x88, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x80, 0xF8, 0x80, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0xF8, 0x80, 0x80, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0xB8, 0x88, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x20, 0x20, 0x20, 0xF8, 0x00 }, SMALL_FONT_KERN }, - { { 0x08, 0x08, 0x08, 0x88, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x90, 0xE0, 0x90, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0x80, 0x80, 0x80, 0x80, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0x88, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0x88, 0x88, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0xF0, 0x80, 0x80, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x88, 0x88, 0x90, 0x68, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0xF0, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x20, 0x20, 0x20, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0x88, 0x88, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0x88, 0x50, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0xA8, 0xA8, 0xA8, 0xA8, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x50, 0x20, 0x50, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0x70, 0x20, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x08, 0x70, 0x80, 0xF8, 0x00 }, SMALL_FONT_KERN }, - - { { 0x70, 0x40, 0x40, 0x40, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x80, 0x40, 0x20, 0x10, 0x08, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x10, 0x10, 0x10, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x20, 0x50, 0x00, 0x00, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0x00, 0x00, 0x00, 0x00, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x20, 0x10, 0x00, 0x00, 0x00, 0x00 }, SMALL_FONT_KERN }, - - /* A-Z */ - { { 0x70, 0x88, 0xF8, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0xF0, 0x88, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0x80, 0x80, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0x88, 0x88, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x80, 0xF8, 0x80, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0xF8, 0x80, 0x80, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0xB8, 0x88, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x20, 0x20, 0x20, 0xF8, 0x00 }, SMALL_FONT_KERN }, - { { 0x08, 0x08, 0x08, 0x88, 0x70, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x90, 0xE0, 0x90, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0x80, 0x80, 0x80, 0x80, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0x88, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0x88, 0x88, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0xF0, 0x80, 0x80, 0x00 }, SMALL_FONT_KERN }, - { { 0x70, 0x88, 0x88, 0x90, 0x68, 0x00 }, SMALL_FONT_KERN }, - { { 0xF0, 0x88, 0xF0, 0x88, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x20, 0x20, 0x20, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0x88, 0x88, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0x88, 0x50, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0xA8, 0xA8, 0xA8, 0xA8, 0x78, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x50, 0x20, 0x50, 0x88, 0x00 }, SMALL_FONT_KERN }, - { { 0x88, 0x88, 0x70, 0x20, 0x20, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x08, 0x70, 0x80, 0xF8, 0x00 }, SMALL_FONT_KERN }, - - { { 0x10, 0x20, 0x20, 0x20, 0x10, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00 }, SMALL_FONT_KERN }, - { { 0x40, 0x20, 0x20, 0x20, 0x40, 0x00 }, SMALL_FONT_KERN }, - { { 0x50, 0xA0, 0x00, 0x00, 0x00, 0x00 }, SMALL_FONT_KERN }, - { { 0xF8, 0x88, 0x88, 0x88, 0xF8, 0x00 }, SMALL_FONT_KERN }, -}; - -font_t small = { small_data, SMALL_FONT_HEIGHT }; - -const uint8 cursor_color[] = -{ - 0, - GUI_BLACK, - GUI_WHITE, - GUI_LTGRAY, - GUI_GRAY -}; - -const uint8 cursor[] = -{ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, - 4, 2, 3, 3, 1, 0, 0, 0, 0, 0, 0, - 4, 2, 3, 3, 3, 1, 0, 0, 0, 0, 0, - 4, 2, 2, 3, 3, 3, 1, 0, 0, 0, 0, - 4, 2, 2, 3, 3, 3, 3, 1, 0, 0, 0, - 4, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0, - 4, 2, 2, 2, 3, 3, 3, 3, 3, 1, 0, - 4, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, - 4, 2, 3, 1, 2, 2, 1, 0, 0, 0, 0, - 4, 3, 1, 0, 4, 2, 3, 1, 0, 0, 0, - 4, 1, 0, 0, 4, 2, 3, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 4, 2, 3, 1, 0, 0, - 0, 0, 0, 0, 0, 4, 2, 3, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 2, 3, 1, 0, - 0, 0, 0, 0, 0, 0, 4, 3, 3, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, -}; - -/* -** $Log: gui_elem.c,v $ -** Revision 1.2 2001/04/27 14:37:11 neil -** wheeee -** -** Revision 1.1.1.1 2001/04/27 07:03:54 neil -** initial -** -** Revision 1.8 2000/10/10 13:03:54 matt -** Mr. Clean makes a guest appearance -** -** Revision 1.7 2000/07/31 04:28:46 matt -** one million cleanups -** -** Revision 1.6 2000/07/17 04:21:18 neil -** warning: initialization makes integer from pointer without a cast -** -** Revision 1.5 2000/07/17 01:52:27 matt -** made sure last line of all source files is a newline -** -** Revision 1.4 2000/06/09 15:12:25 matt -** initial revision -** -*/ diff --git a/components/nofrendo/gui_elem.h b/components/nofrendo/gui_elem.h deleted file mode 100644 index 6841aa2d..00000000 --- a/components/nofrendo/gui_elem.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) -** -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of version 2 of the GNU Library General -** Public License as published by the Free Software Foundation. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Library General Public License for more details. To obtain a -** copy of the GNU Library General Public License, write to the Free -** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Any permitted reproduction of these routines, in whole or in part, -** must bear this legend. -** -** -** gui_elem.h -** -** GUI elements (font, mouse pointer, etc.) -** $Id: gui_elem.h,v 1.1.1.1 2001/04/27 07:03:54 neil Exp $ -*/ - -#ifndef _GUI_ELEM_H_ -#define _GUI_ELEM_H_ - -typedef struct fontchar_s -{ - uint8 lines[6]; - uint8 spacing; -} fontchar_t; - -typedef struct font_s -{ - const fontchar_t *character; - uint8 height; -} font_t; - -extern font_t small; - -#define CURSOR_WIDTH 11 -#define CURSOR_HEIGHT 19 - -extern const uint8 cursor_color[]; -extern const uint8 cursor[]; - -#endif /* _GUI_ELEM_H_ */ - -/* -** $Log: gui_elem.h,v $ -** Revision 1.1.1.1 2001/04/27 07:03:54 neil -** initial -** -** Revision 1.7 2000/10/10 13:03:54 matt -** Mr. Clean makes a guest appearance -** -** Revision 1.6 2000/07/31 04:28:46 matt -** one million cleanups -** -** Revision 1.5 2000/07/17 01:52:27 matt -** made sure last line of all source files is a newline -** -** Revision 1.4 2000/06/09 15:12:25 matt -** initial revision -** -*/ diff --git a/main/cart.hpp b/main/cart.hpp new file mode 100644 index 00000000..b49f0b13 --- /dev/null +++ b/main/cart.hpp @@ -0,0 +1,314 @@ +#pragma once + +#include +#include +#include + +#include "display.hpp" +#include "fs_init.hpp" +#include "spi_lcd.h" +#include "input.h" +#include "logger.hpp" +#include "mmap.hpp" +#include "rom_info.hpp" +#include "st7789.hpp" +#include "menu.hpp" + +/// This class is the base class for all carts. +/// It provides the following functionality: +/// - menu +/// - save/load +/// - screenshot +/// - video setting +/// - romdata +class Cart { +public: + + /// Configuration for the Cart class + struct Config { + RomInfo info; ///< rom info + std::shared_ptr display; ///< display pointer for the menu + espp::Logger::Verbosity verbosity = espp::Logger::Verbosity::WARN; ///< verbosity level for the logger + }; + + /// Constructor + /// \param config configuration for the cart + Cart(const Config& config) + : info_(config.info), + savedir_(FS_PREFIX + "/" + SAVE_DIR), + display_(config.display), + logger_({.tag = "Cart", .level = config.verbosity}) { + logger_.info("ctor"); + menu_ = std::make_unique(Menu::Config{ + .display = display_, + .paused_image_path = get_paused_image_path(), + .action_callback = + std::bind(&Cart::on_menu_action, this, std::placeholders::_1), + .slot_image_callback = [this]() -> std::string { + return get_screenshot_path(false); + }, + .log_level = espp::Logger::Verbosity::WARN + }); + // create the save directory if it doesn't exist + std::error_code ec; + if (!std::filesystem::exists(savedir_, ec)) { + std::filesystem::create_directory(savedir_, ec); + } + } + + ~Cart() { + logger_.info("dtor"); + deinit(); + } + + std::string get_rom_filename() const { + return FS_PREFIX + "/" + info_.rom_path; + } + + virtual void reset() { + logger_.info("reset"); + // the subclass should override this to reset the emulator + } + + virtual void load() { + logger_.info("loading..."); + // move the screenshot to the pause image + auto screenshot_path = get_screenshot_path(true); + auto paused_image_path = get_paused_image_path(); + logger_.debug("copy {} to {}", screenshot_path, paused_image_path); + std::error_code ec; + if (std::filesystem::exists(paused_image_path, ec)) { + 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 paused_image(paused_image_path, std::ios::binary | std::ios::out); + paused_image << screenshot.rdbuf(); + screenshot.close(); + paused_image.close(); + } + + virtual void save() { + logger_.info("saving..."); + // move the pause image to the screenshot + auto paused_image_path = get_paused_image_path(); + auto screenshot_path = get_screenshot_path(true); + logger_.debug("copy {} to {}", paused_image_path, screenshot_path); + std::error_code ec; + if (std::filesystem::exists(paused_image_path, ec)) { + if (std::filesystem::exists(screenshot_path, ec)) { + std::filesystem::remove(screenshot_path, ec); + } + // 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(); + paused_image.close(); + screenshot.close(); + } else { + logger_.warn("paused image does not exist"); + } + } + + /// Save the current screen to a file + /// \param filename filename to save the screenshot to + /// \return true if the screenshot was saved successfully + virtual bool screenshot(std::string_view filename) { + logger_.info("screenshot: {}", filename); + // get the screen data from the display, size of the frame buffer is + // (320*2)*240 formatted as RGB565 + auto size = get_video_size(); + uint16_t width = size.first; + uint16_t height = size.second; + logger_.debug("frame buffer size: {}x{}", width, height); + std::vector frame = get_video_buffer(); + + // save it to the file + std::ofstream file(filename.data(), std::ios::binary); + if (!file.is_open()) { + logger_.error("Failed to open file: {}", filename); + return false; + } + + uint8_t header[4] = { + (uint8_t)(width >> 8), + (uint8_t)(width & 0xFF), + (uint8_t)(height >> 8), + (uint8_t)(height & 0xFF) + }; + // write the header + file.write((char*)header, sizeof(header)); + + // write the data + file.write((char*)frame.data(), frame.size()); + // make sure to close the file + file.close(); + + return true; + } + + virtual void init() { + logger_.info("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("deinit"); + } + + virtual bool run() { + running_ = true; + // handle touchpad so we can know if the user presses the menu + uint8_t _num_touches, _btn_state; + uint16_t _x,_y; + touchpad_read(&_num_touches, &_x, &_y, &_btn_state); + if (_btn_state) { + logger_.warn("Menu pressed!"); + pre_menu(); + // take a screenshot before we show the menu + screenshot(get_paused_image_path()); + // now resume the menu + menu_->resume(); + display_->force_refresh(); + display_->resume(); + // wait here until the menu is no longer shown + while (!menu_->is_paused()) { + using namespace std::chrono_literals; + std::this_thread::sleep_for(100ms); + } + display_->pause(); + // make sure to clear the screen before we resume the game + espp::St7789::clear(0,0,320,240); + // only run the post_menu if we are still running + if (running_) + post_menu(); + } + return running_; + } + +protected: + static constexpr std::string FS_PREFIX = MOUNT_POINT; + static constexpr std::string SAVE_DIR = "/saves/"; + + virtual void on_menu_action(Menu::Action action) { + switch (action) { + case Menu::Action::RESUME: + menu_->pause(); + break; + case Menu::Action::RESET: + reset(); + menu_->pause(); + break; + case Menu::Action::QUIT: + running_ = false; + menu_->pause(); + break; + case Menu::Action::SAVE: + save(); + break; + case Menu::Action::LOAD: + load(); + break; + default: + break; + } + } + + virtual std::string get_save_extension() const { + return ".sav"; + } + + virtual std::string get_screenshot_extension() const { + return ".bin"; + } + + virtual void pre_menu() { + // subclass should override this function if they need to stop their tasks + // or save screen state before the menu is shown + } + + virtual void post_menu() { + // subclass should override this function if they need to resume their tasks + // or restore screen state before the menu is shown + handle_video_setting(); + } + + virtual std::pair get_video_size() const { + // subclass should override this method to return the size of the video + // in the framebuffer. This will be used when capturing screenshots. + return std::make_pair(320, 240); + } + + virtual std::vector get_video_buffer() const { + // subclass should override this method to return the frame buffer + // as a vector of uint16_t + return std::vector(); + } + + // subclass should override these methods + virtual void set_original_video_setting() = 0; + virtual void set_fit_video_setting() = 0; + virtual void set_fill_video_setting() = 0; + + virtual void handle_video_setting() { + logger_.info("handling video setting..."); + switch (get_video_setting()) { + case VideoSetting::ORIGINAL: + set_original_video_setting(); + break; + case VideoSetting::FIT: + set_fit_video_setting(); + break; + case VideoSetting::FILL: + set_fill_video_setting(); + break; + default: + break; + } + } + + std::string get_save_path(bool bypass_exist_check=false) { + namespace fs = std::filesystem; + auto save_path = + savedir_ + "/" + + fs::path(get_rom_filename()).stem().string() + + 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() { + namespace fs = std::filesystem; + auto save_path = + savedir_ + "/paused" + + get_screenshot_extension(); + return save_path; + } + + std::string get_screenshot_path(bool bypass_exist_check=false) { + auto save_path = get_save_path(bypass_exist_check); + if (!save_path.empty()) { + return save_path + get_screenshot_extension(); + } + return ""; + } + + std::atomic running_{false}; + size_t rom_size_bytes_{0}; + uint8_t* romdata_{nullptr}; + RomInfo info_; + std::string savedir_; + std::unique_ptr menu_; + std::shared_ptr display_; + espp::Logger logger_; +}; diff --git a/main/gameboy.hpp b/main/gameboy.hpp deleted file mode 100644 index 7b92b6c3..00000000 --- a/main/gameboy.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -void set_gb_video_original(); -void set_gb_video_fit(); -void set_gb_video_fill(); -void init_gameboy(const std::string& rom_filename, uint8_t *romdata, size_t rom_data_size); -void run_gameboy_rom(); -void deinit_gameboy(); diff --git a/main/gbc_cart.hpp b/main/gbc_cart.hpp new file mode 100644 index 00000000..c2d24a0b --- /dev/null +++ b/main/gbc_cart.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include "cart.hpp" +#include "gameboy.hpp" + +class GbcCart : public Cart { +public: + + GbcCart(const Cart::Config& config) + : Cart(config) { + init(); + } + + ~GbcCart() { + deinit(); + } + + virtual void reset() override { + Cart::reset(); + reset_gameboy(); + } + + virtual void load() override { + Cart::load(); + load_gameboy(get_save_path()); + } + + virtual void save() override { + Cart::save(); + save_gameboy(get_save_path(true)); + } + + virtual void init() override { + Cart::init(); + init_gameboy(get_rom_filename(), romdata_, rom_size_bytes_); + start_gameboy_tasks(); + } + + virtual void deinit() override { + stop_gameboy_tasks(); + deinit_gameboy(); + } + + virtual bool run() override { + run_gameboy_rom(); + return Cart::run(); + } + +protected: + // GB + static constexpr size_t GAMEBOY_WIDTH = 160; + static constexpr size_t GAMEBOY_HEIGHT = 144; + + virtual void pre_menu() override { + Cart::pre_menu(); + logger_.info("gbc::pre_menu()"); + stop_gameboy_tasks(); + } + + virtual void post_menu() override { + Cart::post_menu(); + logger_.info("gbc::post_menu()"); + start_gameboy_tasks(); + } + + virtual void set_original_video_setting() override { + logger_.info("gbc::video: original"); + set_gb_video_original(); + } + + virtual std::pair get_video_size() const override { + return std::make_pair(GAMEBOY_WIDTH, GAMEBOY_HEIGHT); + } + + virtual std::vector get_video_buffer() const override { + return get_gameboy_video_buffer(); + } + + virtual void set_fit_video_setting() override { + logger_.info("gbc::video: fit"); + set_gb_video_fit(); + } + + virtual void set_fill_video_setting() override { + logger_.info("gbc::video: fill"); + set_gb_video_fill(); + } + + virtual std::string get_save_extension() const override { + switch (info_.platform) { + case Emulator::GAMEBOY: + return "_gb.sav"; + case Emulator::GAMEBOY_COLOR: + return "_gbc.sav"; + default: + return Cart::get_save_extension(); + } + } +}; diff --git a/main/main.cpp b/main/main.cpp index 694fe488..e31eba3d 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -22,6 +22,8 @@ #include "drv2605.hpp" +#include "gbc_cart.hpp" +#include "nes_cart.hpp" #include "heap_utils.hpp" #include "string_utils.hpp" #include "fs_init.hpp" @@ -34,20 +36,40 @@ extern std::shared_ptr display; using namespace std::chrono_literals; -// GB -#define GAMEBOY_WIDTH (160) -#define GAMEBOY_HEIGHT (144) -// SMS -#define SMS_WIDTH (256) -#define SMS_HEIGHT (192) -// GG -#define GAMEGEAR_WIDTH (160) -#define GAMEGEAR_HEIGHT (144) +bool operator==(const InputState& lhs, const InputState& rhs) { + return + lhs.a == rhs.a && + lhs.b == rhs.b && + lhs.x == rhs.x && + lhs.y == rhs.y && + lhs.select == rhs.select && + lhs.start == rhs.start && + lhs.up == rhs.up && + lhs.down == rhs.down && + lhs.left == rhs.left && + lhs.right == rhs.right && + lhs.joystick_select == rhs.joystick_select; +} -static QueueHandle_t gpio_evt_queue; -static void gpio_isr_handler(void *arg) { - uint32_t gpio_num = (uint32_t)arg; - xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); +std::unique_ptr make_cart(const RomInfo& info) { + switch (info.platform) { + case Emulator::GAMEBOY: + case Emulator::GAMEBOY_COLOR: + return std::make_unique(Cart::Config{ + .info = info, + .display = display, + .verbosity = espp::Logger::Verbosity::WARN + }); + break; + case Emulator::NES: + return std::make_unique(Cart::Config{ + .info = info, + .display = display, + .verbosity = espp::Logger::Verbosity::WARN + }); + default: + return nullptr; + } } extern "C" void app_main(void) { @@ -66,29 +88,23 @@ extern "C" void app_main(void) { // init the input subsystem init_input(); - auto write_drv = [](uint8_t reg, uint8_t data) { - uint8_t buf[] = {reg, data}; - i2c_write_external_bus(Drv2605::ADDRESS, buf, 2); - }; - auto read_drv = [](uint8_t reg) -> uint8_t { - uint8_t read_data; - i2c_read_external_bus(Drv2605::ADDRESS, reg, &read_data, 1); - return read_data; - }; - - Drv2605 haptic_motor({ - .write = write_drv, - .read = read_drv, + espp::Drv2605 haptic_motor(espp::Drv2605::Config{ + .device_address = espp::Drv2605::DEFAULT_ADDRESS, + .write = i2c_write_external_bus, + .read = i2c_read_external_bus, + .motor_type = espp::Drv2605::MotorType::LRA }); - // we're using an ERM motor, so select an ERM library. - haptic_motor.select_library(1); + // we're using an LRA motor, so select th LRA library. + haptic_motor.select_library(6); auto play_haptic = [&haptic_motor]() { haptic_motor.start(); }; auto set_waveform = [&haptic_motor](int waveform) { - haptic_motor.set_waveform(0, (Drv2605::Waveform)waveform); - haptic_motor.set_waveform(1, Drv2605::Waveform::END); + haptic_motor.set_waveform(0, espp::Drv2605::Waveform::SOFT_BUMP); + haptic_motor.set_waveform(1, espp::Drv2605::Waveform::SOFT_FUZZ); + haptic_motor.set_waveform(2, (espp::Drv2605::Waveform)(waveform)); + haptic_motor.set_waveform(3, espp::Drv2605::Waveform::END); }; fmt::print("initializing gui...\n"); @@ -100,79 +116,6 @@ extern "C" void app_main(void) { .log_level = espp::Logger::Verbosity::WARN }); - static constexpr size_t BOOT_GPIO = 0; - static constexpr size_t MUTE_GPIO = 1; - // create the gpio event queue - gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); - // setup gpio interrupts for boot button and mute button - gpio_config_t io_conf; - memset(&io_conf, 0, sizeof(io_conf)); - // interrupt on any edge (since MUTE is connected to flipflop, see note below) - io_conf.intr_type = GPIO_INTR_ANYEDGE; - io_conf.pin_bit_mask = (1< bool { - static uint32_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((gpio_num_t)io_num); - // fmt::print("Got gpio interrupt: {}, pressed: {}\n", io_num, pressed); - // see if it's the mute button or the boot button - if (io_num == MUTE_GPIO) { - // 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 - // read the state to know whether to be muted or not. - gui.set_mute(pressed); - // now make sure the output sound is updated - set_audio_volume(gui.get_audio_level()); - } else if (io_num == BOOT_GPIO && pressed) { - // toggle between the original / fit / fill video scaling modes; - // NOTE: only do something the state is high, since this gpio has no - // flip-flop. - gui.next_video_setting(); - // set the video scaling for the emulation - auto video_scaling = gui.get_video_setting(); - switch (video_scaling) { - case Gui::VideoSetting::ORIGINAL: - set_nes_video_original(); - set_gb_video_original(); - break; - case Gui::VideoSetting::FIT: - set_nes_video_fit(); - set_gb_video_fit(); - break; - case Gui::VideoSetting::FILL: - set_nes_video_fill(); - set_gb_video_fill(); - break; - case Gui::VideoSetting::MAX_UNUSED: - default: - break; - } - } - } - // don't want to stop the task - return false; - }, - .stack_size_bytes = 4*1024, - }); - gpio_task.start(); - - // update the mute state (since it's a flip-flop and may have been set if we - // restarted without power loss) - bool muted = !gpio_get_level((gpio_num_t)MUTE_GPIO); - gui.set_mute(muted); - // the prefix for the filesystem (either littlefs or sdcard) std::string fs_prefix = MOUNT_POINT; @@ -183,116 +126,77 @@ extern "C" void app_main(void) { gui.add_rom(rom.name, boxart_prefix + rom.boxart_path); } - int x_offset, y_offset; - // store the offset for resetting to later (after emulation ends) - espp::St7789::get_offset(x_offset, y_offset); - while (true) { // reset gui ready to play and user_quit gui.ready_to_play(false); - reset_user_quit(); + struct InputState prev_state; + struct InputState curr_state; + get_input_state(&prev_state); + get_input_state(&curr_state); while (!gui.ready_to_play()) { // TODO: would be better to make this an actual LVGL input device instead // of this.. - static struct InputState prev_state; - static struct InputState curr_state; get_input_state(&curr_state); - if (curr_state.up && !prev_state.up) { - gui.previous(); - } else if (curr_state.down && !prev_state.down) { - gui.next(); - } else if (curr_state.start) { - // same as play button was pressed, just exit the loop! - break; + if (curr_state != prev_state) { + prev_state = curr_state; + if (curr_state.up) { + gui.previous(); + } else if (curr_state.down) { + gui.next(); + } else if (curr_state.start) { + // same as play button was pressed, just exit the loop! + break; + } } - prev_state = curr_state; - std::this_thread::sleep_for(100ms); + std::this_thread::sleep_for(50ms); } // have broken out of the loop, let the user know we're processing... haptic_motor.start(); - // update the audio level according to the gui - set_audio_volume(gui.get_audio_level()); - // Now pause the LVGL gui display->pause(); gui.pause(); - // set the video scaling for the emulation - auto video_scaling = gui.get_video_setting(); - switch (video_scaling) { - case Gui::VideoSetting::ORIGINAL: - set_nes_video_original(); - set_gb_video_original(); - break; - case Gui::VideoSetting::FIT: - set_nes_video_fit(); - set_gb_video_fit(); - break; - case Gui::VideoSetting::FILL: - set_nes_video_fill(); - set_gb_video_fill(); - break; - case Gui::VideoSetting::MAX_UNUSED: - default: - break; - } - // ensure the display has been paused - std::this_thread::sleep_for(500ms); - - auto selected_rom_index = gui.get_selected_rom_index(); - fmt::print("Selected rom index: {}\n", selected_rom_index); - auto selected_rom_info = roms[selected_rom_index]; + std::this_thread::sleep_for(100ms); - // copy the rom into the nesgame partition and memory map it - std::string rom_filename = fs_prefix + "/" + selected_rom_info.rom_path; - size_t rom_size_bytes = copy_romdata_to_nesgame_partition(rom_filename); - if (rom_size_bytes) { - uint8_t* romdata = get_mmapped_romdata(); - fmt::print("Got mmapped romdata for {}, length={}\n", rom_filename, rom_size_bytes); + fmt::print("Before emulation, minimum free heap: {}\n", heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT)); - // Clear the display - espp::St7789::clear(0,0,320,240); - - switch (selected_rom_info.platform) { - case Emulator::GAMEBOY: - case Emulator::GAMEBOY_COLOR: - init_gameboy(rom_filename, romdata, rom_size_bytes); - while (!user_quit()) { - run_gameboy_rom(); - } - deinit_gameboy(); - break; - case Emulator::NES: - init_nes(rom_filename, romdata, rom_size_bytes); - while (!user_quit()) { - run_nes_rom(); + auto selected_rom_index = gui.get_selected_rom_index(); + if (selected_rom_index < roms.size()) { + fmt::print("Selected rom:\n"); + fmt::print(" index: {}\n", selected_rom_index); + auto selected_rom_info = roms[selected_rom_index]; + fmt::print(" name: {}\n", selected_rom_info.name); + fmt::print(" path: {}\n", selected_rom_info.rom_path); + + // Cart handles platform specific code, state management, etc. + { + std::unique_ptr cart = std::move(make_cart(selected_rom_info)); + if (cart) { + fmt::print("Running cart...\n"); + while (cart->run()); + } else { + fmt::print("Failed to create cart!\n"); } - deinit_nes(); - break; - default: - break; } } else { - fmt::print("Could not copy {} into nesgame_partition!\n", rom_filename); + fmt::print("Invalid rom selected!\n"); } - fmt::print("quitting emulation...\n"); - - std::this_thread::sleep_for(500ms); + std::this_thread::sleep_for(100ms); fmt::print("Resuming your regularly scheduled programming...\n"); + + fmt::print("During emulation, minimum free heap: {}\n", heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT)); + // need to reset to control the whole screen espp::St7789::clear(0,0,320,240); - // reset the offset - espp::St7789::set_offset(x_offset, y_offset); + gui.resume(); display->force_refresh(); - display->resume(); - gui.resume(); } } diff --git a/main/nes_cart.hpp b/main/nes_cart.hpp new file mode 100644 index 00000000..f2cbc7f2 --- /dev/null +++ b/main/nes_cart.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include "cart.hpp" +#include "nes.hpp" + +class NesCart : public Cart { +public: + + NesCart(const Cart::Config& config) + : Cart(config) { + init(); + } + + ~NesCart() { + deinit(); + } + + virtual void reset() override { + Cart::reset(); + reset_nes(); + } + + virtual void load() override { + Cart::load(); + load_nes(get_save_path()); + // TODO: right now load_nes will change the screen data since the task is + // still running. This is a hack to fix that. + display_->force_refresh(); + } + + virtual void save() override { + Cart::save(); + save_nes(get_save_path(true)); + } + + virtual void init() override { + Cart::init(); + init_nes(get_rom_filename(), romdata_, rom_size_bytes_); + start_nes_tasks(); + } + + virtual void deinit() override { + stop_nes_tasks(); + deinit_nes(); + } + + virtual bool run() override { + run_nes_rom(); + return Cart::run(); + } + +protected: + static constexpr size_t NES_WIDTH = 256; + static constexpr size_t NES_HEIGHT = 240; + + virtual void pre_menu() override { + Cart::pre_menu(); + logger_.info("nes::pre_menu()"); + stop_nes_tasks(); + } + + virtual void post_menu() override { + Cart::post_menu(); + logger_.info("nes::post_menu()"); + start_nes_tasks(); + } + + virtual std::pair get_video_size() const override { + return std::make_pair(NES_WIDTH, NES_HEIGHT); + } + + virtual std::vector get_video_buffer() const override { + return get_nes_video_buffer(); + } + + virtual void set_original_video_setting() override { + set_nes_video_original(); + } + + virtual void set_fit_video_setting() override { + set_nes_video_fit(); + } + + virtual void set_fill_video_setting() override { + set_nes_video_fill(); + } + + virtual std::string get_save_extension() const override { + return "_nes.sav"; + } +}; diff --git a/main/rom_info.cpp b/main/rom_info.cpp new file mode 100644 index 00000000..b8ee5b90 --- /dev/null +++ b/main/rom_info.cpp @@ -0,0 +1,60 @@ +#include "rom_info.hpp" + +std::vector parse_metadata(const std::string& metadata_path) { + std::vector infos; + // load metadata path + std::ifstream metadata(metadata_path, std::ios::in); + if (!metadata.is_open()) { + fmt::print("Couldn't load metadata file {}!\n", metadata_path); + return infos; + } + // parse it as csv, format = rom_path, boxart_path, name - name is last + // because it might have commas in it. + std::string line; + while (std::getline(metadata, line)) { + // get the fields from each line + std::string rom_path, boxart_path, name; + char *str = line.data(); + char *token = strtok(str, ","); + int num_tokens = 0; + while (token != NULL && num_tokens < 3) { + switch (num_tokens) { + case 0: + // rom path + rom_path = token; + rom_path = trim(rom_path); + break; + case 1: + // boxart path + boxart_path = token; + boxart_path = trim(boxart_path); + break; + case 2: + // name + name = token; + name = trim(name); + break; + default: + // DANGER WILL ROBINSON + break; + } + token = strtok(NULL, ","); + num_tokens++; + } + fmt::print("INFO: '{}', '{}', '{}'\n", rom_path, boxart_path, name); + Emulator platform = Emulator::UNKNOWN; + if (endsWith(rom_path, ".nes")) { + platform = Emulator::NES; + } else if (endsWith(rom_path, ".gb")) { + platform = Emulator::GAMEBOY; + } else if (endsWith(rom_path, ".gbc")) { + platform = Emulator::GAMEBOY_COLOR; + } + if (platform != Emulator::UNKNOWN) { + // for each row, create rom entry + infos.emplace_back(name, boxart_path, rom_path, platform); + } + } + + return infos; +} diff --git a/main/rom_info.hpp b/main/rom_info.hpp index 80225824..31d93091 100644 --- a/main/rom_info.hpp +++ b/main/rom_info.hpp @@ -2,9 +2,9 @@ #include #include +#include #include "format.hpp" - #include "string_utils.hpp" enum class Emulator { UNKNOWN, NES, GAMEBOY, GAMEBOY_COLOR, SEGA_MASTER_SYSTEM, GENESIS, SNES }; @@ -16,61 +16,4 @@ struct RomInfo { Emulator platform; }; -std::vector parse_metadata(const std::string& metadata_path) { - std::vector infos; - // load metadata path - std::ifstream metadata(metadata_path, std::ios::in); - if (!metadata.is_open()) { - fmt::print("Couldn't load metadata file {}!\n", metadata_path); - return infos; - } - // parse it as csv, format = rom_path, boxart_path, name - name is last - // because it might have commas in it. - std::string line; - while (std::getline(metadata, line)) { - // get the fields from each line - std::string rom_path, boxart_path, name; - char *str = line.data(); - char *token = strtok(str, ","); - int num_tokens = 0; - while (token != NULL && num_tokens < 3) { - switch (num_tokens) { - case 0: - // rom path - rom_path = token; - rom_path = trim(rom_path); - break; - case 1: - // boxart path - boxart_path = token; - boxart_path = trim(boxart_path); - break; - case 2: - // name - name = token; - name = trim(name); - break; - default: - // DANGER WILL ROBINSON - break; - } - token = strtok(NULL, ","); - num_tokens++; - } - fmt::print("INFO: '{}', '{}', '{}'\n", rom_path, boxart_path, name); - Emulator platform = Emulator::UNKNOWN; - if (endsWith(rom_path, ".nes")) { - platform = Emulator::NES; - } else if (endsWith(rom_path, ".gb")) { - platform = Emulator::GAMEBOY; - } else if (endsWith(rom_path, ".gbc")) { - platform = Emulator::GAMEBOY_COLOR; - } - if (platform != Emulator::UNKNOWN) { - // for each row, create rom entry - infos.emplace_back(name, boxart_path, rom_path, platform); - } - } - - return infos; -} +std::vector parse_metadata(const std::string& metadata_path); diff --git a/main/string_utils.cpp b/main/string_utils.cpp new file mode 100644 index 00000000..bffa9900 --- /dev/null +++ b/main/string_utils.cpp @@ -0,0 +1,34 @@ +#include "string_utils.hpp" + +static const std::string WHITESPACE = " \n\r\t\f\v"; + +bool endsWith(const std::string& a, const std::string& b) { + if (b.size() > a.size()) return false; + return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin()); +} + +std::string ltrim(const std::string &s) +{ + size_t start = s.find_first_not_of(WHITESPACE); + return (start == std::string::npos) ? "" : s.substr(start); +} +std::string rtrim(const std::string &s) +{ + size_t end = s.find_last_not_of(WHITESPACE); + return (end == std::string::npos) ? "" : s.substr(0, end + 1); +} +std::string trim(const std::string &s) { + return rtrim(ltrim(s)); +} + +const char* getfield(char* line, int num) { + const char* tok; + for (tok = strtok(line, ","); + tok && *tok; + tok = strtok(NULL, ",\n")) + { + if (!--num) + return tok; + } + return NULL; +} diff --git a/main/string_utils.hpp b/main/string_utils.hpp index 75c42b84..960e1ee3 100644 --- a/main/string_utils.hpp +++ b/main/string_utils.hpp @@ -2,35 +2,10 @@ #include #include +#include -bool endsWith(const std::string& a, const std::string& b) { - if (b.size() > a.size()) return false; - return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin()); -} - -static const std::string WHITESPACE = " \n\r\t\f\v"; -std::string ltrim(const std::string &s) -{ - size_t start = s.find_first_not_of(WHITESPACE); - return (start == std::string::npos) ? "" : s.substr(start); -} -std::string rtrim(const std::string &s) -{ - size_t end = s.find_last_not_of(WHITESPACE); - return (end == std::string::npos) ? "" : s.substr(0, end + 1); -} -std::string trim(const std::string &s) { - return rtrim(ltrim(s)); -} - -const char* getfield(char* line, int num) { - const char* tok; - for (tok = strtok(line, ","); - tok && *tok; - tok = strtok(NULL, ",\n")) - { - if (!--num) - return tok; - } - return NULL; -} +bool endsWith(const std::string& a, const std::string& b); +std::string ltrim(const std::string &s); +std::string rtrim(const std::string &s); +std::string trim(const std::string &s); +const char* getfield(char* line, int num); diff --git a/metadata.csv b/metadata.csv index 68d61e5f..36cecdd6 100644 --- a/metadata.csv +++ b/metadata.csv @@ -5,8 +5,24 @@ zelda.nes, boxart/zelda1.jpg, The Legend of Zelda zelda_2.nes, boxart/zelda2.jpg, The Legend of Zelda 2: the Adventure of Link mega_man.nes, boxart/megaman1.jpg, MegaMan metroid.nes, boxart/metroid1.jpg, Metroid +mario_open_golf.nes, boxart/mario_open_golf.jpg, Mario Open Golf +metal_gear.nes, boxart/metal_gear.jpg, Metal Gear +final_fantasy.nes, boxart/final_fantasy.jpg, Final Fantasy +final_fantasy_ii.nes, boxart/final_fantasy_ii.jpg, Final Fantasy II +final_fantasy_iii.nes, boxart/final_fantasy_iii.jpg, Final Fantasy III +batman_the_animated_series.gb, boxart/batman_the_animated_series.jpg, Batman: The Animated Series +duck_tales.gb, boxart/duck_tales.jpg, Duck Tales +final_fantasy_adventure.gb, boxart/final_fantasy_adventure.jpg, Final Fantasy Adventure +harvest_moon.gb, boxart/harvest_moon.jpg, Harvest Moon +mario_golf.gbc, boxart/mario_golf.jpg, Mario Golf +mario_tennis.gbc, boxart/mario_tennis.jpg, Mario Tennis +metroid_2_return_of_samus.gb, boxart/metroid_2_return_of_samus.jpg, Metroid 2: Return of Samus +metal_gear_solid.gbc, boxart/metal_gear_solid.jpg, Metal Gear Solid pokemon_blue.gb, boxart/pokemon_blue.jpg, Pokemon Blue pokemon_red.gb, boxart/pokemon_red.jpg, Pokemon Red pokemon_yellow.gbc, boxart/pokemon_yellow.jpg, Pokemon Yellow +pokemon_crystal.gbc, boxart/pokemon_crystal.jpg, Pokemon Crystal links_awakening.gb, boxart/tloz_links_awakening.jpg, The Legend of Zelda: Link's Awakening links_awakening.gbc, boxart/tloz_links_awakening_dx.jpg, The Legend of Zelda: Link's Awakening DX +tloz_oracle_of_ages.gbc, boxart/tloz_oracle_ages.jpg, The Legend of Zelda: Oracle of Ages +tloz_oracle_of_seasons.gbc, boxart/tloz_oracle_seasons.jpg, The Legend of Zelda: Oracle of Seasons diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 3e1971a3..0cc096ca 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -12,11 +12,13 @@ CONFIG_ESPTOOLPY_FLASHSIZE="16MB" CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y + # CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y # Common ESP-related # -CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096 +# CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096 CONFIG_ESP_MAIN_TASK_STACK_SIZE=32768 # SPIRAM Configuration @@ -32,7 +34,6 @@ CONFIG_SPIRAM_SPEED_80M=y CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" - # # FATFS config CONFIG_FATFS_LONG_FILENAMES=y @@ -44,6 +45,8 @@ CONFIG_FATFS_LFN_HEAP=y CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH=y + # # LVGL configuration - # Monitoring # @@ -52,6 +55,9 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 CONFIG_LV_BUILD_EXAMPLES=n +# NOTE: this will need to be increased if more menu / UI elements are added, or if there are a _lot_ of roms... +CONFIG_LV_MEM_SIZE_KILOBYTES=50 + # # LVGL configuration - # Color settings # @@ -71,10 +77,3 @@ CONFIG_LV_USE_THEME_DEFAULT=y CONFIG_LV_THEME_DEFAULT_DARK=y CONFIG_LV_THEME_DEFAULT_GROW=y CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME=80 - -# LVGL Configuration - 3rd party libraries -CONFIG_LV_USE_FS_POSIX=y -# configure the lv drive letter to be 'L' (76) for use as "L:/..." -CONFIG_LV_FS_POSIX_LETTER=76 -# CONFIG_LV_USE_SJPG=y -# CONFIG_LV_USE_QRCODE=y