diff --git a/CMakeLists.txt b/CMakeLists.txt index 31c44c2..10a423b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,10 @@ message("that you are resting well.") message(" -- Your friend, Stephanie") message("******************************") +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + add_compile_definitions(EMU_DEBUG=1) +endif() + # Main project sources add_subdirectory(src) diff --git a/include/dbvzRegisterAccessors.c.h b/include/dbvzRegisterAccessors.c.h index f813ca1..1e220c7 100644 --- a/include/dbvzRegisterAccessors.c.h +++ b/include/dbvzRegisterAccessors.c.h @@ -710,6 +710,7 @@ static void setUstcnt2(uint16_t value){ registerArrayWrite16(USTCNT2, value); updateUart2Interrupt(); + updateUart2PortState(); } static void setTstat1(uint16_t value){ diff --git a/include/dbvzTiming.c.h b/include/dbvzTiming.c.h index c4e9b89..f89bb8e 100644 --- a/include/dbvzTiming.c.h +++ b/include/dbvzTiming.c.h @@ -404,6 +404,9 @@ static void dbvzEndClk32(void){ updateUart1Interrupt(); updateUart2Interrupt(); + updateUart1PortState(); + updateUart2PortState(); + checkInterrupts(); } diff --git a/include/emulator.h b/include/emulator.h index 9d27ef8..bfeb1d8 100644 --- a/include/emulator.h +++ b/include/emulator.h @@ -109,7 +109,7 @@ enum{ }; //types -typedef struct{ +typedef struct { bool enable; bool enableParity; bool oddParity; @@ -215,7 +215,11 @@ extern void (*palmSerialDataFlush)(void);//called by the emulator to delete extern void (*palmGetRtcFromHost)(uint8_t* writeBack);//[0] = hours, [1] = minutes, [2] = seconds //functions -uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmBootloaderData, uint32_t palmBootloaderSize, bool syncRtc, bool allowInvalidBehavior); +uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t *palmRomData, + uint32_t palmRomSize, uint8_t *palmBootloaderData, + uint32_t palmBootloaderSize, bool syncRtc, + bool allowInvalidBehavior, const char *serialPortDev); + void emulatorDeinit(void); void emulatorHardReset(void); void emulatorSoftReset(void); diff --git a/include/serial.h b/include/serial.h new file mode 100644 index 0000000..f2587e0 --- /dev/null +++ b/include/serial.h @@ -0,0 +1,18 @@ +// +// Created by stephanie on 6/14/24. +// + +#ifndef MU_SERIAL_H +#define MU_SERIAL_H + +#include "emulator.h" + +/** + * Opens and initializes the serial port. + * + * @param path The path of the serial port. + * @since 2024/06/14 + */ +void mu_serial_open_and_init(const char* path); + +#endif // MU_SERIAL_H diff --git a/libretroBuildSystem/CMakeLists.txt b/libretroBuildSystem/CMakeLists.txt index d8edda5..e108f9b 100644 --- a/libretroBuildSystem/CMakeLists.txt +++ b/libretroBuildSystem/CMakeLists.txt @@ -14,6 +14,10 @@ add_library(mu_libretro SHARED # Remove the "lib" prefix always, RetroArch does not name in this way set_target_properties(mu_libretro PROPERTIES PREFIX "") +# Define these +target_compile_definitions(mu_libretro PUBLIC + __LIBRETRO__=1) + # Bring all the sub-modules as needed target_link_libraries(mu_libretro MuCore) diff --git a/libretroBuildSystem/libretro.c b/libretroBuildSystem/libretro.c index 9595a24..e4c33d6 100644 --- a/libretroBuildSystem/libretro.c +++ b/libretroBuildSystem/libretro.c @@ -1,11 +1,11 @@ #include "libretro.h" -#include #include -#include +#include #include +#include #include -#include +#include #include #include @@ -13,421 +13,449 @@ #include #include +#include "cursors.h" #include "emulator.h" -#include "portability.h" -#include "silkscreen.h" #include "fileLauncher/launcher.h" -#include "cursors.h" #include "miniz.h" +#include "portability.h" +#include "silkscreen.h" #define JOYSTICK_DEADZONE 4000 #define JOYSTICK_MULTIPLIER 0.0001 #define SCREEN_HIRES (!(palmFramebufferWidth == 160)) - -static retro_log_printf_t log_cb = NULL; -static retro_video_refresh_t video_cb = NULL; +static retro_log_printf_t log_cb = NULL; +static retro_video_refresh_t video_cb = NULL; static retro_audio_sample_batch_t audio_cb = NULL; -static retro_set_led_state_t led_cb = NULL; -static retro_environment_t environ_cb = NULL; -static retro_input_poll_t input_poll_cb = NULL; -static retro_input_state_t input_state_cb = NULL; - -static double cpuSpeed; -static bool syncRtc; -static bool allowInvalidBehavior; -static const char* osVersion; -static uint8_t deviceModel; -static bool firstRetroRunCall; -static bool dontRenderGraffiti; -static bool useJoystickAsMouse; -static float touchCursorX; -static float touchCursorY; -static char contentPath[PATH_MAX_LENGTH]; -static uint16_t mouseCursorOldArea[32 * 32]; -static bool runningImgFile; -static uint16_t screenYEnd; - - -static void frontendGetCurrentTime(uint8_t* writeBack){ - time_t rawTime; - struct tm* timeInfo; - - time(&rawTime); - timeInfo = localtime(&rawTime); - - writeBack[0] = timeInfo->tm_hour; - writeBack[1] = timeInfo->tm_min; - writeBack[2] = timeInfo->tm_sec; -} - -static void renderMouseCursor(int16_t screenX, int16_t screenY){ - if(SCREEN_HIRES){ - int8_t x; - int8_t y; - - //align cursor to side of image - screenX -= 6; - - for(y = 0; y < 32; y++){ - for(x = 6; x < 26; x++){ - if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight){ - mouseCursorOldArea[y * 32 + x] = palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x]; - if(cursor32x32[y * 32 + x] != 0xFFFF) - palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor32x32[y * 32 + x]; - } - } +static retro_set_led_state_t led_cb = NULL; +static retro_environment_t environ_cb = NULL; +static retro_input_poll_t input_poll_cb = NULL; +static retro_input_state_t input_state_cb = NULL; + +static double cpuSpeed; +static bool syncRtc; +static bool allowInvalidBehavior; +static const char *osVersion; +static uint8_t deviceModel; +static bool firstRetroRunCall; +static bool dontRenderGraffiti; +static bool useJoystickAsMouse; +static float touchCursorX; +static float touchCursorY; +static char contentPath[PATH_MAX_LENGTH]; +static uint16_t mouseCursorOldArea[32 * 32]; +static bool runningImgFile; +static uint16_t screenYEnd; + +static void frontendGetCurrentTime(uint8_t *writeBack) { + time_t rawTime; + struct tm *timeInfo; + + time(&rawTime); + timeInfo = localtime(&rawTime); + + writeBack[0] = timeInfo->tm_hour; + writeBack[1] = timeInfo->tm_min; + writeBack[2] = timeInfo->tm_sec; +} + +static void renderMouseCursor(int16_t screenX, int16_t screenY) { + if (SCREEN_HIRES) { + int8_t x; + int8_t y; + + // align cursor to side of image + screenX -= 6; + + for (y = 0; y < 32; y++) { + for (x = 6; x < 26; x++) { + if (screenX + x >= 0 && screenY + y >= 0 && + screenX + x < palmFramebufferWidth && + screenY + y < palmFramebufferHeight) { + mouseCursorOldArea[y * 32 + x] = + palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + + x]; + if (cursor32x32[y * 32 + x] != 0xFFFF) + palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + + x] = cursor32x32[y * 32 + x]; + } } - } - else{ - int8_t x; - int8_t y; - - //align cursor to side of image - screenX -= 3; - - for(y = 0; y < 16; y++){ - for(x = 3; x < 13; x++){ - if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight){ - mouseCursorOldArea[y * 16 + x] = palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x]; - if(cursor16x16[y * 16 + x] != 0xFFFF) - palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor16x16[y * 16 + x]; - } - } - } - } -} - -static void unrenderMouseCursor(int16_t screenX, int16_t screenY){ - if(SCREEN_HIRES){ - int8_t x; - int8_t y; - - //align cursors missing rectangle to side of image - screenX -= 6; - - for(y = 0; y < 32; y++) - for(x = 6; x < 26; x++) - if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight) - palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = mouseCursorOldArea[y * 32 + x]; - } - else{ - int8_t x; - int8_t y; - - //align cursors missing rectangle to side of image - screenX -= 3; - - for(y = 0; y < 16; y++) - for(x = 3; x < 13; x++) - if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight) - palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = mouseCursorOldArea[y * 16 + x]; - } -} - -static void fallback_log(enum retro_log_level level, const char *fmt, ...){ - va_list va; - - (void)level; - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); -} - -static void check_variables(bool booting){ - struct retro_variable var = {0}; - - if(booting){ - var.key = "palm_emu_cpu_speed"; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - cpuSpeed = atoi(var.value); - - var.key = "palm_emu_feature_synced_rtc"; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - syncRtc = !strcmp(var.value, "enabled"); - - var.key = "palm_emu_feature_durable"; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - allowInvalidBehavior = !strcmp(var.value, "enabled"); - } - - var.key = "palm_emu_use_joystick_as_mouse"; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - useJoystickAsMouse = !strcmp(var.value, "enabled"); - - var.key = "palm_emu_disable_graffiti"; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - dontRenderGraffiti = !strcmp(var.value, "enabled"); - - var.key = "palm_emu_os_version"; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value){ - if(!strcmp(var.value, "Palm m500/Palm OS 4.0")){ - deviceModel = EMU_DEVICE_PALM_M500; - osVersion = "palmos40-en-m500"; - } - else if(!strcmp(var.value, "Palm m515/Palm OS 4.1")){ - deviceModel = EMU_DEVICE_PALM_M515; - osVersion = "palmos41-en-m515"; + } + } else { + int8_t x; + int8_t y; + + // align cursor to side of image + screenX -= 3; + + for (y = 0; y < 16; y++) { + for (x = 3; x < 13; x++) { + if (screenX + x >= 0 && screenY + y >= 0 && + screenX + x < palmFramebufferWidth && + screenY + y < palmFramebufferHeight) { + mouseCursorOldArea[y * 16 + x] = + palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + + x]; + if (cursor16x16[y * 16 + x] != 0xFFFF) + palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + + x] = cursor16x16[y * 16 + x]; + } } + } + } +} + +static void unrenderMouseCursor(int16_t screenX, int16_t screenY) { + if (SCREEN_HIRES) { + int8_t x; + int8_t y; + + // align cursors missing rectangle to side of image + screenX -= 6; + + for (y = 0; y < 32; y++) + for (x = 6; x < 26; x++) + if (screenX + x >= 0 && screenY + y >= 0 && + screenX + x < palmFramebufferWidth && + screenY + y < palmFramebufferHeight) + palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = + mouseCursorOldArea[y * 32 + x]; + } else { + int8_t x; + int8_t y; + + // align cursors missing rectangle to side of image + screenX -= 3; + + for (y = 0; y < 16; y++) + for (x = 3; x < 13; x++) + if (screenX + x >= 0 && screenY + y >= 0 && + screenX + x < palmFramebufferWidth && + screenY + y < palmFramebufferHeight) + palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = + mouseCursorOldArea[y * 16 + x]; + } +} + +static void fallback_log(enum retro_log_level level, const char *fmt, ...) { + va_list va; + + (void)level; + + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); +} + +static void check_variables(bool booting) { + struct retro_variable var = {0}; + + if (booting) { + var.key = "palm_emu_cpu_speed"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + cpuSpeed = atoi(var.value); + + var.key = "palm_emu_feature_synced_rtc"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + syncRtc = !strcmp(var.value, "enabled"); + + var.key = "palm_emu_feature_durable"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + allowInvalidBehavior = !strcmp(var.value, "enabled"); + } + + var.key = "palm_emu_use_joystick_as_mouse"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + useJoystickAsMouse = !strcmp(var.value, "enabled"); + + var.key = "palm_emu_disable_graffiti"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + dontRenderGraffiti = !strcmp(var.value, "enabled"); + + var.key = "palm_emu_os_version"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (!strcmp(var.value, "Palm m500/Palm OS 4.0")) { + deviceModel = EMU_DEVICE_PALM_M500; + osVersion = "palmos40-en-m500"; + } else if (!strcmp(var.value, "Palm m515/Palm OS 4.1")) { + deviceModel = EMU_DEVICE_PALM_M515; + osVersion = "palmos41-en-m515"; + } #if defined(EMU_SUPPORT_PALM_OS5) - else if(!strcmp(var.value, "Tungsten T3/Palm OS 5.2.1")){ - deviceModel = EMU_DEVICE_TUNGSTEN_T3; - osVersion = "palmos52-en-t3"; - } - else if(!strcmp(var.value, "Tungsten T3/Palm OS 6.0")){ - deviceModel = EMU_DEVICE_TUNGSTEN_T3; - osVersion = "palmos60-en-t3"; - } + else if (!strcmp(var.value, "Tungsten T3/Palm OS 5.2.1")) { + deviceModel = EMU_DEVICE_TUNGSTEN_T3; + osVersion = "palmos52-en-t3"; + } else if (!strcmp(var.value, "Tungsten T3/Palm OS 6.0")) { + deviceModel = EMU_DEVICE_TUNGSTEN_T3; + osVersion = "palmos60-en-t3"; + } #endif - else{ - deviceModel = EMU_DEVICE_PALM_M515; - osVersion = "palmos41-en-m515"; - } - } + else { + deviceModel = EMU_DEVICE_PALM_M515; + osVersion = "palmos41-en-m515"; + } + } } -void retro_init(void){ - enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565; - - if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) - log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); -} +void retro_init(void) { + enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565; -void retro_deinit(void){ - + if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) + log_cb(RETRO_LOG_INFO, + "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); } -unsigned retro_api_version(void){ - return RETRO_API_VERSION; -} +void retro_deinit(void) {} + +unsigned retro_api_version(void) { return RETRO_API_VERSION; } -void retro_set_controller_port_device(unsigned port, unsigned device){ - (void)port; - (void)device; +void retro_set_controller_port_device(unsigned port, unsigned device) { + (void)port; + (void)device; } -void retro_get_system_info(struct retro_system_info *info){ - memset(info, 0, sizeof(*info)); - info->library_name = "Mu"; +void retro_get_system_info(struct retro_system_info *info) { + memset(info, 0, sizeof(*info)); + info->library_name = "Mu"; #ifndef GIT_VERSION #define GIT_VERSION "" #endif - info->library_version = "v1.3.1" GIT_VERSION; - info->need_fullpath = true; - info->valid_extensions = "prc|pqa|img|pdb|zip"; + info->library_version = "v1.3.1" GIT_VERSION; + info->need_fullpath = true; + info->valid_extensions = "prc|pqa|img|pdb|zip"; - // Prevent RetroArch from looking within ZIP files, so we can grab all - // the PRCs and PDBs accordingly as a single group - info->block_extract = true; + // Prevent RetroArch from looking within ZIP files, so we can grab all + // the PRCs and PDBs accordingly as a single group + info->block_extract = true; } -void retro_get_system_av_info(struct retro_system_av_info *info){ - info->timing.fps = EMU_FPS; - info->timing.sample_rate = AUDIO_SAMPLE_RATE; +void retro_get_system_av_info(struct retro_system_av_info *info) { + info->timing.fps = EMU_FPS; + info->timing.sample_rate = AUDIO_SAMPLE_RATE; - info->geometry.base_width = 160; - info->geometry.base_height = 220; + info->geometry.base_width = 160; + info->geometry.base_height = 220; #if defined(EMU_SUPPORT_PALM_OS5) - info->geometry.max_width = 320; - info->geometry.max_height = 480; + info->geometry.max_width = 320; + info->geometry.max_height = 480; #else - info->geometry.max_width = 160; - info->geometry.max_height = 220; + info->geometry.max_width = 160; + info->geometry.max_height = 220; #endif - info->geometry.aspect_ratio = 160.0 / 220.0; -} - -void retro_set_environment(retro_environment_t cb){ - struct retro_log_callback logging; - struct retro_vfs_interface_info vfs_getter = { 1, NULL }; - struct retro_led_interface led_getter; - struct retro_variable vars[] = { - { "palm_emu_cpu_speed", "CPU Speed; 1.0|1.5|2.0|2.5|3.0|0.5" }, - { "palm_emu_feature_synced_rtc", "Force Match System Clock; disabled|enabled" }, - { "palm_emu_feature_durable", "Ignore Invalid Behavior; disabled|enabled" }, - { "palm_emu_use_joystick_as_mouse", "Use Left Joystick As Mouse; disabled|enabled" }, - { "palm_emu_disable_graffiti", "Disable Graffiti Area; disabled|enabled" }, + info->geometry.aspect_ratio = 160.0 / 220.0; +} + +void retro_set_environment(retro_environment_t cb) { + struct retro_log_callback logging; + struct retro_vfs_interface_info vfs_getter = {1, NULL}; + struct retro_led_interface led_getter; + struct retro_variable vars[] = { + {"palm_emu_cpu_speed", "CPU Speed; 1.0|1.5|2.0|2.5|3.0|0.5"}, + {"palm_emu_feature_synced_rtc", + "Force Match System Clock; disabled|enabled"}, + {"palm_emu_feature_durable", "Ignore Invalid Behavior; disabled|enabled"}, + {"palm_emu_use_joystick_as_mouse", + "Use Left Joystick As Mouse; disabled|enabled"}, + {"palm_emu_disable_graffiti", "Disable Graffiti Area; disabled|enabled"}, #if defined(EMU_SUPPORT_PALM_OS5) - { "palm_emu_os_version", "OS Version; Palm m515/Palm OS 4.1|Tungsten T3/Palm OS 5.2.1|Tungsten T3/Palm OS 6.0|Palm m500/Palm OS 4.0" }, + {"palm_emu_os_version", + "OS Version; Palm m515/Palm OS 4.1|Tungsten T3/Palm OS 5.2.1|Tungsten " + "T3/Palm OS 6.0|Palm m500/Palm OS 4.0"}, #else - { "palm_emu_os_version", "OS Version; Palm m515/Palm OS 4.1|Palm m500/Palm OS 4.0" }, + {"palm_emu_os_version", + "OS Version; Palm m515/Palm OS 4.1|Palm m500/Palm OS 4.0"}, #endif - { 0 } - }; - struct retro_input_descriptor input_desc[] = { - { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Touchscreen Mouse X" }, - { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Touchscreen Mouse Y" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Touchscreen Mouse Click" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Dpad Up" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Dpad Down" }, + {0}}; + struct retro_input_descriptor input_desc[] = { + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, + RETRO_DEVICE_ID_ANALOG_X, "Touchscreen Mouse X"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, + RETRO_DEVICE_ID_ANALOG_Y, "Touchscreen Mouse Y"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, + "Touchscreen Mouse Click"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Dpad Up"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Dpad Down"}, #if defined(EMU_SUPPORT_PALM_OS5) - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Dpad Left" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Dpad Right" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Dpad Center" }, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Dpad Left"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Dpad Right"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Dpad Center"}, #endif - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Power" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Date Book" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Address Book" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "To Do List" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Note Pad" }, - { 0 } - }; - bool no_rom = true; - - environ_cb = cb; - - environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom); - - if(environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging) && logging.log) - log_cb = logging.log; - - if(!log_cb) - log_cb = fallback_log; - - led_getter.set_led_state = NULL; - if(environ_cb(RETRO_ENVIRONMENT_GET_LED_INTERFACE, &led_getter) && led_getter.set_led_state) - led_cb = led_getter.set_led_state; - - if(environ_cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs_getter) && vfs_getter.iface) - filestream_vfs_init(&vfs_getter); - - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, vars); - environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, input_desc); -} + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Power"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Date Book"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Address Book"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "To Do List"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Note Pad"}, + {0}}; + bool no_rom = true; -void retro_set_audio_sample(retro_audio_sample_t cb){ - -} + environ_cb = cb; -void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb){ - audio_cb = cb; -} + environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom); -void retro_set_input_poll(retro_input_poll_t cb){ - input_poll_cb = cb; -} + if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging) && logging.log) + log_cb = logging.log; -void retro_set_input_state(retro_input_state_t cb){ - input_state_cb = cb; -} + if (!log_cb) + log_cb = fallback_log; + + led_getter.set_led_state = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_LED_INTERFACE, &led_getter) && + led_getter.set_led_state) + led_cb = led_getter.set_led_state; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs_getter) && + vfs_getter.iface) + filestream_vfs_init(&vfs_getter); -void retro_set_video_refresh(retro_video_refresh_t cb){ - video_cb = cb; + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, vars); + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, input_desc); } -void retro_reset(void){ - emulatorSoftReset(); +void retro_set_audio_sample(retro_audio_sample_t cb) {} + +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { + audio_cb = cb; } -void retro_run(void){ - input_poll_cb(); - - //some RetroArch functions can only be called from this function so call those if needed - if(unlikely(firstRetroRunCall)){ - struct retro_game_geometry geometry; +void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; } + +void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; } + +void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } + +void retro_reset(void) { emulatorSoftReset(); } + +void retro_run(void) { + input_poll_cb(); + + // some RetroArch functions can only be called from this function so call + // those if needed + if (unlikely(firstRetroRunCall)) { + struct retro_game_geometry geometry; #if defined(EMU_SUPPORT_PALM_OS5) - if(deviceModel == EMU_DEVICE_TUNGSTEN_T3){ - if(dontRenderGraffiti){ - geometry.base_width = 320; - geometry.base_height = 320; - geometry.max_width = 320; - geometry.max_height = 480; - } - else{ - geometry.base_width = 320; - geometry.base_height = 480; - } + if (deviceModel == EMU_DEVICE_TUNGSTEN_T3) { + if (dontRenderGraffiti) { + geometry.base_width = 320; + geometry.base_height = 320; + geometry.max_width = 320; + geometry.max_height = 480; + } else { + geometry.base_width = 320; + geometry.base_height = 480; } - else{ + } else { #endif - if(dontRenderGraffiti){ - geometry.base_width = 160; - geometry.base_height = 160; - } - else{ - geometry.base_width = 160; - geometry.base_height = 220; - } -#if defined(EMU_SUPPORT_PALM_OS5) + if (dontRenderGraffiti) { + geometry.base_width = 160; + geometry.base_height = 160; + } else { + geometry.base_width = 160; + geometry.base_height = 220; } +#if defined(EMU_SUPPORT_PALM_OS5) + } #endif - geometry.aspect_ratio = (float)geometry.base_width / (float)geometry.base_height; - environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &geometry); - firstRetroRunCall = false; - } - - //touchscreen - if(useJoystickAsMouse){ - int16_t x = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X); - int16_t y = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y); - - if(x < -JOYSTICK_DEADZONE || x > JOYSTICK_DEADZONE) - touchCursorX += x * JOYSTICK_MULTIPLIER * (SCREEN_HIRES ? 2.0 : 1.0); - - if(y < -JOYSTICK_DEADZONE || y > JOYSTICK_DEADZONE) - touchCursorY += y * JOYSTICK_MULTIPLIER * (SCREEN_HIRES ? 2.0 : 1.0); - - if(touchCursorX < 0) - touchCursorX = 0; - else if(touchCursorX > palmFramebufferWidth - 1) - touchCursorX = palmFramebufferWidth - 1; - - if(touchCursorY < 0) - touchCursorY = 0; - else if(touchCursorY > palmFramebufferHeight - 1) - touchCursorY = palmFramebufferHeight - 1; - - palmInput.touchscreenX = touchCursorX / (palmFramebufferWidth - 1); - palmInput.touchscreenY = touchCursorY / (palmFramebufferHeight - 1); - palmInput.touchscreenTouched = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R); - } - else{ - //use RetroArch internal pointer - palmInput.touchscreenX = ((float)input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) / 0x7FFF + 1.0) / 2.0; - palmInput.touchscreenY = ((float)input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) / 0x7FFF + 1.0) / 2.0 * ((float)screenYEnd / palmFramebufferHeight); - palmInput.touchscreenTouched = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED); - } - - //dpad - palmInput.buttonUp = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP); - palmInput.buttonDown = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN); + geometry.aspect_ratio = + (float)geometry.base_width / (float)geometry.base_height; + environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &geometry); + firstRetroRunCall = false; + } + + // touchscreen + if (useJoystickAsMouse) { + int16_t x = + input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, + RETRO_DEVICE_ID_ANALOG_X); + int16_t y = + input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, + RETRO_DEVICE_ID_ANALOG_Y); + + if (x < -JOYSTICK_DEADZONE || x > JOYSTICK_DEADZONE) + touchCursorX += x * JOYSTICK_MULTIPLIER * (SCREEN_HIRES ? 2.0 : 1.0); + + if (y < -JOYSTICK_DEADZONE || y > JOYSTICK_DEADZONE) + touchCursorY += y * JOYSTICK_MULTIPLIER * (SCREEN_HIRES ? 2.0 : 1.0); + + if (touchCursorX < 0) + touchCursorX = 0; + else if (touchCursorX > palmFramebufferWidth - 1) + touchCursorX = palmFramebufferWidth - 1; + + if (touchCursorY < 0) + touchCursorY = 0; + else if (touchCursorY > palmFramebufferHeight - 1) + touchCursorY = palmFramebufferHeight - 1; + + palmInput.touchscreenX = touchCursorX / (palmFramebufferWidth - 1); + palmInput.touchscreenY = touchCursorY / (palmFramebufferHeight - 1); + palmInput.touchscreenTouched = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R); + } else { + // use RetroArch internal pointer + palmInput.touchscreenX = ((float)input_state_cb(0, RETRO_DEVICE_POINTER, 0, + RETRO_DEVICE_ID_POINTER_X) / + 0x7FFF + + 1.0) / + 2.0; + palmInput.touchscreenY = ((float)input_state_cb(0, RETRO_DEVICE_POINTER, 0, + RETRO_DEVICE_ID_POINTER_Y) / + 0x7FFF + + 1.0) / + 2.0 * ((float)screenYEnd / palmFramebufferHeight); + palmInput.touchscreenTouched = input_state_cb( + 0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED); + } + + // dpad + palmInput.buttonUp = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP); + palmInput.buttonDown = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN); #if defined(EMU_SUPPORT_PALM_OS5) - if(deviceModel == EMU_DEVICE_TUNGSTEN_T3){ - palmInput.buttonLeft = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT); - palmInput.buttonRight = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT); - palmInput.buttonCenter = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT); - } + if (deviceModel == EMU_DEVICE_TUNGSTEN_T3) { + palmInput.buttonLeft = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT); + palmInput.buttonRight = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT); + palmInput.buttonCenter = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, + RETRO_DEVICE_ID_JOYPAD_SELECT); + } #endif - - //app buttons - palmInput.buttonCalendar = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y); - palmInput.buttonAddress = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X); - palmInput.buttonTodo = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B); - palmInput.buttonNotes = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A); - - //special buttons - palmInput.buttonPower = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START); - - //run emulator - emulatorRunFrame(); - - //draw mouse - if(useJoystickAsMouse) - renderMouseCursor(touchCursorX, touchCursorY); - - video_cb(palmFramebuffer, palmFramebufferWidth, screenYEnd, palmFramebufferWidth * sizeof(uint16_t)); - audio_cb(palmAudio, AUDIO_SAMPLES_PER_FRAME); - if(led_cb){ - led_cb(0, palmMisc.greenLed); + + // app buttons + palmInput.buttonCalendar = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y); + palmInput.buttonAddress = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X); + palmInput.buttonTodo = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B); + palmInput.buttonNotes = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A); + + // special buttons + palmInput.buttonPower = + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START); + + // run emulator + emulatorRunFrame(); + + // draw mouse + if (useJoystickAsMouse) + renderMouseCursor(touchCursorX, touchCursorY); + + video_cb(palmFramebuffer, palmFramebufferWidth, screenYEnd, + palmFramebufferWidth * sizeof(uint16_t)); + audio_cb(palmAudio, AUDIO_SAMPLES_PER_FRAME); + if (led_cb) { + led_cb(0, palmMisc.greenLed); #if defined(EMU_SUPPORT_PALM_OS5) - led_cb(1, palmMisc.redLed); + led_cb(1, palmMisc.redLed); #endif - } - - //repair damage done to the framebuffer by the mouse cursor - if(useJoystickAsMouse) - unrenderMouseCursor(touchCursorX, touchCursorY); + } + + // repair damage done to the framebuffer by the mouse cursor + if (useJoystickAsMouse) + unrenderMouseCursor(touchCursorX, touchCursorY); } /** @@ -441,425 +469,413 @@ void retro_run(void){ * @since 2022/10/02 */ bool loadContentFileNonSRAM(uint32_t *error, uint8_t *contentData, - uint32_t contentSize) { - mz_zip_archive zipArchive; - mz_zip_archive_file_stat stat; - uint32_t appId = 0, maybeAppId, newError; - uint32_t numFiles, index, lookStage; - uint32_t fileNameLen; - void* entryBuf; - - // Detect if this is a ZIP file, if it is - memset(&zipArchive, 0, sizeof(zipArchive)); - if (mz_zip_reader_init_mem(&zipArchive, - contentData, contentSize, - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY | - MZ_ZIP_FLAG_ASCII_FILENAME)) - { - // Notice - log_cb(RETRO_LOG_INFO, "Loading from ZIP...\n"); - - // Process every file in the ZIP looking for PDBs, then PRCs - numFiles = mz_zip_reader_get_num_files(&zipArchive); - for (lookStage = 0; lookStage < 2; lookStage++) - for (index = 0; index < numFiles; index++) - { - // If we are failing then just fail here - if ((*error) != EMU_ERROR_NONE) - { - lookStage = 9999; - index = numFiles; - break; - } - - // Get file information, only care about valid ones - memset(&stat, 0, sizeof(stat)); - if (!mz_zip_reader_file_stat(&zipArchive, - index, &stat)) - continue; - - // Ignore directories and anything MiniZ does not support - if (!stat.m_is_supported || stat.m_is_directory) - continue; - - // How long is the file name? - fileNameLen = strlen(stat.m_filename); - - // Too short? - if (fileNameLen < 4) - continue; - - // Not a PDB or PRC? - if (0 != strcasecmp((lookStage == 0 ? ".pdb" : ".prc"), - &stat.m_filename[fileNameLen - 4])) - continue; - - // Allocate buffer for the data - entryBuf = malloc(stat.m_uncomp_size); - if (entryBuf == NULL) - return false; - - // Load in data - memset(entryBuf, 0, stat.m_uncomp_size); - if (mz_zip_reader_extract_to_mem_no_alloc(&zipArchive, - index, entryBuf, stat.m_uncomp_size, - 0, NULL, 0)) - { - // Notice - log_cb(RETRO_LOG_INFO, "Installing from ZIP: %s\n", - stat.m_filename); - - // Install the file - newError = launcherInstallFile(entryBuf, - stat.m_uncomp_size); - - // Fill in error state - if (newError != EMU_ERROR_NONE) - (*error) = newError; - - // If we are loading a PRC, get the appId of it so that we - // can launch it accordingly - if (lookStage == 1) - { - maybeAppId = launcherGetAppId(entryBuf, - stat.m_uncomp_size); - if (maybeAppId != 0) - appId = maybeAppId; - } - } - - // Clear allocated data - free(entryBuf); - } - - // Stop reading the ZIP - mz_zip_end(&zipArchive); - } - - // Otherwise, not a ZIP at all... load it directly - else - { - // Notice - log_cb(RETRO_LOG_INFO, "Loading single PRC/PDB...\n"); - - // Install the file - (*error) = launcherInstallFile(contentData, contentSize); - - // Get the app ID to launch - appId = launcherGetAppId(contentData, contentSize); - } - - // Notice - log_cb(RETRO_LOG_INFO, "Completed load!\n"); - - // Try to the launch the app, if it even is one... - if ((*error) == EMU_ERROR_NONE && appId != 0) - (*error) = launcherExecute(appId); -} + uint32_t contentSize) { + mz_zip_archive zipArchive; + mz_zip_archive_file_stat stat; + uint32_t appId = 0, maybeAppId, newError; + uint32_t numFiles, index, lookStage; + uint32_t fileNameLen; + void *entryBuf; + + // Detect if this is a ZIP file, if it is + memset(&zipArchive, 0, sizeof(zipArchive)); + if (mz_zip_reader_init_mem(&zipArchive, contentData, contentSize, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY | + MZ_ZIP_FLAG_ASCII_FILENAME)) { + // Notice + log_cb(RETRO_LOG_INFO, "Loading from ZIP...\n"); + + // Process every file in the ZIP looking for PDBs, then PRCs + numFiles = mz_zip_reader_get_num_files(&zipArchive); + for (lookStage = 0; lookStage < 2; lookStage++) + for (index = 0; index < numFiles; index++) { + // If we are failing then just fail here + if ((*error) != EMU_ERROR_NONE) { + lookStage = 9999; + index = numFiles; + break; + } + + // Get file information, only care about valid ones + memset(&stat, 0, sizeof(stat)); + if (!mz_zip_reader_file_stat(&zipArchive, index, &stat)) + continue; + + // Ignore directories and anything MiniZ does not support + if (!stat.m_is_supported || stat.m_is_directory) + continue; + + // How long is the file name? + fileNameLen = strlen(stat.m_filename); + + // Too short? + if (fileNameLen < 4) + continue; + + // Not a PDB or PRC? + if (0 != strcasecmp((lookStage == 0 ? ".pdb" : ".prc"), + &stat.m_filename[fileNameLen - 4])) + continue; + + // Allocate buffer for the data + entryBuf = malloc(stat.m_uncomp_size); + if (entryBuf == NULL) + return false; + + // Load in data + memset(entryBuf, 0, stat.m_uncomp_size); + if (mz_zip_reader_extract_to_mem_no_alloc( + &zipArchive, index, entryBuf, stat.m_uncomp_size, 0, NULL, 0)) { + // Notice + log_cb(RETRO_LOG_INFO, "Installing from ZIP: %s\n", stat.m_filename); + + // Install the file + newError = launcherInstallFile(entryBuf, stat.m_uncomp_size); + + // Fill in error state + if (newError != EMU_ERROR_NONE) + (*error) = newError; + + // If we are loading a PRC, get the appId of it so that we + // can launch it accordingly + if (lookStage == 1) { + maybeAppId = launcherGetAppId(entryBuf, stat.m_uncomp_size); + if (maybeAppId != 0) + appId = maybeAppId; + } + } + + // Clear allocated data + free(entryBuf); + } + + // Stop reading the ZIP + mz_zip_end(&zipArchive); + } + + // Otherwise, not a ZIP at all... load it directly + else { + // Notice + log_cb(RETRO_LOG_INFO, "Loading single PRC/PDB...\n"); + + // Install the file + (*error) = launcherInstallFile(contentData, contentSize); + + // Get the app ID to launch + appId = launcherGetAppId(contentData, contentSize); + } -bool loadContentFile(bool hasSram, uint32_t* error) { - struct RFILE *contentFile; - uint8_t *contentData; - uint32_t contentSize; - - contentFile = filestream_open(contentPath, RETRO_VFS_FILE_ACCESS_READ, - RETRO_VFS_FILE_ACCESS_HINT_NONE); - if (contentFile) { - contentSize = filestream_get_size(contentFile); - contentData = malloc(contentSize); - - if (contentData) - filestream_read(contentFile, contentData, contentSize); - else - return false; - filestream_close(contentFile); - } else { - //no content at path, fail time - return false; - } - - launcherBootInstantly(hasSram); - - if (runningImgFile) { - char infoPath[PATH_MAX_LENGTH]; - struct RFILE *infoFile; - uint8_t *infoData = NULL; - uint32_t infoSize = 0; - sd_card_info_t sdInfo; - - memset(&sdInfo, 0x00, sizeof(sdInfo)); - - strlcpy(infoPath, contentPath, PATH_MAX_LENGTH); - infoPath[strlen(infoPath) - 4] = '\0';//chop off ".img" - strlcat(infoPath, ".info", PATH_MAX_LENGTH); - infoFile = filestream_open(infoPath, RETRO_VFS_FILE_ACCESS_READ, - RETRO_VFS_FILE_ACCESS_HINT_NONE); - if (infoFile) { - infoSize = filestream_get_size(infoFile); - infoData = malloc(infoSize); - - if (infoData) - filestream_read(infoFile, infoData, infoSize); - - filestream_close(infoFile); - } - - if (infoData) - launcherGetSdCardInfoFromInfoFile(infoData, infoSize, &sdInfo); - (*error) = emulatorInsertSdCard(contentData, contentSize, - infoData ? &sdInfo : NULL); - if (infoData) - free(infoData); - } else { - if (!hasSram) - loadContentFileNonSRAM(error, contentData, contentSize); - } - - free(contentData); - if ((*error) != EMU_ERROR_NONE) - return false; - - return true; + // Notice + log_cb(RETRO_LOG_INFO, "Completed load!\n"); + + // Try to the launch the app, if it even is one... + if ((*error) == EMU_ERROR_NONE && appId != 0) + (*error) = launcherExecute(appId); } -bool retro_load_game(const struct retro_game_info *info){ - uint8_t* romData; - uint32_t romSize; - uint8_t* bootloaderData; - uint32_t bootloaderSize; - char romPath[PATH_MAX_LENGTH]; - char bootloaderPath[PATH_MAX_LENGTH]; - char saveRamPath[PATH_MAX_LENGTH]; - char sdImgPath[PATH_MAX_LENGTH]; - struct RFILE* romFile; - struct RFILE* bootloaderFile; - struct RFILE* saveRamFile; - struct RFILE* sdImgFile; - const char* systemDir; - time_t rawTime; - struct tm* timeInfo; - bool hasSram = false; - uint32_t error; - - //updates the emulator configuration - check_variables(true); - - environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemDir); - - if(info && !string_is_empty(info->path)){ - //boot application - strlcpy(contentPath, info->path, PATH_MAX_LENGTH); - runningImgFile = string_is_equal_case_insensitive(contentPath + strlen(contentPath) - 4, ".img"); - } - else{ - //boot standard device image - strlcpy(contentPath, systemDir, PATH_MAX_LENGTH); - strlcat(contentPath, "/default", PATH_MAX_LENGTH); - runningImgFile = false; - } - - //ROM - strlcpy(romPath, systemDir, PATH_MAX_LENGTH); - strlcat(romPath, "/", PATH_MAX_LENGTH); - strlcat(romPath, osVersion, PATH_MAX_LENGTH); - strlcat(romPath, ".rom", PATH_MAX_LENGTH); - romFile = filestream_open(romPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(romFile){ - romSize = filestream_get_size(romFile); - romData = malloc(romSize); - - if(romData) - filestream_read(romFile, romData, romSize); - else - romSize = 0; - filestream_close(romFile); - } - else{ - //cant load without ROM +bool loadContentFile(bool hasSram, uint32_t *error) { + struct RFILE *contentFile; + uint8_t *contentData; + uint32_t contentSize; + + contentFile = filestream_open(contentPath, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (contentFile) { + contentSize = filestream_get_size(contentFile); + contentData = malloc(contentSize); + + if (contentData) + filestream_read(contentFile, contentData, contentSize); + else return false; - } - - //bootloader, will simply be ignored for Tungsten T3 - strlcpy(bootloaderPath, systemDir, PATH_MAX_LENGTH); - strlcat(bootloaderPath, "/bootloader-dbvz.rom", PATH_MAX_LENGTH); - bootloaderFile = filestream_open(bootloaderPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(bootloaderFile){ - bootloaderSize = filestream_get_size(bootloaderFile); - bootloaderData = malloc(bootloaderSize); - - if(bootloaderData) - filestream_read(bootloaderFile, bootloaderData, bootloaderSize); - else - bootloaderSize = 0; - filestream_close(bootloaderFile); - } - else{ - bootloaderData = NULL; + filestream_close(contentFile); + } else { + // no content at path, fail time + return false; + } + + launcherBootInstantly(hasSram); + + if (runningImgFile) { + char infoPath[PATH_MAX_LENGTH]; + struct RFILE *infoFile; + uint8_t *infoData = NULL; + uint32_t infoSize = 0; + sd_card_info_t sdInfo; + + memset(&sdInfo, 0x00, sizeof(sdInfo)); + + strlcpy(infoPath, contentPath, PATH_MAX_LENGTH); + infoPath[strlen(infoPath) - 4] = '\0'; // chop off ".img" + strlcat(infoPath, ".info", PATH_MAX_LENGTH); + infoFile = filestream_open(infoPath, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (infoFile) { + infoSize = filestream_get_size(infoFile); + infoData = malloc(infoSize); + + if (infoData) + filestream_read(infoFile, infoData, infoSize); + + filestream_close(infoFile); + } + + if (infoData) + launcherGetSdCardInfoFromInfoFile(infoData, infoSize, &sdInfo); + (*error) = emulatorInsertSdCard(contentData, contentSize, + infoData ? &sdInfo : NULL); + if (infoData) + free(infoData); + } else { + if (!hasSram) + loadContentFileNonSRAM(error, contentData, contentSize); + } + + free(contentData); + if ((*error) != EMU_ERROR_NONE) + return false; + + return true; +} + +bool retro_load_game(const struct retro_game_info *info) { + uint8_t *romData; + uint32_t romSize; + uint8_t *bootloaderData; + uint32_t bootloaderSize; + char romPath[PATH_MAX_LENGTH]; + char bootloaderPath[PATH_MAX_LENGTH]; + char saveRamPath[PATH_MAX_LENGTH]; + char sdImgPath[PATH_MAX_LENGTH]; + struct RFILE *romFile; + struct RFILE *bootloaderFile; + struct RFILE *saveRamFile; + struct RFILE *sdImgFile; + const char *systemDir; + time_t rawTime; + struct tm *timeInfo; + bool hasSram = false; + uint32_t error; + + // updates the emulator configuration + check_variables(true); + + environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemDir); + + if (info && !string_is_empty(info->path)) { + // boot application + strlcpy(contentPath, info->path, PATH_MAX_LENGTH); + runningImgFile = string_is_equal_case_insensitive( + contentPath + strlen(contentPath) - 4, ".img"); + } else { + // boot standard device image + strlcpy(contentPath, systemDir, PATH_MAX_LENGTH); + strlcat(contentPath, "/default", PATH_MAX_LENGTH); + runningImgFile = false; + } + + // ROM + strlcpy(romPath, systemDir, PATH_MAX_LENGTH); + strlcat(romPath, "/", PATH_MAX_LENGTH); + strlcat(romPath, osVersion, PATH_MAX_LENGTH); + strlcat(romPath, ".rom", PATH_MAX_LENGTH); + romFile = filestream_open(romPath, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (romFile) { + romSize = filestream_get_size(romFile); + romData = malloc(romSize); + + if (romData) + filestream_read(romFile, romData, romSize); + else + romSize = 0; + filestream_close(romFile); + } else { + // cant load without ROM + return false; + } + + // bootloader, will simply be ignored for Tungsten T3 + strlcpy(bootloaderPath, systemDir, PATH_MAX_LENGTH); + strlcat(bootloaderPath, "/bootloader-dbvz.rom", PATH_MAX_LENGTH); + bootloaderFile = filestream_open(bootloaderPath, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (bootloaderFile) { + bootloaderSize = filestream_get_size(bootloaderFile); + bootloaderData = malloc(bootloaderSize); + + if (bootloaderData) + filestream_read(bootloaderFile, bootloaderData, bootloaderSize); + else bootloaderSize = 0; - } - - error = emulatorInit(deviceModel, romData, romSize, bootloaderData, bootloaderSize, syncRtc, allowInvalidBehavior); - free(romData); - if(bootloaderData) - free(bootloaderData); - - if(error != EMU_ERROR_NONE) + filestream_close(bootloaderFile); + } else { + bootloaderData = NULL; + bootloaderSize = 0; + } + + error = emulatorInit(deviceModel, romData, romSize, bootloaderData, + bootloaderSize, syncRtc, allowInvalidBehavior, NULL); + free(romData); + if (bootloaderData) + free(bootloaderData); + + if (error != EMU_ERROR_NONE) + return false; + + // save RAM + strlcpy(saveRamPath, contentPath, PATH_MAX_LENGTH); + strlcat(saveRamPath, "-", PATH_MAX_LENGTH); + strlcat(saveRamPath, osVersion, PATH_MAX_LENGTH); + strlcat(saveRamPath, ".ram", PATH_MAX_LENGTH); + saveRamFile = filestream_open(saveRamPath, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + + // There is now always SRAM because it gets initialized to garbage + hasSram = true; + + if (saveRamFile) { + if (filestream_get_size(saveRamFile) == emulatorGetRamSize()) { + filestream_read(saveRamFile, palmRam, emulatorGetRamSize()); + swap16BufferIfLittle(palmRam, emulatorGetRamSize() / sizeof(uint16_t)); + } + + filestream_close(saveRamFile); + } + + if (!runningImgFile) { + // SD card + strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH); + strlcat(sdImgPath, "-", PATH_MAX_LENGTH); + strlcat(sdImgPath, osVersion, PATH_MAX_LENGTH); + strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH); + sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (sdImgFile) { + uint32_t sdImgSize = filestream_get_size(sdImgFile); + + // use the NULL, size, NULL method because it takes less RAM + + error = emulatorInsertSdCard(NULL, sdImgSize, NULL); + if (error == EMU_ERROR_NONE) + filestream_read(sdImgFile, palmSdCard.flashChipData, sdImgSize); + + filestream_close(sdImgFile); + } + } + + // set RTC + time(&rawTime); + timeInfo = localtime(&rawTime); + emulatorSetRtc(timeInfo->tm_yday, timeInfo->tm_hour, timeInfo->tm_min, + timeInfo->tm_sec); + + // see if RetroArch wants something launched + if (info && !string_is_empty(info->path)) { + if (!loadContentFile(hasSram, &error)) { return false; - - //save RAM - strlcpy(saveRamPath, contentPath, PATH_MAX_LENGTH); - strlcat(saveRamPath, "-", PATH_MAX_LENGTH); - strlcat(saveRamPath, osVersion, PATH_MAX_LENGTH); - strlcat(saveRamPath, ".ram", PATH_MAX_LENGTH); - saveRamFile = filestream_open(saveRamPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - - // There is now always SRAM because it gets initialized to garbage - hasSram = true; - - if(saveRamFile) { - if(filestream_get_size(saveRamFile) == emulatorGetRamSize()){ - filestream_read(saveRamFile, palmRam, emulatorGetRamSize()); - swap16BufferIfLittle(palmRam, emulatorGetRamSize() / sizeof(uint16_t)); - } + } + } + + // set the time callback + palmGetRtcFromHost = frontendGetCurrentTime; - filestream_close(saveRamFile); - } - - if(!runningImgFile){ - //SD card + // set mouse position + touchCursorX = palmFramebufferWidth / 2; + touchCursorY = palmFramebufferHeight / 2; + + // make touches land on the correct spot and screen render the correct size + // when the graffiti area is off + if (dontRenderGraffiti) { +#if defined(EMU_SUPPORT_PALM_OS5) + if (deviceModel == EMU_DEVICE_TUNGSTEN_T3) + screenYEnd = 320; + else +#endif + screenYEnd = 160; + } else { + screenYEnd = palmFramebufferHeight; + } + + // used to resize things properly + firstRetroRunCall = true; + + // set default CPU speed + emulatorSetCpuSpeed(cpuSpeed); + + return true; +} + +void retro_unload_game(void) { + char saveRamPath[PATH_MAX_LENGTH]; + char sdImgPath[PATH_MAX_LENGTH]; + struct RFILE *saveRamFile; + struct RFILE *sdImgFile; + + // save RAM + strlcpy(saveRamPath, contentPath, PATH_MAX_LENGTH); + strlcat(saveRamPath, "-", PATH_MAX_LENGTH); + strlcat(saveRamPath, osVersion, PATH_MAX_LENGTH); + strlcat(saveRamPath, ".ram", PATH_MAX_LENGTH); + saveRamFile = filestream_open(saveRamPath, RETRO_VFS_FILE_ACCESS_WRITE, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (saveRamFile) { + swap16BufferIfLittle( + palmRam, emulatorGetRamSize() / + sizeof(uint16_t)); // this will no longer be used, so its + // ok to destroy it when swapping + filestream_write(saveRamFile, palmRam, emulatorGetRamSize()); + filestream_close(saveRamFile); + } + + if (!runningImgFile) { + // SD card + if (palmSdCard.flashChipData) { strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH); strlcat(sdImgPath, "-", PATH_MAX_LENGTH); strlcat(sdImgPath, osVersion, PATH_MAX_LENGTH); strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH); - sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(sdImgFile){ - uint32_t sdImgSize = filestream_get_size(sdImgFile); - - //use the NULL, size, NULL method because it takes less RAM - - error = emulatorInsertSdCard(NULL, sdImgSize, NULL); - if(error == EMU_ERROR_NONE) - filestream_read(sdImgFile, palmSdCard.flashChipData, sdImgSize); - - filestream_close(sdImgFile); + sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_WRITE, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + if (sdImgFile) { + filestream_write(sdImgFile, palmSdCard.flashChipData, + palmSdCard.flashChipSize); + filestream_close(sdImgFile); } - } - - //set RTC - time(&rawTime); - timeInfo = localtime(&rawTime); - emulatorSetRtc(timeInfo->tm_yday, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec); - - //see if RetroArch wants something launched - if(info && !string_is_empty(info->path)) { - if (!loadContentFile(hasSram, &error)) { - return false; - } - } - - //set the time callback - palmGetRtcFromHost = frontendGetCurrentTime; - - //set mouse position - touchCursorX = palmFramebufferWidth / 2; - touchCursorY = palmFramebufferHeight / 2; - - //make touches land on the correct spot and screen render the correct size when the graffiti area is off - if(dontRenderGraffiti){ -#if defined(EMU_SUPPORT_PALM_OS5) - if(deviceModel == EMU_DEVICE_TUNGSTEN_T3) - screenYEnd = 320; - else -#endif - screenYEnd = 160; - } - else{ - screenYEnd = palmFramebufferHeight; - } - - //used to resize things properly - firstRetroRunCall = true; - - //set default CPU speed - emulatorSetCpuSpeed(cpuSpeed); - - return true; -} + } + } -void retro_unload_game(void){ - char saveRamPath[PATH_MAX_LENGTH]; - char sdImgPath[PATH_MAX_LENGTH]; - struct RFILE* saveRamFile; - struct RFILE* sdImgFile; - - //save RAM - strlcpy(saveRamPath, contentPath, PATH_MAX_LENGTH); - strlcat(saveRamPath, "-", PATH_MAX_LENGTH); - strlcat(saveRamPath, osVersion, PATH_MAX_LENGTH); - strlcat(saveRamPath, ".ram", PATH_MAX_LENGTH); - saveRamFile = filestream_open(saveRamPath, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(saveRamFile){ - swap16BufferIfLittle(palmRam, emulatorGetRamSize() / sizeof(uint16_t));//this will no longer be used, so its ok to destroy it when swapping - filestream_write(saveRamFile, palmRam, emulatorGetRamSize()); - filestream_close(saveRamFile); - } - - if(!runningImgFile){ - //SD card - if(palmSdCard.flashChipData){ - strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH); - strlcat(sdImgPath, "-", PATH_MAX_LENGTH); - strlcat(sdImgPath, osVersion, PATH_MAX_LENGTH); - strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH); - sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(sdImgFile){ - filestream_write(sdImgFile, palmSdCard.flashChipData, palmSdCard.flashChipSize); - filestream_close(sdImgFile); - } - } - } - - emulatorDeinit(); + emulatorDeinit(); } -unsigned retro_get_region(void){ - return RETRO_REGION_NTSC; -} +unsigned retro_get_region(void) { return RETRO_REGION_NTSC; } -bool retro_load_game_special(unsigned type, const struct retro_game_info *info, size_t num){ - (void)type; - (void)info; - (void)num; - return false; +bool retro_load_game_special(unsigned type, const struct retro_game_info *info, + size_t num) { + (void)type; + (void)info; + (void)num; + return false; } -size_t retro_serialize_size(void){ - return emulatorGetStateSize(); -} +size_t retro_serialize_size(void) { return emulatorGetStateSize(); } -bool retro_serialize(void *data, size_t size){ - return emulatorSaveState(data, size); +bool retro_serialize(void *data, size_t size) { + return emulatorSaveState(data, size); } -bool retro_unserialize(const void *data, size_t size){ - return emulatorLoadState(data, size); +bool retro_unserialize(const void *data, size_t size) { + return emulatorLoadState(data, size); } -void* retro_get_memory_data(unsigned id){ - return NULL; -} +void *retro_get_memory_data(unsigned id) { return NULL; } -size_t retro_get_memory_size(unsigned id){ - return 0; -} +size_t retro_get_memory_size(unsigned id) { return 0; } -void retro_cheat_reset(void){ - -} +void retro_cheat_reset(void) {} -void retro_cheat_set(unsigned index, bool enabled, const char *code){ - (void)index; - (void)enabled; - (void)code; +void retro_cheat_set(unsigned index, bool enabled, const char *code) { + (void)index; + (void)enabled; + (void)code; } - diff --git a/qtBuildSystem/Mu/Mu.pro b/qtBuildSystem/Mu/Mu.pro index 7b65aae..a53bd06 100644 --- a/qtBuildSystem/Mu/Mu.pro +++ b/qtBuildSystem/Mu/Mu.pro @@ -221,6 +221,7 @@ SOURCES += \ ../../src/audio/blip_buf.c \ ../../src/dbvz.c \ ../../src/emulator.c \ + ../../src/serial.c \ ../../src/fileLauncher/launcher.c \ ../../src/flx68000.c \ ../../src/m5XXBus.c \ diff --git a/qtBuildSystem/Mu/emuwrapper.cpp b/qtBuildSystem/Mu/emuwrapper.cpp index 3bd80d1..2947e60 100644 --- a/qtBuildSystem/Mu/emuwrapper.cpp +++ b/qtBuildSystem/Mu/emuwrapper.cpp @@ -1,611 +1,632 @@ -#include -#include +#include +#include +#include #include #include #include -#include -#include -#include +#include #include +#include -#include -#include #include -#include -#include +#include #include #include +#include +#include #include #include "emuwrapper.h" #if defined(BUILT_FROM_CMAKE) - #include "emulator.h" - #include "fileLauncher/launcher.h" +#include "emulator.h" +#include "fileLauncher/launcher.h" #else - #include "../../include/emulator.h" - #include "../../include/fileLauncher/launcher.h" +#include "../../include/emulator.h" +#include "../../include/fileLauncher/launcher.h" #endif extern "C" { #if defined(BUILT_FROM_CMAKE) - #include "flx68000.h" - #include "m68k/m68k.h" - #include "pxa260/pxa260.h" - #include "armv5te/disasm.h" +#include "flx68000.h" +#include "m68k/m68k.h" +#include "pxa260/pxa260.h" +#include "armv5te/disasm.h" #else - #include "../../include/flx68000.h" - #include "../../include/m68k/m68k.h" - #include "../../include/pxa260/pxa260.h" - #include "../../include/armv5te/disasm.h" +#include "../../include/flx68000.h" +#include "../../include/m68k/m68k.h" +#include "../../include/pxa260/pxa260.h" +#include "../../include/armv5te/disasm.h" #endif } - #define MAX_LOG_ENTRYS 2000 #define MAX_LOG_ENTRY_LENGTH 200 +static bool alreadyExists = + false; // there can only be one of this class since it wrappers C code -static bool alreadyExists = false;//there can only be one of this class since it wrappers C code - -static QVector debugStrings; -static uint64_t debugDeletedStrings; +static QVector debugStrings; +static uint64_t debugDeletedStrings; static QVector debugDuplicateCallCount; -static bool debugAbort = false; -static QString debugAbortString = ""; -uint32_t frontendDebugStringSize; -char* frontendDebugString; - - -void frontendHandleDebugPrint(){ - QString newDebugString = frontendDebugString; - - //lock out logs to capture a specific section - if(debugAbort) - return; - - if(!debugAbortString.isEmpty() && newDebugString.contains(debugAbortString)) - debugAbort = true; - - //this debug handler doesnt need the \n - if(newDebugString.back() == '\n') - newDebugString.remove(newDebugString.length() - 1, 1); - else - newDebugString.append("MISSING \"\\n\""); - - if(!debugStrings.empty() && newDebugString == debugStrings.back()){ - debugDuplicateCallCount.back()++; - } - else{ - debugStrings.push_back(newDebugString); - debugDuplicateCallCount.push_back(1); - } - - while(debugStrings.size() > MAX_LOG_ENTRYS){ - debugStrings.remove(0); - debugDuplicateCallCount.remove(0); - debugDeletedStrings++; - } +static bool debugAbort = false; +static QString debugAbortString = ""; +uint32_t frontendDebugStringSize; +char *frontendDebugString; + +void frontendHandleDebugPrint() { + QString newDebugString = frontendDebugString; + + // lock out logs to capture a specific section + if (debugAbort) + return; + + if (!debugAbortString.isEmpty() && newDebugString.contains(debugAbortString)) + debugAbort = true; + + // this debug handler doesnt need the \n + if (newDebugString.back() == '\n') + newDebugString.remove(newDebugString.length() - 1, 1); + else + newDebugString.append("MISSING \"\\n\""); + + if (!debugStrings.empty() && newDebugString == debugStrings.back()) { + debugDuplicateCallCount.back()++; + } else { + debugStrings.push_back(newDebugString); + debugDuplicateCallCount.push_back(1); + } + + while (debugStrings.size() > MAX_LOG_ENTRYS) { + debugStrings.remove(0); + debugDuplicateCallCount.remove(0); + debugDeletedStrings++; + } } -static void frontendGetCurrentTime(uint8_t* writeBack){ - time_t rawTime; - struct tm* timeInfo; +static void frontendGetCurrentTime(uint8_t *writeBack) { + time_t rawTime; + struct tm *timeInfo; - time(&rawTime); - timeInfo = localtime(&rawTime); + time(&rawTime); + timeInfo = localtime(&rawTime); - writeBack[0] = timeInfo->tm_hour; - writeBack[1] = timeInfo->tm_min; - writeBack[2] = timeInfo->tm_sec; + writeBack[0] = timeInfo->tm_hour; + writeBack[1] = timeInfo->tm_min; + writeBack[2] = timeInfo->tm_sec; } +EmuWrapper::EmuWrapper() { + if (alreadyExists == true) + throw std::bad_alloc(); + alreadyExists = true; -EmuWrapper::EmuWrapper(){ - if(alreadyExists == true) - throw std::bad_alloc(); - alreadyExists = true; - - emuInited = false; - emuThreadJoin = false; - emuRunning = false; - emuPaused = false; - emuNewFrameReady = false; + emuInited = false; + emuThreadJoin = false; + emuRunning = false; + emuPaused = false; + emuNewFrameReady = false; - frontendDebugString = new char[MAX_LOG_ENTRY_LENGTH]; - frontendDebugStringSize = MAX_LOG_ENTRY_LENGTH; + frontendDebugString = new char[MAX_LOG_ENTRY_LENGTH]; + frontendDebugStringSize = MAX_LOG_ENTRY_LENGTH; } -EmuWrapper::~EmuWrapper(){ - if(emuInited) - exit(); +EmuWrapper::~EmuWrapper() { + if (emuInited) + exit(); - delete[] frontendDebugString; - frontendDebugStringSize = 0; - debugStrings.clear(); - debugDuplicateCallCount.clear(); + delete[] frontendDebugString; + frontendDebugStringSize = 0; + debugStrings.clear(); + debugDuplicateCallCount.clear(); - //allow creating a new emu class after the old one is closed - alreadyExists = false; + // allow creating a new emu class after the old one is closed + alreadyExists = false; } -void EmuWrapper::emuThreadRun(){ - while(!emuThreadJoin){ - if(emuRunning){ - emuPaused = false; - if(!emuNewFrameReady){ - palmInput = emuInput; - emulatorRunFrame(); - emuNewFrameReady = true; - } - } - else{ - emuPaused = true; +void EmuWrapper::emuThreadRun() { + while (!emuThreadJoin) { + if (emuRunning) { + emuPaused = false; + if (!emuNewFrameReady) { + palmInput = emuInput; + emulatorRunFrame(); + emuNewFrameReady = true; } + } else { + emuPaused = true; + } - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - } + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } } -void EmuWrapper::writeOutSaves(){ - if(emuRamFilePath != ""){ - QFile ramFile(emuRamFilePath); - uint32_t emuRamSize = emulatorGetRamSize(); - uint8_t* emuRamData = new uint8_t[emuRamSize]; +void EmuWrapper::writeOutSaves() { + if (emuRamFilePath != "") { + QFile ramFile(emuRamFilePath); + uint32_t emuRamSize = emulatorGetRamSize(); + uint8_t *emuRamData = new uint8_t[emuRamSize]; - emulatorSaveRam(emuRamData, emuRamSize); + emulatorSaveRam(emuRamData, emuRamSize); - //save out RAM before exit - if(ramFile.open(QFile::WriteOnly | QFile::Truncate)){ - ramFile.write((const char*)emuRamData, emuRamSize); - ramFile.close(); - } + // save out RAM before exit + if (ramFile.open(QFile::WriteOnly | QFile::Truncate)) { + ramFile.write((const char *)emuRamData, emuRamSize); + ramFile.close(); + } - delete[] emuRamData; - } - if(emuSdCardFilePath != ""){ - uint32_t emuSdCardSize = emulatorGetSdCardSize(); - uint8_t* emuSdCardData = new uint8_t[emuSdCardSize]; + delete[] emuRamData; + } + if (emuSdCardFilePath != "") { + uint32_t emuSdCardSize = emulatorGetSdCardSize(); + uint8_t *emuSdCardData = new uint8_t[emuSdCardSize]; - if(emulatorGetSdCardData(emuSdCardData, emuSdCardSize) == EMU_ERROR_NONE){ - QFile sdCardFile(emuSdCardFilePath); + if (emulatorGetSdCardData(emuSdCardData, emuSdCardSize) == EMU_ERROR_NONE) { + QFile sdCardFile(emuSdCardFilePath); - //save out SD card before exit - if(sdCardFile.open(QFile::WriteOnly | QFile::Truncate)){ - sdCardFile.write((const char*)emuSdCardData, emuSdCardSize); - sdCardFile.close(); - } + // save out SD card before exit + if (sdCardFile.open(QFile::WriteOnly | QFile::Truncate)) { + sdCardFile.write((const char *)emuSdCardData, emuSdCardSize); + sdCardFile.close(); } - } + } + } } -uint32_t EmuWrapper::init(const QString& assetPath, const QString& osVersion, bool syncRtc, bool allowInvalidBehavior, bool fastBoot){ - if(!emuRunning && !emuInited){ - //start emu - uint32_t error; - uint8_t deviceModel; - bool hasBootloader = true; - - if(osVersion == "Palm m500/Palm OS 4.0") - emuOsName = "palmos40-en-m500"; - else if(osVersion == "Palm m515/Palm OS 4.1") - emuOsName = "palmos41-en-m515"; - else if(osVersion == "Tungsten T3/Palm OS 5.2.1") - emuOsName = "palmos52-en-t3"; - else if(osVersion == "Tungsten T3/Palm OS 5.2.1") - emuOsName = "palmos60-en-t3"; - else - return EMU_ERROR_INVALID_PARAMETER; - - if(osVersion.contains("Palm m500")) - deviceModel = EMU_DEVICE_PALM_M500; - else if(osVersion.contains("Palm m515")) - deviceModel = EMU_DEVICE_PALM_M515; - else if(osVersion.contains("Tungsten T3")) - deviceModel = EMU_DEVICE_TUNGSTEN_T3; - else - return EMU_ERROR_INVALID_PARAMETER; - - QFile romFile(assetPath + "/" + emuOsName + ".rom"); - QFile bootloaderFile(assetPath + "/bootloader-dbvz.rom"); - QFile ramFile(assetPath + "/userdata-" + emuOsName + ".ram"); - QFile sdCardFile(assetPath + "/sd-" + emuOsName + ".img"); - - if(!romFile.open(QFile::ReadOnly | QFile::ExistingOnly)) - return EMU_ERROR_INVALID_PARAMETER; - - if(deviceModel == EMU_DEVICE_TUNGSTEN_T3 || !bootloaderFile.open(QFile::ReadOnly | QFile::ExistingOnly)) - hasBootloader = false; - - error = emulatorInit(deviceModel, (uint8_t*)romFile.readAll().data(), romFile.size(), hasBootloader ? (uint8_t*)bootloaderFile.readAll().data() : NULL, hasBootloader ? bootloaderFile.size() : 0, syncRtc, allowInvalidBehavior); - if(error == EMU_ERROR_NONE){ - QTime now = QTime::currentTime(); - - palmGetRtcFromHost = frontendGetCurrentTime; - emulatorSetRtc(QDate::currentDate().day(), now.hour(), now.minute(), now.second()); - - if(ramFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - emulatorLoadRam((uint8_t*)ramFile.readAll().data(), ramFile.size()); - ramFile.close(); - } - - if(sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - emulatorInsertSdCard((uint8_t*)sdCardFile.readAll().data(), sdCardFile.size(), NULL); - sdCardFile.close(); - } - - emuInput = palmInput; - emuRamFilePath = assetPath + "/userdata-" + emuOsName + ".ram"; - emuSdCardFilePath = assetPath + "/sd-" + emuOsName + ".img"; - emuSaveStatePath = assetPath + "/states-" + emuOsName + ".states"; - - //make the place to store the saves - QDir(emuSaveStatePath).mkdir("."); - - //skip the boot screen - if(fastBoot) - launcherBootInstantly(ramFile.exists()); - - //start the thread - emuThreadJoin = false; - emuInited = true; - emuRunning = true; - emuPaused = false; - emuNewFrameReady = false; - emuThread = std::thread(&EmuWrapper::emuThreadRun, this); +uint32_t EmuWrapper::init(const QString &assetPath, const QString &osVersion, + bool syncRtc, bool allowInvalidBehavior, + bool fastBoot, const QString &serialPortDev) { + if (!emuRunning && !emuInited) { + // start emu + uint32_t error; + uint8_t deviceModel; + bool hasBootloader = true; + + if (osVersion == "Palm m500/Palm OS 4.0") + emuOsName = "palmos40-en-m500"; + else if (osVersion == "Palm m515/Palm OS 4.1") + emuOsName = "palmos41-en-m515"; + else if (osVersion == "Tungsten T3/Palm OS 5.2.1") + emuOsName = "palmos52-en-t3"; + else if (osVersion == "Tungsten T3/Palm OS 5.2.1") + emuOsName = "palmos60-en-t3"; + else + return EMU_ERROR_INVALID_PARAMETER; + + if (osVersion.contains("Palm m500")) + deviceModel = EMU_DEVICE_PALM_M500; + else if (osVersion.contains("Palm m515")) + deviceModel = EMU_DEVICE_PALM_M515; + else if (osVersion.contains("Tungsten T3")) + deviceModel = EMU_DEVICE_TUNGSTEN_T3; + else + return EMU_ERROR_INVALID_PARAMETER; + + QFile romFile(assetPath + "/" + emuOsName + ".rom"); + QFile bootloaderFile(assetPath + "/bootloader-dbvz.rom"); + QFile ramFile(assetPath + "/userdata-" + emuOsName + ".ram"); + QFile sdCardFile(assetPath + "/sd-" + emuOsName + ".img"); + + if (!romFile.open(QFile::ReadOnly | QFile::ExistingOnly)) + return EMU_ERROR_INVALID_PARAMETER; + + if (deviceModel == EMU_DEVICE_TUNGSTEN_T3 || + !bootloaderFile.open(QFile::ReadOnly | QFile::ExistingOnly)) + hasBootloader = false; + + error = emulatorInit( + deviceModel, + (uint8_t *)romFile.readAll().data(), romFile.size(), + hasBootloader ? (uint8_t *)bootloaderFile.readAll().data() : NULL, + hasBootloader ? bootloaderFile.size() : 0, syncRtc, + allowInvalidBehavior, + (serialPortDev.length() == 0 ? NULL : + serialPortDev.toLocal8Bit().data())); + + if (error == EMU_ERROR_NONE) { + QTime now = QTime::currentTime(); + + palmGetRtcFromHost = frontendGetCurrentTime; + emulatorSetRtc(QDate::currentDate().day(), now.hour(), now.minute(), + now.second()); + + if (ramFile.open(QFile::ReadOnly | QFile::ExistingOnly)) { + emulatorLoadRam((uint8_t *)ramFile.readAll().data(), ramFile.size()); + ramFile.close(); } - else{ - return error; + + if (sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly)) { + emulatorInsertSdCard((uint8_t *)sdCardFile.readAll().data(), + sdCardFile.size(), NULL); + sdCardFile.close(); } - romFile.close(); - bootloaderFile.close(); - } + emuInput = palmInput; + emuRamFilePath = assetPath + "/userdata-" + emuOsName + ".ram"; + emuSdCardFilePath = assetPath + "/sd-" + emuOsName + ".img"; + emuSaveStatePath = assetPath + "/states-" + emuOsName + ".states"; - return EMU_ERROR_NONE; -} + // make the place to store the saves + QDir(emuSaveStatePath).mkdir("."); -void EmuWrapper::exit(){ - emuThreadJoin = true; - emuRunning = false; - if(emuThread.joinable()) - emuThread.join(); - if(emuInited){ - writeOutSaves(); - emulatorDeinit(); - } -} + // skip the boot screen + if (fastBoot) + launcherBootInstantly(ramFile.exists()); -void EmuWrapper::pause(){ - if(emuInited){ - emuRunning = false; - while(!emuPaused) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } -} - -void EmuWrapper::resume(){ - if(emuInited){ + // start the thread + emuThreadJoin = false; + emuInited = true; emuRunning = true; - while(emuPaused) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + emuPaused = false; + emuNewFrameReady = false; + emuThread = std::thread(&EmuWrapper::emuThreadRun, this); + } else { + return error; + } + + romFile.close(); + bootloaderFile.close(); + } + + return EMU_ERROR_NONE; } -void EmuWrapper::reset(bool hard){ - if(emuInited){ - bool wasPaused = isPaused(); - - if(!wasPaused) - pause(); - - if(hard) - emulatorHardReset(); - else - emulatorSoftReset(); - - if(!wasPaused) - resume(); - } +void EmuWrapper::exit() { + emuThreadJoin = true; + emuRunning = false; + if (emuThread.joinable()) + emuThread.join(); + if (emuInited) { + writeOutSaves(); + emulatorDeinit(); + } } -void EmuWrapper::setCpuSpeed(double speed){ - if(emuInited){ - bool wasPaused = isPaused(); - - if(!wasPaused) - pause(); - - emulatorSetCpuSpeed(speed); - - if(!wasPaused) - resume(); - } +void EmuWrapper::pause() { + if (emuInited) { + emuRunning = false; + while (!emuPaused) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } } -uint32_t EmuWrapper::bootFromFile(const QString& mainPath){ - bool wasPaused = isPaused(); - uint32_t error = EMU_ERROR_NONE; - QFileInfo pathInfo(mainPath); - QFile appFile(mainPath); - QFile ramFile(mainPath + "." + emuOsName + ".ram"); - QFile sdCardFile(mainPath + "." + emuOsName + ".sd.img"); - QString suffix = QFileInfo(mainPath).suffix().toLower(); - bool hasSaveRam; - bool hasSaveSdCard; - - if(!wasPaused) - pause(); - - //save the current data for the last program launched, or the standard device image if none where launched - writeOutSaves(); - - //its OK if these fail, the buffer will just be NULL, 0 if they do - hasSaveRam = ramFile.open(QFile::ReadOnly | QFile::ExistingOnly); - hasSaveSdCard = suffix != "img" ? sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly) : false; - - //fully clear the emu - emulatorEjectSdCard(); - emulatorHardReset(); +void EmuWrapper::resume() { + if (emuInited) { + emuRunning = true; + while (emuPaused) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} - if(hasSaveRam) - emulatorLoadRam((uint8_t*)ramFile.readAll().data(), ramFile.size()); - if(hasSaveSdCard) - emulatorInsertSdCard((uint8_t*)sdCardFile.readAll().data(), sdCardFile.size(), NULL); +void EmuWrapper::reset(bool hard) { + if (emuInited) { + bool wasPaused = isPaused(); - //its OK if these fail - if(hasSaveRam) - ramFile.close(); - if(hasSaveSdCard) - sdCardFile.close(); + if (!wasPaused) + pause(); - launcherBootInstantly(hasSaveRam); + if (hard) + emulatorHardReset(); + else + emulatorSoftReset(); - if(appFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - QByteArray fileBuffer = appFile.readAll(); + if (!wasPaused) + resume(); + } +} - appFile.close(); +void EmuWrapper::setCpuSpeed(double speed) { + if (emuInited) { + bool wasPaused = isPaused(); - if(suffix == "img"){ - QFile infoFile(mainPath.mid(0, mainPath.length() - 3) + "info");//swap "img" for "info" - sd_card_info_t sdInfo; + if (!wasPaused) + pause(); - memset(&sdInfo, 0x00, sizeof(sdInfo)); + emulatorSetCpuSpeed(speed); - if(infoFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - launcherGetSdCardInfoFromInfoFile((uint8_t*)infoFile.readAll().data(), infoFile.size(), &sdInfo); - infoFile.close(); - } + if (!wasPaused) + resume(); + } +} - error = emulatorInsertSdCard((uint8_t*)fileBuffer.data(), fileBuffer.size(), &sdInfo); - if(error != EMU_ERROR_NONE) - goto errorOccurred; +uint32_t EmuWrapper::bootFromFile(const QString &mainPath) { + bool wasPaused = isPaused(); + uint32_t error = EMU_ERROR_NONE; + QFileInfo pathInfo(mainPath); + QFile appFile(mainPath); + QFile ramFile(mainPath + "." + emuOsName + ".ram"); + QFile sdCardFile(mainPath + "." + emuOsName + ".sd.img"); + QString suffix = QFileInfo(mainPath).suffix().toLower(); + bool hasSaveRam; + bool hasSaveSdCard; + + if (!wasPaused) + pause(); + + // save the current data for the last program launched, or the standard device + // image if none where launched + writeOutSaves(); + + // its OK if these fail, the buffer will just be NULL, 0 if they do + hasSaveRam = ramFile.open(QFile::ReadOnly | QFile::ExistingOnly); + hasSaveSdCard = suffix != "img" + ? sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly) + : false; + + // fully clear the emu + emulatorEjectSdCard(); + emulatorHardReset(); + + if (hasSaveRam) + emulatorLoadRam((uint8_t *)ramFile.readAll().data(), ramFile.size()); + if (hasSaveSdCard) + emulatorInsertSdCard((uint8_t *)sdCardFile.readAll().data(), + sdCardFile.size(), NULL); + + // its OK if these fail + if (hasSaveRam) + ramFile.close(); + if (hasSaveSdCard) + sdCardFile.close(); + + launcherBootInstantly(hasSaveRam); + + if (appFile.open(QFile::ReadOnly | QFile::ExistingOnly)) { + QByteArray fileBuffer = appFile.readAll(); + + appFile.close(); + + if (suffix == "img") { + QFile infoFile(mainPath.mid(0, mainPath.length() - 3) + + "info"); // swap "img" for "info" + sd_card_info_t sdInfo; + + memset(&sdInfo, 0x00, sizeof(sdInfo)); + + if (infoFile.open(QFile::ReadOnly | QFile::ExistingOnly)) { + launcherGetSdCardInfoFromInfoFile((uint8_t *)infoFile.readAll().data(), + infoFile.size(), &sdInfo); + infoFile.close(); } - else{ - if(!hasSaveRam){ - error = launcherInstallFile((uint8_t*)fileBuffer.data(), fileBuffer.size()); - if(error != EMU_ERROR_NONE) - goto errorOccurred; - } - error = launcherExecute(launcherGetAppId((uint8_t*)fileBuffer.data(), fileBuffer.size())); - if(error != EMU_ERROR_NONE) - goto errorOccurred; - } - } - - //everything worked, set output save files - emuRamFilePath = mainPath + "." + emuOsName + ".ram"; - emuSdCardFilePath = suffix != "img" ? mainPath + "." + emuOsName + ".sd.img" : "";//dont duplicate booted SD card images - emuSaveStatePath = mainPath + "." + emuOsName + ".states"; - //make the place to store the saves - QDir(emuSaveStatePath).mkdir("."); - - //need this goto because the emulator must be released before returning - errorOccurred: - if(error != EMU_ERROR_NONE){ - //try and recover from error - emulatorEjectSdCard(); - emulatorHardReset(); - } - - if(!wasPaused) - resume(); - - return error; + error = emulatorInsertSdCard((uint8_t *)fileBuffer.data(), + fileBuffer.size(), &sdInfo); + if (error != EMU_ERROR_NONE) + goto errorOccurred; + } else { + if (!hasSaveRam) { + error = launcherInstallFile((uint8_t *)fileBuffer.data(), + fileBuffer.size()); + if (error != EMU_ERROR_NONE) + goto errorOccurred; + } + error = launcherExecute( + launcherGetAppId((uint8_t *)fileBuffer.data(), fileBuffer.size())); + if (error != EMU_ERROR_NONE) + goto errorOccurred; + } + } + + // everything worked, set output save files + emuRamFilePath = mainPath + "." + emuOsName + ".ram"; + emuSdCardFilePath = suffix != "img" + ? mainPath + "." + emuOsName + ".sd.img" + : ""; // dont duplicate booted SD card images + emuSaveStatePath = mainPath + "." + emuOsName + ".states"; + + // make the place to store the saves + QDir(emuSaveStatePath).mkdir("."); + +// need this goto because the emulator must be released before returning +errorOccurred: + if (error != EMU_ERROR_NONE) { + // try and recover from error + emulatorEjectSdCard(); + emulatorHardReset(); + } + + if (!wasPaused) + resume(); + + return error; } -uint32_t EmuWrapper::installApplication(const QString& path){ - bool wasPaused = isPaused(); - uint32_t error = EMU_ERROR_INVALID_PARAMETER; - QFile appFile(path); +uint32_t EmuWrapper::installApplication(const QString &path) { + bool wasPaused = isPaused(); + uint32_t error = EMU_ERROR_INVALID_PARAMETER; + QFile appFile(path); - if(!wasPaused) - pause(); + if (!wasPaused) + pause(); - if(appFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - error = launcherInstallFile((uint8_t*)appFile.readAll().data(), appFile.size()); - appFile.close(); - } + if (appFile.open(QFile::ReadOnly | QFile::ExistingOnly)) { + error = launcherInstallFile((uint8_t *)appFile.readAll().data(), + appFile.size()); + appFile.close(); + } - if(!wasPaused) - resume(); + if (!wasPaused) + resume(); - return error; + return error; } -uint32_t EmuWrapper::saveState(const QString& name){ - bool wasPaused = isPaused(); - uint32_t error = EMU_ERROR_INVALID_PARAMETER; - QFile stateFile(emuSaveStatePath + "/" + name + ".state"); +uint32_t EmuWrapper::saveState(const QString &name) { + bool wasPaused = isPaused(); + uint32_t error = EMU_ERROR_INVALID_PARAMETER; + QFile stateFile(emuSaveStatePath + "/" + name + ".state"); - if(!wasPaused) - pause(); + if (!wasPaused) + pause(); - //save here - if(stateFile.open(QFile::WriteOnly)){ - uint32_t stateSize = emulatorGetStateSize(); - uint8_t* stateData = new uint8_t[stateSize]; + // save here + if (stateFile.open(QFile::WriteOnly)) { + uint32_t stateSize = emulatorGetStateSize(); + uint8_t *stateData = new uint8_t[stateSize]; - emulatorSaveState(stateData, stateSize);//no need to check for errors since the buffer is always the right size - stateFile.write((const char*)stateData, stateSize); - stateFile.close(); + emulatorSaveState(stateData, + stateSize); // no need to check for errors since the + // buffer is always the right size + stateFile.write((const char *)stateData, stateSize); + stateFile.close(); - error = EMU_ERROR_NONE; - } + error = EMU_ERROR_NONE; + } - if(!wasPaused) - resume(); + if (!wasPaused) + resume(); - return error; + return error; } -uint32_t EmuWrapper::loadState(const QString& name){ - bool wasPaused = isPaused(); - uint32_t error = EMU_ERROR_INVALID_PARAMETER; - QFile stateFile(emuSaveStatePath + "/" + name + ".state"); - - if(!wasPaused) - pause(); +uint32_t EmuWrapper::loadState(const QString &name) { + bool wasPaused = isPaused(); + uint32_t error = EMU_ERROR_INVALID_PARAMETER; + QFile stateFile(emuSaveStatePath + "/" + name + ".state"); - if(stateFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - if(emulatorLoadState((uint8_t*)stateFile.readAll().data(), stateFile.size())) - error = EMU_ERROR_NONE; - stateFile.close(); + if (!wasPaused) + pause(); - } + if (stateFile.open(QFile::ReadOnly | QFile::ExistingOnly)) { + if (emulatorLoadState((uint8_t *)stateFile.readAll().data(), + stateFile.size())) + error = EMU_ERROR_NONE; + stateFile.close(); + } - if(!wasPaused) - resume(); + if (!wasPaused) + resume(); - return error; + return error; } -void EmuWrapper::setPenValue(float x, float y, bool touched){ - emuInput.touchscreenX = x; - emuInput.touchscreenY = y; - emuInput.touchscreenTouched = touched; +void EmuWrapper::setPenValue(float x, float y, bool touched) { + emuInput.touchscreenX = x; + emuInput.touchscreenY = y; + emuInput.touchscreenTouched = touched; } -void EmuWrapper::setKeyValue(uint8_t key, bool pressed){ - switch(key){ - case BUTTON_UP: - emuInput.buttonUp = pressed; - break; +void EmuWrapper::setKeyValue(uint8_t key, bool pressed) { + switch (key) { + case BUTTON_UP: + emuInput.buttonUp = pressed; + break; - case BUTTON_DOWN: - emuInput.buttonDown = pressed; - break; + case BUTTON_DOWN: + emuInput.buttonDown = pressed; + break; - case BUTTON_LEFT: - emuInput.buttonLeft = pressed; - break; + case BUTTON_LEFT: + emuInput.buttonLeft = pressed; + break; - case BUTTON_RIGHT: - emuInput.buttonRight = pressed; - break; + case BUTTON_RIGHT: + emuInput.buttonRight = pressed; + break; - case BUTTON_CENTER: - emuInput.buttonCenter = pressed; - break; + case BUTTON_CENTER: + emuInput.buttonCenter = pressed; + break; - case BUTTON_CALENDAR: - emuInput.buttonCalendar = pressed; - break; + case BUTTON_CALENDAR: + emuInput.buttonCalendar = pressed; + break; - case BUTTON_ADDRESS: - emuInput.buttonAddress = pressed; - break; + case BUTTON_ADDRESS: + emuInput.buttonAddress = pressed; + break; - case BUTTON_TODO: - emuInput.buttonTodo = pressed; - break; + case BUTTON_TODO: + emuInput.buttonTodo = pressed; + break; - case BUTTON_NOTES: - emuInput.buttonNotes = pressed; - break; + case BUTTON_NOTES: + emuInput.buttonNotes = pressed; + break; - case BUTTON_VOICE_MEMO: - emuInput.buttonVoiceMemo = pressed; - break; + case BUTTON_VOICE_MEMO: + emuInput.buttonVoiceMemo = pressed; + break; - case BUTTON_POWER: - emuInput.buttonPower = pressed; - break; + case BUTTON_POWER: + emuInput.buttonPower = pressed; + break; - default: - break; - } + default: + break; + } } -QVector& EmuWrapper::debugLogEntrys(){ - return debugStrings; -} +QVector &EmuWrapper::debugLogEntrys() { return debugStrings; } -QVector& EmuWrapper::debugDuplicateLogEntryCount(){ - return debugDuplicateCallCount; +QVector &EmuWrapper::debugDuplicateLogEntryCount() { + return debugDuplicateCallCount; } -uint64_t& EmuWrapper::debugDeletedLogEntryCount(){ - return debugDeletedStrings; +uint64_t &EmuWrapper::debugDeletedLogEntryCount() { + return debugDeletedStrings; } -QString EmuWrapper::debugGetCpuRegisterString(){ - QString regString = ""; - - if(palmEmulatingTungstenT3){ - for(uint8_t regs = 0; regs < 16; regs++) - regString += QString::asprintf("R%d:0x%08X\n", regs, pxa260GetRegister(regs)); - regString += QString::asprintf("SP:0x%08X\n", pxa260GetRegister(13)); - regString += QString::asprintf("LR:0x%08X\n", pxa260GetRegister(14)); - regString += QString::asprintf("PC:0x%08X\n", pxa260GetPc()); - regString += QString::asprintf("CPSR:0x%08X\n", pxa260GetCpsr()); - regString += QString::asprintf("SPSR:0x%08X", pxa260GetSpsr()); - } - else{ - for(uint8_t dRegs = 0; dRegs < 8; dRegs++) - regString += QString::asprintf("D%d:0x%08X\n", dRegs, flx68000GetRegister(dRegs)); - for(uint8_t aRegs = 0; aRegs < 8; aRegs++) - regString += QString::asprintf("A%d:0x%08X\n", aRegs, flx68000GetRegister(8 + aRegs)); - regString += QString::asprintf("SP:0x%08X\n", flx68000GetRegister(15)); - regString += QString::asprintf("PC:0x%08X\n", flx68000GetPc()); - regString += QString::asprintf("SR:0x%04X", flx68000GetStatusRegister()); - } - - return regString; +QString EmuWrapper::debugGetCpuRegisterString() { + QString regString = ""; + + if (palmEmulatingTungstenT3) { + for (uint8_t regs = 0; regs < 16; regs++) + regString += + QString::asprintf("R%d:0x%08X\n", regs, pxa260GetRegister(regs)); + regString += QString::asprintf("SP:0x%08X\n", pxa260GetRegister(13)); + regString += QString::asprintf("LR:0x%08X\n", pxa260GetRegister(14)); + regString += QString::asprintf("PC:0x%08X\n", pxa260GetPc()); + regString += QString::asprintf("CPSR:0x%08X\n", pxa260GetCpsr()); + regString += QString::asprintf("SPSR:0x%08X", pxa260GetSpsr()); + } else { + for (uint8_t dRegs = 0; dRegs < 8; dRegs++) + regString += + QString::asprintf("D%d:0x%08X\n", dRegs, flx68000GetRegister(dRegs)); + for (uint8_t aRegs = 0; aRegs < 8; aRegs++) + regString += QString::asprintf("A%d:0x%08X\n", aRegs, + flx68000GetRegister(8 + aRegs)); + regString += QString::asprintf("SP:0x%08X\n", flx68000GetRegister(15)); + regString += QString::asprintf("PC:0x%08X\n", flx68000GetPc()); + regString += QString::asprintf("SR:0x%04X", flx68000GetStatusRegister()); + } + + return regString; } -uint64_t EmuWrapper::debugGetEmulatorMemory(uint32_t address, uint8_t size){ - if(palmEmulatingTungstenT3) - return pxa260ReadArbitraryMemory(address, size); - return flx68000ReadArbitraryMemory(address, size); +uint64_t EmuWrapper::debugGetEmulatorMemory(uint32_t address, uint8_t size) { + if (palmEmulatingTungstenT3) + return pxa260ReadArbitraryMemory(address, size); + return flx68000ReadArbitraryMemory(address, size); } -QString EmuWrapper::debugDisassemble(uint32_t address, uint32_t opcodes){ - QString output = ""; +QString EmuWrapper::debugDisassemble(uint32_t address, uint32_t opcodes) { + QString output = ""; - if(palmEmulatingTungstenT3){ - for(uint32_t index = 0; index < opcodes; index++){ - address += disasm_arm_insn(address); - output += disasmReturnBuf; - output += '\n'; - } - } - else{ - char temp[100]; + if (palmEmulatingTungstenT3) { + for (uint32_t index = 0; index < opcodes; index++) { + address += disasm_arm_insn(address); + output += disasmReturnBuf; + output += '\n'; + } + } else { + char temp[100]; - for(uint32_t index = 0; index < opcodes; index++){ - uint8_t opcodeSize = m68k_disassemble(temp, address, M68K_CPU_TYPE_DBVZ); - QString opcodeHex = ""; + for (uint32_t index = 0; index < opcodes; index++) { + uint8_t opcodeSize = m68k_disassemble(temp, address, M68K_CPU_TYPE_DBVZ); + QString opcodeHex = ""; - for(uint8_t opcodeByteIndex = 0; opcodeByteIndex < opcodeSize; opcodeByteIndex++) - opcodeHex += QString::asprintf("%02X", flx68000ReadArbitraryMemory(address + opcodeByteIndex, 8)); + for (uint8_t opcodeByteIndex = 0; opcodeByteIndex < opcodeSize; + opcodeByteIndex++) + opcodeHex += QString::asprintf( + "%02X", flx68000ReadArbitraryMemory(address + opcodeByteIndex, 8)); - output += QString::asprintf("0x%08X: 0x%s\t%s \n", address, opcodeHex.toStdString().c_str(), temp); + output += QString::asprintf("0x%08X: 0x%s\t%s \n", address, + opcodeHex.toStdString().c_str(), temp); - address += opcodeSize; - } - } + address += opcodeSize; + } + } - return output; + return output; } diff --git a/qtBuildSystem/Mu/emuwrapper.h b/qtBuildSystem/Mu/emuwrapper.h index 42562e9..2be77c5 100644 --- a/qtBuildSystem/Mu/emuwrapper.h +++ b/qtBuildSystem/Mu/emuwrapper.h @@ -54,7 +54,9 @@ class EmuWrapper{ EmuWrapper(); ~EmuWrapper(); - uint32_t init(const QString& assetPath, const QString& osVersion, bool syncRtc = false, bool allowInvalidBehavior = false, bool fastBoot = false); + uint32_t init(const QString &assetPath, const QString &osVersion, + bool syncRtc = false, bool allowInvalidBehavior = false, + bool fastBoot = false, const QString &serialPortDev = ""); void exit(); void pause(); void resume(); diff --git a/qtBuildSystem/Mu/mainwindow.cpp b/qtBuildSystem/Mu/mainwindow.cpp index 12a5656..3639f0b 100644 --- a/qtBuildSystem/Mu/mainwindow.cpp +++ b/qtBuildSystem/Mu/mainwindow.cpp @@ -333,7 +333,14 @@ void MainWindow::on_center_released(){ void MainWindow::on_ctrlBtn_clicked(){ if(!emu.isInited()){ QString sysDir = settings->value("resourceDirectory", "").toString(); - uint32_t error = emu.init(sysDir, settings->value("palmOsVersionString", "Palm m515/Palm OS 4.1").toString(), settings->value("featureSyncedRtc", false).toBool(), settings->value("featureDurable", false).toBool(), settings->value("fastBoot", false).toBool()); + uint32_t error = emu.init( + sysDir, + settings->value("palmOsVersionString", "Palm m515/Palm OS 4.1") + .toString(), + settings->value("featureSyncedRtc", false).toBool(), + settings->value("featureDurable", false).toBool(), + settings->value("fastBoot", false).toBool(), + settings->value("serialPortDev", "").toString()); if(error == EMU_ERROR_NONE){ emu.setCpuSpeed(settings->value("cpuSpeed", 1.00).toDouble()); diff --git a/qtBuildSystem/Mu/settingsmanager.cpp b/qtBuildSystem/Mu/settingsmanager.cpp index 517c781..17d9168 100644 --- a/qtBuildSystem/Mu/settingsmanager.cpp +++ b/qtBuildSystem/Mu/settingsmanager.cpp @@ -31,6 +31,10 @@ SettingsManager::SettingsManager(QWidget* parent) : ui->featureSyncedRtc->setChecked(settings->value("featureSyncedRtc", false).toBool()); ui->featureDurable->setChecked(settings->value("featureDurable", false).toBool()); + ui->serialPortDev->setText(settings->value("serialPortDev", + "").toString()); + connect(ui->serialPortDev, &QLineEdit::textChanged, this, &SettingsManager::on_serialPortDev_textChanged); + setKeySelectorState(-1); updateButtonKeys(); } @@ -166,3 +170,7 @@ void SettingsManager::on_palmOsVersion_currentIndexChanged(int index){ settings->setValue("palmOsVersionIndex", index); settings->setValue("palmOsVersionString", ui->palmOsVersion->itemText(index)); } + +void SettingsManager::on_serialPortDev_textChanged(const QString& arg1) { + settings->setValue("serialPortDev", ui->serialPortDev->text()); +} diff --git a/qtBuildSystem/Mu/settingsmanager.h b/qtBuildSystem/Mu/settingsmanager.h index 6dadbbc..39043a4 100644 --- a/qtBuildSystem/Mu/settingsmanager.h +++ b/qtBuildSystem/Mu/settingsmanager.h @@ -51,6 +51,8 @@ private slots: void on_cpuSpeed_valueChanged(double arg1); void on_palmOsVersion_currentIndexChanged(int index); + void on_serialPortDev_textChanged(const QString& arg1); + private: Ui::SettingsManager* ui; QSettings* settings; diff --git a/qtBuildSystem/Mu/settingsmanager.ui b/qtBuildSystem/Mu/settingsmanager.ui index 60516ef..be5d119 100644 --- a/qtBuildSystem/Mu/settingsmanager.ui +++ b/qtBuildSystem/Mu/settingsmanager.ui @@ -29,9 +29,9 @@ 0 - 0 + -284 613 - 444 + 705 @@ -430,6 +430,16 @@ + + + + Serial Port Device + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ec59dab..54318c5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(MuCore STATIC ads7846.c dbvz.c emulator.c + serial.c flx68000.c m5XXBus.c pdiUsbD12.c diff --git a/src/dbvz.c b/src/dbvz.c index b016ba2..8d10332 100644 --- a/src/dbvz.c +++ b/src/dbvz.c @@ -475,17 +475,26 @@ uint8_t dbvzGetRegister8(uint32_t address){ //PDSEL lacks the bottom 4 bits but that is handled on write return registerArrayRead8(address); + case URX1: + case URX1 + 1: + case URX2: + case URX2 + 1: + return registerArrayRead16(address); + default: + printHwRegAccess(address, 0, 8, false); + //bootloader if(address >= 0xE00) return registerArrayRead8(address); - printHwRegAccess(address, 0, 8, false); return 0x00; } } uint16_t dbvzGetRegister16(uint32_t address){ + uint16_t bit; + #if !defined(EMU_NO_SAFETY) if((address & 0x0000F000) != 0x0000F000){ dbvzSetBusErrorTimeOut(address, false); @@ -520,6 +529,16 @@ uint16_t dbvzGetRegister16(uint32_t address){ } case UTX1:{ +#if defined(EMU_DEBUG) + printHwRegAccess(address, 0, 16, false); +#endif + uint16_t dataFlag = 0; + if (palmIrDataSize != NULL) + if (palmIrDataSize() > 0) { + dataFlag = 0x4000; // byte swapped + updateUart1Interrupt(); + } + uint16_t uart1TxStatus = registerArrayRead16(UTX1); uint8_t entrys = uart1TxFifoEntrys(); @@ -527,10 +546,20 @@ uint16_t dbvzGetRegister16(uint32_t address){ uart1TxStatus |= (entrys < 4) << 14; uart1TxStatus |= (entrys < 8) << 13; - return uart1TxStatus; + return uart1TxStatus | dataFlag; } case UTX2:{ +#if defined(EMU_DEBUG) + printHwRegAccess(address, 0, 16, false); +#endif + uint16_t dataFlag = 0; + if (palmSerialDataSize != NULL) + if (palmSerialDataSize() > 0) { + dataFlag = 0x4000; // byte swapped + updateUart2Interrupt(); + } + uint16_t uart2TxStatus = registerArrayRead16(UTX2); uint8_t entrys = uart2TxFifoEntrys(); @@ -538,7 +567,7 @@ uint16_t dbvzGetRegister16(uint32_t address){ uart2TxStatus |= (entrys < 4) << 14; uart2TxStatus |= (entrys < 8) << 13; - return uart2TxStatus; + return uart2TxStatus | dataFlag; } case PLLFSR: @@ -599,11 +628,12 @@ uint16_t dbvzGetRegister16(uint32_t address){ return registerArrayRead16(address); default: + printHwRegAccess(address, 0, 16, false); + //bootloader if(address >= 0xE00) return registerArrayRead16(address); - printHwRegAccess(address, 0, 16, false); return 0x0000; } } @@ -668,6 +698,7 @@ void dbvzSetRegister8(uint32_t address, uint8_t value){ if((registerArrayRead16(USTCNT2) & 0xA000) == 0xA000){ uart2TxFifoWrite(value); updateUart2Interrupt(); + updateUart2PortState(); } return; @@ -1128,6 +1159,7 @@ void dbvzSetRegister16(uint32_t address, uint16_t value){ if((registerArrayRead16(USTCNT2) & 0xA000) == 0xA000){ uart2TxFifoWrite(value & 0x1000 ? value & 0xFF : EMU_SERIAL_BREAK); updateUart2Interrupt(); + updateUart2PortState(); } return; diff --git a/src/emulator.c b/src/emulator.c index c81cf59..754845c 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -11,6 +11,7 @@ #include "ads7846.h" #include "pdiUsbD12.h" #include "sdCard.h" +#include "serial.h" #include "silkscreen.h" #include "portability.h" #if defined(EMU_SUPPORT_PALM_OS5) @@ -117,7 +118,10 @@ void mu_garbage_fill(uint8_t* ram, uint32_t size) { } } -uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmBootloaderData, uint32_t palmBootloaderSize, bool syncRtc, bool allowInvalidBehavior){ +uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t *palmRomData, + uint32_t palmRomSize, uint8_t *palmBootloaderData, + uint32_t palmBootloaderSize, bool syncRtc, + bool allowInvalidBehavior, const char *serialPortDev) { if(emulatorInitialized) return EMU_ERROR_RESOURCE_LOCKED; @@ -132,13 +136,19 @@ uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t* palmRomData, uint32_t pal palmIrDataReceive = NULL; palmIrDataSend = NULL; palmIrDataFlush = NULL; - palmSerialSetPortProperties = NULL; - palmSerialDataSize = NULL; - palmSerialDataReceive = NULL; - palmSerialDataSend = NULL; - palmSerialDataFlush = NULL; palmGetRtcFromHost = NULL; + // Setup serial port + palmSerialSetPortProperties = NULL; + palmSerialDataSize = NULL; + palmSerialDataReceive = NULL; + palmSerialDataSend = NULL; + palmSerialDataFlush = NULL; + + if (serialPortDev != NULL) { + mu_serial_open_and_init(serialPortDev); + } + #if defined(EMU_SUPPORT_PALM_OS5) palmEmulatingTungstenT3 = emulatedDevice == EMU_DEVICE_TUNGSTEN_T3; diff --git a/src/makefile.all b/src/makefile.all index 3276e95..4011f1a 100644 --- a/src/makefile.all +++ b/src/makefile.all @@ -1,5 +1,6 @@ EMU_DEFINES := EMU_SOURCES_C := $(EMU_PATH)/emulator.c \ + $(EMU_PATH)/serial.c \ $(EMU_PATH)/m5XXBus.c \ $(EMU_PATH)/dbvz.c \ $(EMU_PATH)/flx68000.c \ diff --git a/src/serial.c b/src/serial.c new file mode 100644 index 0000000..ec579e5 --- /dev/null +++ b/src/serial.c @@ -0,0 +1,255 @@ +// +// Created by stephanie on 6/14/24. +// + +#include +#include + +#if defined(__LIBRETRO__) +#elif defined(_WIN32) + #include +#else + #include + #include + #include + #include +#endif + +#include "emulator.h" + +#define MU_SERIAL_DEBUG + +#define MU_SERIAL_BUF_SIZE 4096 + +static const char* mu_serial_path = NULL; + +#if defined(__LIBRETRO__) +#elif defined(_WIN32) +#else +static int mu_serial_fd = -1; +#endif + +static uint8_t mu_serial_buf[MU_SERIAL_BUF_SIZE]; +static int32_t mu_serial_buf_len; +static serial_port_properties_t mu_serial_properties; + +void mu_serial_palmSerialSetPortProperties(serial_port_properties_t* properties) +{ +#if defined(__LIBRETRO__) +#elif defined(_WIN32) +#else + struct termios tty; +#endif + + // Always use base properties + if (properties == NULL) { + properties = &mu_serial_properties; + } + + // Did the properties not actually change? + if (0 == memcmp(properties, &mu_serial_properties, + sizeof(mu_serial_properties))) { + return; + } + +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial PROPERTIES\n"); +#endif + + // Write over new properties + memmove(&mu_serial_properties, properties, + sizeof(mu_serial_properties)); + +#if defined(__LIBRETRO__) +#elif defined(_WIN32) +#else + if (properties->enable && mu_serial_fd < 0) { +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial OPEN %s\n", mu_serial_path); +#endif + + mu_serial_fd = open(mu_serial_path, + O_RDWR | O_EXCL | O_NONBLOCK); + + if (mu_serial_fd < 0) { + fprintf(stderr, "Serial FAIL %s\n", + strerror(errno)); + + return; + } + + mu_serial_buf_len = 0; + } else if (!properties->enable && mu_serial_fd >= 0) { +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial CLOSE %s\n", mu_serial_path); +#endif + + close(mu_serial_fd); + + mu_serial_fd = -1; + mu_serial_buf_len = 0; + } + + if (mu_serial_fd >= 0) { + memset(&tty, 0, sizeof(tty)); + + cfsetspeed(&tty, properties->baudRate); + + if (properties->enableParity) { + tty.c_cflag |= PARENB; + } + + if (properties->oddParity) { + tty.c_cflag |= PARODD; + } + + if (properties->stopBits > 1) { + tty.c_cflag |= CSTOPB; + } else { + tty.c_cflag &= (~CSTOPB); + } + + if (properties->use8BitMode) { + tty.c_cflag |= CS8; + } else { + tty.c_lflag &= (~CSIZE); + tty.c_cflag |= CS7; + } + } +#endif +} + +uint32_t mu_serial_palmSerialDataSize(void) +{ + int32_t read_count; + + // Do not read any more data if there is any + if (mu_serial_buf_len > 0) { + return mu_serial_buf_len; + } + +#if defined(__LIBRETRO__) +#elif defined(_WIN32) +#else + if (mu_serial_fd >= 0) { + // Try reading in as much as possible + if (mu_serial_buf_len < MU_SERIAL_BUF_SIZE) { + read_count = read(mu_serial_fd, + &mu_serial_buf[mu_serial_buf_len], + MU_SERIAL_BUF_SIZE - mu_serial_buf_len); + + if (read_count > 0) { + mu_serial_buf_len += read_count; + +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial FLOW %d < %d\n", + mu_serial_buf_len, read_count); +#endif + } + } + } +#endif + + return mu_serial_buf_len; +} + +uint16_t mu_serial_palmSerialDataReceive(void) +{ + uint8_t data; + uint32_t buf_len; + + // Get size of current buffer + buf_len = mu_serial_palmSerialDataSize(); + +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial RECV TRY %d\n", mu_serial_buf_len); +#endif + + // No data to read? + if (buf_len == 0 || mu_serial_buf_len == 0) { + return 0; + } + + // Read in next byte + data = mu_serial_buf[0]; + + // Shift over + memmove(&mu_serial_buf[0], &mu_serial_buf[1], + mu_serial_buf_len - 1); + mu_serial_buf_len -= 1; + +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial RECV %02x %c\n", data, data); +#endif + + // Give the byte we read + return data; +} + +void mu_serial_palmSerialDataSend(uint16_t data) +{ + uint8_t part; + + // Only need to send the lower bit + part = data & 0xFF; + +#if defined(__LIBRETRO__) +#elif defined(_WIN32) +#else + if (mu_serial_fd >= 0) { +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial SEND %02x %c\n", part, part); +#endif + + write(mu_serial_fd, &part, 1); + fsync(mu_serial_fd); + } +#endif +} + +void mu_serial_palmSerialDataFlush(void) +{ + +#if defined(__LIBRETRO__) +#elif defined(_WIN32) +#else + if (mu_serial_fd >= 0) { +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial DROP\n"); +#endif + + tcflush(mu_serial_fd, TCIFLUSH); + } +#endif +} + +void mu_serial_open_and_init(const char* path) +{ + mu_serial_path = strdup(path); + +#if defined(__LIBRETRO__) +#elif defined(_WIN32) +#else + mu_serial_fd = -1; +#endif + +#if defined(MU_SERIAL_DEBUG) + // Debug + fprintf(stderr, "Serial PORT %s\n", mu_serial_path); +#endif + + // Set functions to use + palmSerialSetPortProperties = mu_serial_palmSerialSetPortProperties; + palmSerialDataSize = mu_serial_palmSerialDataSize; + palmSerialDataReceive = mu_serial_palmSerialDataReceive; + palmSerialDataSend = mu_serial_palmSerialDataSend; + palmSerialDataFlush = mu_serial_palmSerialDataFlush; +}