diff --git a/.vscode/settings.json b/.vscode/settings.json index 9871f4ab..ddb3eda1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,5 @@ }, "C_Cpp.formatting": "clangFormat", "C_Cpp.clang_format_style": "file", - "C_Cpp.clang_format_fallbackStyle": "Google" + "C_Cpp.clang_format_path": "${workspaceFolder}\\bin\\windows\\bin\\clang-format.exe", } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index d0776f18..be0673ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ # Minimum CMake version requirement -cmake_minimum_required(VERSION 3.6) +cmake_minimum_required(VERSION 3.10) + +#set(CMAKE_GENERATOR_TOOLSET "ClangCl") # test compilation on clang-c option(ENABLE_CODE_GENERATION "Enable code generation" OFF) @@ -25,8 +27,10 @@ if (APPLE OR LINUX OR UNIX) find_package(SDL2 REQUIRED) endif() +if(NOT DEFINED SDL2_INCLUDE_DIRS) + set(SDL2_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/external/sdl2/include") +endif() -add_definitions(-DEASTL_EASTDC_VSNPRINTF=0) if (WIN32) add_definitions(-D_HAS_STD_BYTE=0) @@ -35,6 +39,10 @@ if (WIN32) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /ZI") add_link_options("/INCREMENTAL") add_compile_options("/MP") # multiprocessor build + + if(NOT CMAKE_GENERATOR_PLATFORM) + set(CMAKE_GENERATOR_PLATFORM "Win32") # add Win32 platform to solution + endif() endif() endif() @@ -209,6 +217,10 @@ set(UAE_SOURCE_LIST uae_src/blit.h ) add_executable(quaesar ${UAE_SOURCE_LIST}) +if (WIN32) + add_dependencies(quaesar quaesar-clang-format) +endif() + source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${UAE_SOURCE_LIST}) # Recursively glob for all .cpp files in the src directory @@ -220,16 +232,15 @@ target_sources(quaesar PRIVATE ${CROSS_FILES} ${QUAE_HEADERS}) set_property(GLOBAL PROPERTY USE_FOLDERS ON) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${QUAE_HEADERS} ${CROSS_FILES} ${SDL2_INCLUDE_DIRS}) +target_include_directories(quaesar PRIVATE ${SDL2_INCLUDE_DIRS}) + if (APPLE OR LINUX OR UNIX) - target_compile_options(quaesar PRIVATE -DUAE=1 -D_cdecl= -DFILEFLAG_WRITE=1 -DOS_NAME=\"linux\") - target_compile_options(quaesar PRIVATE -DUSHORT=uint16_t -DHWND=uint32_t -DHRESULT=uint32_t -DWPARAM=uint16_t -DLPARAM=uint32_t) + target_compile_options(quaesar PRIVATE -DUAE=1 -D_cdecl= -DOS_NAME=\"linux\") target_compile_definitions(quaesar PRIVATE FSUAE) - target_include_directories(quaesar PRIVATE ${SDL2_INCLUDE_DIRS}) target_link_libraries(quaesar PRIVATE ${SDL2_LIBRARIES}) endif() if (WIN32) - target_include_directories(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external/sdl2/include") if (CMAKE_SIZEOF_VOID_P EQUAL 8) target_link_libraries(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external/sdl2/x64/sdl2.lib") target_link_libraries(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external/sdl2/x64/SDL2main.lib") @@ -243,19 +254,15 @@ if (WIN32) endif() if (APPLE) - target_compile_options(quaesar PRIVATE -Wno-macro-redefined -Wno-deprecated-declarations -DFILEFLAG_DIR=1 -DFILEFLAG_DIR=1 -D_ftelli64=ftell -D_fseeki64=fseek -D_fseeko64=fseeko -Dfseeko64=fseeko -Dftello64=ftell) + target_compile_options(quaesar PRIVATE -Wno-macro-redefined -Wno-deprecated-declarations) endif() if (LINUX OR UNIX) - target_compile_options(quaesar PRIVATE -DFILEFLAG_DIR=1 -D_ftelli64=ftello64 -D_fseeki64=fseeko64) target_link_libraries(quaesar PRIVATE dl) endif() target_include_directories(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external/ADFlib/src") -target_include_directories(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external/dear_imgui") target_include_directories(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external") -target_include_directories(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external/capstone/include") -target_include_directories(quaesar PRIVATE "${CMAKE_SOURCE_DIR}/external/EASTL/include") target_link_libraries(quaesar PRIVATE ${SDL2_LIBRARIES} zlibstatic adf imgui capstone EASTL) @@ -263,3 +270,35 @@ if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/imgui.ini") file(COPY_FILE "${CMAKE_CURRENT_LIST_DIR}/bin/install/default_layout.ini" "${CMAKE_CURRENT_BINARY_DIR}/imgui.ini") endif() + +# Format source code with clang-format +if(WIN32) + set(CLANG_FORMAT_EXE "${CMAKE_SOURCE_DIR}/bin/windows/bin/clang-format.exe") +else() + find_program(CLANG_FORMAT_EXE NAMES clang-format) +endif() + +if(CLANG_FORMAT_EXE) + file(GLOB_RECURSE QUAE_FORMAT_SRC_FILES + "${CMAKE_SOURCE_DIR}/src/*.cpp" + "${CMAKE_SOURCE_DIR}/src/*.h" + ) + + # Create a stamp file to track formatting + set(CLANG_FORMAT_STAMP "${CMAKE_BINARY_DIR}/.clang_format.stamp") + + add_custom_command( + OUTPUT ${CLANG_FORMAT_STAMP} + COMMAND ${CMAKE_COMMAND} -E echo "Format sources with clang-format: ${CLANG_FORMAT_EXE}" + COMMAND ${CLANG_FORMAT_EXE} -i --style=file ${QUAE_FORMAT_SRC_FILES} + COMMAND ${CMAKE_COMMAND} -E touch ${CLANG_FORMAT_STAMP} + DEPENDS ${QUAE_FORMAT_SRC_FILES} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Running clang-format on changed files" + ) + + add_custom_target( + quaesar-clang-format + DEPENDS ${CLANG_FORMAT_STAMP} + ) +endif() diff --git a/bin/install/default_layout.ini b/bin/install/default_layout.ini index 756e27d1..b7a29673 100644 --- a/bin/install/default_layout.ini +++ b/bin/install/default_layout.ini @@ -9,69 +9,73 @@ Size=400,400 Collapsed=0 [Window][Disassembly] -Pos=8,42 -Size=334,670 +Pos=8,57 +Size=383,655 Collapsed=0 -DockId=0x00000002,0 +DockId=0x00000003,0 [Window][Registers] -Pos=343,42 -Size=245,244 +Pos=392,57 +Size=267,323 Collapsed=0 -DockId=0x00000005,0 +DockId=0x00000007,0 [Window][Console] -Pos=589,490 -Size=683,222 +Pos=660,490 +Size=612,222 Collapsed=0 -DockId=0x00000008,1 +DockId=0x00000001,1 [Window][Screen] -Pos=589,42 -Size=683,447 +Pos=660,57 +Size=612,432 Collapsed=0 -DockId=0x00000007,1 +DockId=0x00000002,0 [Window][Palette] -Pos=343,42 -Size=245,244 +Pos=392,57 +Size=267,323 Collapsed=0 -DockId=0x00000005,1 +DockId=0x00000007,1 [Window][Memory graph] -Pos=589,42 -Size=683,447 +Pos=660,57 +Size=612,432 Collapsed=0 -DockId=0x00000007,0 +DockId=0x00000002,1 [Window][Memory] -Pos=589,490 -Size=683,222 +Pos=660,490 +Size=612,222 Collapsed=0 -DockId=0x00000008,0 +DockId=0x00000001,0 [Window][Custom regs] -Pos=343,287 -Size=245,425 +Pos=392,381 +Size=267,331 Collapsed=0 -DockId=0x00000006,0 +DockId=0x00000008,0 [Window][Copper debug] -Pos=8,42 -Size=334,670 +Pos=8,57 +Size=383,655 Collapsed=0 -DockId=0x00000002,1 +DockId=0x00000003,1 [Window][Blitter] -Pos=343,42 -Size=245,244 +Pos=392,57 +Size=267,323 Collapsed=0 -DockId=0x00000005,2 +DockId=0x00000007,2 [Window][Blitter/##LEFT_COL_FF37AB84] IsChild=1 Size=112,188 +[Window][Blitter/##LEFT_COL_0360C455] +IsChild=1 +Size=124,267 + [Table][0xF68F8465,4] RefScale=13 Column 0 Width=14 @@ -101,14 +105,43 @@ Column 2 Width=63 Column 3 Width=28 Column 4 Width=589 +[Table][0xD8F01B49,5] +RefScale=13 +Column 0 Width=8 +Column 1 Width=42 +Column 2 Width=63 +Column 3 Width=28 +Column 4 Width=119 + +[Table][0x8745BE8D,4] +RefScale=13 +Column 0 Width=8 +Column 1 Width=56 +Column 2 Width=84 +Column 3 Width=183 + +[Table][0x0613C452,4] +RefScale=13 +Column 0 Width=14 +Column 1 Width=66 +Column 2 Width=18 +Column 3 Width=70 + +[Table][0x1F97F2CE,4] +RefScale=13 +Column 0 Width=52 +Column 1 Width=40 +Column 2 Width=52 +Column 3 Width=45 + [Docking][Data] -DockSpace ID=0x7A095824 Window=0xBB552D6F Pos=8,42 Size=1264,670 Split=X - DockNode ID=0x00000001 Parent=0x7A095824 SizeRef=580,670 Split=X Selected=0x19EDEE42 - DockNode ID=0x00000002 Parent=0x00000001 SizeRef=333,826 Selected=0x19EDEE42 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=245,826 Split=Y Selected=0x13D58281 - DockNode ID=0x00000005 Parent=0x00000003 SizeRef=257,301 Selected=0xEAEE9E08 - DockNode ID=0x00000006 Parent=0x00000003 SizeRef=257,523 Selected=0x13D58281 - DockNode ID=0x00000004 Parent=0x7A095824 SizeRef=865,670 Split=Y Selected=0x35059272 - DockNode ID=0x00000007 Parent=0x00000004 SizeRef=923,602 CentralNode=1 Selected=0x35059272 - DockNode ID=0x00000008 Parent=0x00000004 SizeRef=923,222 Selected=0xB2805FDB +DockSpace ID=0x8E823F11 Window=0x0569B611 Pos=8,57 Size=1264,655 Split=X + DockNode ID=0x0000000A Parent=0x8E823F11 SizeRef=651,655 Split=X + DockNode ID=0x00000003 Parent=0x0000000A SizeRef=383,655 Selected=0xC5987190 + DockNode ID=0x00000006 Parent=0x0000000A SizeRef=267,655 Split=Y + DockNode ID=0x00000007 Parent=0x00000006 SizeRef=174,323 Selected=0xDACC7E9B + DockNode ID=0x00000008 Parent=0x00000006 SizeRef=174,331 CentralNode=1 Selected=0x50B6849F + DockNode ID=0x00000009 Parent=0x8E823F11 SizeRef=612,655 Split=Y Selected=0x60A93F38 + DockNode ID=0x00000002 Parent=0x00000009 SizeRef=629,432 Selected=0xDD2D1825 + DockNode ID=0x00000001 Parent=0x00000009 SizeRef=629,222 Selected=0x561FC6F4 diff --git a/bin/windows/bin/clang-format.exe b/bin/windows/bin/clang-format.exe new file mode 100644 index 00000000..2093879f Binary files /dev/null and b/bin/windows/bin/clang-format.exe differ diff --git a/external/dear_imgui/CMakeLists.txt b/external/dear_imgui/CMakeLists.txt index bdcc3116..90605f05 100644 --- a/external/dear_imgui/CMakeLists.txt +++ b/external/dear_imgui/CMakeLists.txt @@ -15,7 +15,6 @@ list(APPEND IMGUI_SOURCES backends/imgui_impl_sdl2.cpp) list(APPEND IMGUI_SOURCES backends/imgui_impl_sdlrenderer2.cpp) # Include directories for ImGui (SDL2 include paths should be handled in the main CMakeLists.txt) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backends) # Create static library @@ -28,3 +27,5 @@ else() target_include_directories(imgui PRIVATE "${CMAKE_SOURCE_DIR}/external/sdl2/include") endif() +# Include dirs +target_include_directories(imgui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/.clang-format b/src/.clang-format index aaef2abe..2989ab5a 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -33,7 +33,7 @@ BraceWrapping: BeforeCatch: false BeforeElse: false IndentBraces: false - SplitEmptyFunction: true + SplitEmptyFunction: false SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None @@ -99,9 +99,13 @@ SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 +SpacesInLineCommentPrefix: + Minimum: 0 + Maximum: -1 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false diff --git a/src/avioutput.h b/src/avioutput.h index 53b1b577..4669b80b 100644 --- a/src/avioutput.h +++ b/src/avioutput.h @@ -3,7 +3,7 @@ avioutput.h - Copyright(c) 2001 - 2002 §ane + Copyright(c) 2001 - 2002 $ane */ extern int avioutput_video, avioutput_audio, avioutput_enabled, avioutput_requested; diff --git a/src/debugger/action/comps.h b/src/debugger/action/comps.h index a84e0b96..0fdb04a6 100644 --- a/src/debugger/action/comps.h +++ b/src/debugger/action/comps.h @@ -16,6 +16,8 @@ class ShortcutComp : public comp::Base { public: ShortcutComp(action::ActionCreator* cp) : comp::Base(cp, CLASSID) { } + virtual ~ShortcutComp() { + } eastl::span getShortcuts() const { const Shortcut* const* ptrBeg = mShortcuts.data(); diff --git a/src/debugger/action_mgr.cpp b/src/debugger/action_mgr.cpp index 8ff9d8cd..628ae005 100644 --- a/src/debugger/action_mgr.cpp +++ b/src/debugger/action_mgr.cpp @@ -53,7 +53,7 @@ void ActionManager::create(GuiManager* pGuiMgr, Debugger* pDbg) { // create all actions action::ActionCreator ca = {pGuiMgr, pDbg}; auto actionClassMgr = qd::action::details::ActionClassRegistry::get(); - for (auto it : actionClassMgr->m_classInfoMap) { + for (auto it : actionClassMgr->mClassInfoMap) { action::Action* curAction = actionClassMgr->makeInstance(it.first, &ca); mActions.push_back(curAction); const qd::action::details::ActionClassRegistry::MetaInfo& meta = it.second; diff --git a/src/debugger/action_mgr.h b/src/debugger/action_mgr.h index 3a371fef..a16b676e 100644 --- a/src/debugger/action_mgr.h +++ b/src/debugger/action_mgr.h @@ -182,7 +182,7 @@ struct AutoRegistrator { metaInfo.classId = class_id != 0 ? class_id : ++qdbActionAutoClassId; metaInfo.createCallback = (void*)&createClassCb; metaInfo.rtti = &typeid(TClass); - ActionClassRegistry::get()->registerClass(eastl::move(metaInfo)); + metaInfo.registerClass(); } static Action* createClassCb(const ActionClassRegistry::MetaInfo& meta, ActionCreator* cp) { diff --git a/src/debugger/class_reg.h b/src/debugger/class_reg.h index d7c9b064..fa5f5361 100644 --- a/src/debugger/class_reg.h +++ b/src/debugger/class_reg.h @@ -21,7 +21,7 @@ class ClassInfoRegistry_ { void registerClass(); }; // MetaInfo - eastl::vector_map m_classInfoMap; + eastl::vector_map mClassInfoMap; typedef eastl::vector_map TClassInfoMap; public: @@ -35,19 +35,19 @@ class ClassInfoRegistry_ { ~ClassInfoRegistry_(void) = default; void registerClass(TThis::MetaInfo&& meta) { - auto insIt = m_classInfoMap.insert(eastl::make_pair(meta.classId, eastl::move(meta))); + auto insIt = mClassInfoMap.insert(eastl::make_pair(meta.classId, eastl::move(meta))); if (insIt.second == false) { ASSERT_F(0, "Registered classId:%u already exists", meta.classId); } } const MetaInfo* findClassInfo(uint32_t class_id) const { - typename TClassInfoMap::const_iterator It = m_classInfoMap.find(class_id); - if (It == m_classInfoMap.end()) { + typename TClassInfoMap::const_iterator it = mClassInfoMap.find(class_id); + if (it == mClassInfoMap.end()) { ASSERT_F(0, "classId:%u not registered", class_id); return nullptr; } - return &It->second; + return &it->second; } template @@ -61,7 +61,7 @@ class ClassInfoRegistry_ { return pInstance; } -}; // class ClassInfoMgr_ +}; // class ClassInfoRegistry_ ////////////////////////////////////////////////////////////////////////// diff --git a/src/debugger/vm/custom_regs.h b/src/debugger/vm/custom_regs.h index 5254101a..a6665939 100644 --- a/src/debugger/vm/custom_regs.h +++ b/src/debugger/vm/custom_regs.h @@ -8,7 +8,6 @@ namespace qd { -class VM; struct CustomFlagsDesc; diff --git a/src/debugger/window/copper_wnd.cpp b/src/debugger/window/copper_wnd.cpp index e8fd796a..9d81589b 100644 --- a/src/debugger/window/copper_wnd.cpp +++ b/src/debugger/window/copper_wnd.cpp @@ -29,7 +29,6 @@ class CopperDbgWnd : public UiWindow { }; // namespace window ////////////////////////////////////////////////////////////////////////// -// struct DecodedCopperList { diff --git a/src/debugger/window/mem_graph_wnd.cpp b/src/debugger/window/mem_graph_wnd.cpp index 92661adb..82c1ae85 100644 --- a/src/debugger/window/mem_graph_wnd.cpp +++ b/src/debugger/window/mem_graph_wnd.cpp @@ -86,7 +86,7 @@ void MemoryGraphWnd::drawContent() { pCurBank = vm->mem->getBankByInd(mCurBank); mBankOffset = bplPtr - pCurBank->startAddr; CustReg modReg = (nb & 1) == 0 ? CustReg::BPL1MOD : CustReg::BPL2MOD; - mTextureMod = (short)vm->custom->getRegVal(modReg) * 2; + mTextureMod = (short)vm->custom->getRegVal(modReg); // FIXME: How to calculate real bitplane width from ddfstart/ddfstop // int res = 161 / 2 - ddfstrt; int bpWidth = ((ddfstop - ddfstrt) + 8) * 2; diff --git a/src/dummy.cpp b/src/dummy.cpp index 083731bd..de84964a 100644 --- a/src/dummy.cpp +++ b/src/dummy.cpp @@ -18,7 +18,7 @@ #include "pci_hw.h" #include "blkdev.h" #include "uae/time.h" -#include "fsdb.h" +#include "fsusage.h" #include "uae.h" #include "ncr_scsi.h" #include "ncr9x_scsi.h" @@ -51,13 +51,29 @@ #include "drawing.h" // clang-format on +#include #include #include #include #include #include #include +#include +#include +#ifdef TRACE +#undef TRACE +#endif +#define TRACE() SDL_Log("WARN: Using of unimplemented function: '%s()'", __func__) + +void debug(const char* format, ...) { + eastl::fixed_string formatBuffer; + formatBuffer.sprintf("[%s] %s", __func__, format); + va_list args; + va_start(args, format); + SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, formatBuffer.c_str(), args); + va_end(args); +} int avioutput_enabled = 0; bool beamracer_debug = false; @@ -83,6 +99,7 @@ int dos_errno(void) { return errno; } + void pausevideograb(int) { UNIMPLEMENTED(); } @@ -93,7 +110,7 @@ void show_screen(int /*monid*/, int /*mode*/) { // from fs-uae void vsync_clear() { - SDL_Log("quaesar: %s()", __FUNCTION__); + TRACE(); } int vsync_isdone(frame_time_t* /*dt*/) { @@ -111,21 +128,21 @@ bool specialmonitor_need_genlock() { } void setmouseactive(int, int) { - // UNIMPLEMENTED(); + TRACE(); } void screenshot(int /*monid*/, int, int) { UNIMPLEMENTED(); } -int same_aname(const TCHAR* /*an1*/, const TCHAR* /*an2*/) { - UNIMPLEMENTED(); - return 0; + +int same_aname(const TCHAR* an1, const TCHAR* an2) { + //return CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, an1, -1, an2, -1) == CSTR_EQUAL; + return SDL_strcasecmp(an1, an2) == 0; } int input_get_default_keyboard(int /*i*/) { TRACE(); - // UNIMPLEMENTED(); return 0; } @@ -136,36 +153,34 @@ uae_s64 getsetpositionvideograb(uae_s64 /*framepos*/) { // Dummy initialization function static int dummy_init(void) { + TRACE(); return 1; - //*((volatile int*)0) = 0; - // UNIMPLEMENTED(); - // return 0; // Return 0 for success, -1 for failure } // Dummy closing function static void dummy_close(void) { - SDL_Log("quaesar: %s()", __FUNCTION__); + TRACE(); } // Dummy function to acquire an input device static int dummy_acquire(int /*device_id*/, int /*exclusive*/) { - // UNIMPLEMENTED(); + TRACE(); return 0; // Return 0 for success, -1 for failure } // Dummy function to release/unacquire an input device static void dummy_unacquire(int device_id) { - printf("Unacquiring input device %d\n", device_id); + debug("Unacquiring input device %d\n", device_id); } // Dummy function to read input from the device static void dummy_read(void) { - // printf("Reading input from device\n"); + debug("Reading input from device\n"); } // Dummy function to get the number of input devices static int dummy_get_num(void) { - // TRACE(); + TRACE(); return 0; } @@ -221,8 +236,9 @@ struct inputdevice_functions inputdevicefunc_joystick = { dummy_get_widget_num, dummy_get_widget_type, dummy_get_widget_first, dummy_get_flags}; const TCHAR* my_getfilepart(const TCHAR* filename) { - const TCHAR* p; + debug("filename: '%s'", filename); + const TCHAR* p; p = strrchr(filename, '\\'); if (p) return p + 1; @@ -365,27 +381,11 @@ uae_u32 gfxboard_get_romtype(rtgboardconfig*) { return 0; } -void getpathpart(char*, int, char const*) { - UNIMPLEMENTED(); -} - uae_u8* save_log(int, size_t*) { UNIMPLEMENTED(); return nullptr; } -int my_unlink(const TCHAR* /*name*/, bool /*dontrecycle*/) { - UNIMPLEMENTED(); - return 0; -} - -struct fs_usage; - -int get_fs_usage(char const*, char const*, fs_usage*) { - UNIMPLEMENTED(); - return 0; -} - uae_u32 cpuboard_ncr710_io_bget(unsigned int) { UNIMPLEMENTED(); return 0; @@ -410,7 +410,6 @@ void cpuboard_setboard(struct uae_prefs* /*p*/, int /*type*/, int /*subtype*/) { int cpuboard_memorytype(struct uae_prefs* /*p*/) { TRACE(); - // UNIMPLEMENTED(); return 0; } @@ -419,16 +418,6 @@ bool cpuboard_fc_check(uaecptr /*addr*/, uae_u32* /*v*/, int /*size*/, bool /*wr return false; } -int fsdb_name_invalid_dir(a_inode*, const TCHAR* /*n*/) { - UNIMPLEMENTED(); - return 0; -} - -int fsdb_mode_supported(const a_inode*) { - UNIMPLEMENTED(); - return 0; -} - /* int a1060_init(autoconfig_info*) { UNIMPLEMENTED(); @@ -464,7 +453,7 @@ void a4091_add_scsi_unit(int, uaedev_config_info*, romconfig*) { UNIMPLEMENTED(); } void activate_console() { - // UNIMPLEMENTED(); + TRACE(); } void alf3_add_scsi_unit(int, uaedev_config_info*, romconfig*) { @@ -646,11 +635,11 @@ bool cpuboard_autoconfig_init(autoconfig_info*) { } void cpuboard_cleanup() { - SDL_Log("quaesar: %s()", __FUNCTION__); + TRACE(); } void cpuboard_clear() { - SDL_Log("quaesar: %s()", __FUNCTION__); + TRACE(); } void cpuboard_dkb_add_scsi_unit(int, uaedev_config_info*, romconfig*) { @@ -850,26 +839,6 @@ void free_ahi_v2() { TRACE(); } -TCHAR* fsdb_create_unique_nname(a_inode_struct*, char const*) { - UNIMPLEMENTED(); - return nullptr; -} - -int fsdb_mode_representable_p(a_inode_struct const*, int) { - UNIMPLEMENTED(); - return 0; -} - -int fsdb_name_invalid(a_inode_struct*, char const*) { - UNIMPLEMENTED(); - return 0; -} - -TCHAR* fsdb_search_dir(char const*, char*, char**) { - UNIMPLEMENTED(); - return nullptr; -} - int getcapslockstate() { UNIMPLEMENTED(); return 0; @@ -881,7 +850,7 @@ int get_guid_target(unsigned char*) { } void gfxboard_free() { - SDL_Log("quaesar: %s()", __FUNCTION__); + TRACE(); } bool gfxboard_init_memory(autoconfig_info*) { @@ -908,7 +877,7 @@ int graphics_init(bool) { const int amiga_height = 576; const int depth = 32; - int monitor_id = 0; + //int monitor_id = 0; struct vidbuf_description* avidinfo = &adisplays[0].gfxvidinfo; avidinfo->drawbuffer.inwidth = avidinfo->drawbuffer.outwidth = amiga_width; @@ -982,7 +951,7 @@ void unlockscr(struct vidbuffer* vb_in, int /*y_start*/, int /*y_end*/) { void graphics_leave() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); int monitor_id = 0; struct vidbuf_description* avidinfo = &adisplays[monitor_id].gfxvidinfo; @@ -993,7 +962,7 @@ void graphics_leave() { } void graphics_reset(bool) { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } int graphics_setup() { @@ -1061,7 +1030,7 @@ void logging_init() { } void machdep_free() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } int machdep_init() { @@ -1082,63 +1051,6 @@ void multievolution_add_scsi_unit(int, uaedev_config_info*, romconfig*) { UNIMPLEMENTED(); } -void my_close(my_openfile_s*) { - UNIMPLEMENTED(); -} - -bool my_createshortcut(char const*, char const*, char const*) { - UNIMPLEMENTED(); - return false; -} - -uae_s64 my_fsize(my_openfile_s*) { - UNIMPLEMENTED(); - return 0; -} - -bool my_isfilehidden(char const*) { - UNIMPLEMENTED(); - return false; -} - -int my_issamevolume(char const*, char const*, char*) { - UNIMPLEMENTED(); - return 0; -} - -uae_s64 my_lseek(my_openfile_s*, uae_s64, int) { - UNIMPLEMENTED(); - return 0; -} - -int my_mkdir(char const*) { - UNIMPLEMENTED(); - return 0; -} - -my_openfile_s* my_open(char const*, int) { - UNIMPLEMENTED(); - return nullptr; -} - -FILE* my_opentext(char const*) { - UNIMPLEMENTED(); - return nullptr; -} - -unsigned int my_read(my_openfile_s*, void*, unsigned int) { - UNIMPLEMENTED(); - return 0; -} - -void my_setfilehidden(char const*, bool) { - UNIMPLEMENTED(); -} - -unsigned int my_write(my_openfile_s*, void*, unsigned int) { - UNIMPLEMENTED(); - return 0; -} bool ncr710_a4091_autoconfig_init(autoconfig_info*) { UNIMPLEMENTED(); @@ -1288,7 +1200,7 @@ bool samepath(char const*, char const*) { } void sampler_free() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } uae_u8 sampler_getsample(int) { @@ -1323,7 +1235,7 @@ void serial_hsynchandler() { } void serial_rbf_clear() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } uae_u8 serial_readstatus(uae_u8 v, uae_u8) { @@ -1350,7 +1262,7 @@ int sleep_millis_main(int) { } void sndboard_free_capture() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } int sndboard_get_buffer(int*) { @@ -1477,23 +1389,23 @@ void target_paste_to_keyboard() { } void target_quit() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } void target_reset() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } void target_restart() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } void target_run() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } void target_save_options(zfile*, uae_prefs*) { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } void tekmagic_add_scsi_unit(int, uaedev_config_info*, romconfig*) { @@ -1535,7 +1447,7 @@ void* uaenative_get_uaevar() { } void uaeser_clearbuffers(void*) { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } int uaeser_getdatalength() { @@ -1568,7 +1480,7 @@ void uaeser_trigger(void*) { } void uae_slirp_cleanup() { - SDL_Log("quaesar: %s()", __FUNCTION__); + SDL_Log("quaesar: %s()", __func__); } void uae_slirp_end() { @@ -1705,16 +1617,6 @@ bool fp_init_native_80() { return false; } -int fsdb_exists(char const*) { - UNIMPLEMENTED(); - return 0; -} - -int fsdb_fill_file_attrs(a_inode_struct*, a_inode_struct*) { - UNIMPLEMENTED(); - return 0; -} - uae_u32 getlocaltime() { TRACE(); // UNIMPLEMENTED(); @@ -1781,21 +1683,6 @@ uae_u32 masoboshi_ncr9x_scsi_get(unsigned int, int) { return 0; } -bool my_chmod(char const*, unsigned int) { - UNIMPLEMENTED(); - return false; -} - -int my_getvolumeinfo(char const*) { - UNIMPLEMENTED(); - return 0; -} - -int my_rmdir(char const*) { - UNIMPLEMENTED(); - return 0; -} - uae_u8* restore_cdtv_dmac(unsigned char*) { UNIMPLEMENTED(); return nullptr; @@ -1842,9 +1729,21 @@ void target_cpu_speed() { // UNIMPLEMENTED(); } -void target_default_options(uae_prefs*, int) { +void target_default_options(uae_prefs* p, int type) { TRACE(); - // UNIMPLEMENTED(); + if (type == 1 || type == 0 || type == 3) { + //p->win32_uaescsimode = UAESCSI_CDEMU; + p->win32_midioutdev = -2; + p->win32_midiindev = 0; + p->win32_midirouter = false; + p->win32_automount_removable = 0; + p->win32_automount_drives = 0; + p->win32_automount_removabledrives = 0; + p->win32_automount_cddrives = 0; + p->win32_automount_netdrives = 0; + p->picasso96_modeflags = RGBFF_CLUT | RGBFF_R5G6B5PC | RGBFF_B8G8R8A8; + p->win32_filesystem_mangle_reserved_names = true; + } } static int old_w = -1; @@ -1918,112 +1817,111 @@ void f_out(void*, char const*, ...) { } static int dummy_open_bus_func(int flags) { - printf("Dummy open_bus_func called with flags: %d\n", flags); + debug("Dummy open_bus_func called with flags: %d\n", flags); return 0; } static void dummy_close_bus_func(void) { - printf("Dummy close_bus_func called\n"); + debug("Dummy close_bus_func called\n"); } static int dummy_open_device_func(int deviceID, const TCHAR* deviceName, int flags) { - printf("Dummy open_device_func called with deviceID: %d, deviceName: %s, flags: %d\n", deviceID, deviceName, flags); + debug("Dummy open_device_func called with deviceID: %d, deviceName: %s, flags: %d\n", deviceID, deviceName, flags); return 0; } static void dummy_close_device_func(int deviceID) { - printf("Dummy close_device_func called with deviceID: %d\n", deviceID); + debug("Dummy close_device_func called with deviceID: %d\n", deviceID); } static struct device_info* dummy_info_device_func(int deviceID, struct device_info* /*info*/, int size, int flags) { - printf("Dummy info_device_func called with deviceID: %d, size: %d, flags: %d\n", deviceID, size, flags); + debug("Dummy info_device_func called with deviceID: %d, size: %d, flags: %d\n", deviceID, size, flags); return NULL; } static uae_u8* dummy_execscsicmd_out_func(int deviceID, uae_u8* /*cmd*/, int size) { - printf("Dummy execscsicmd_out_func called with deviceID: %d, size: %d\n", deviceID, size); + debug("Dummy execscsicmd_out_func called with deviceID: %d, size: %d\n", deviceID, size); return NULL; } static uae_u8* dummy_execscsicmd_in_func(int deviceID, uae_u8* /*cmd*/, int size, int* result) { - printf("Dummy execscsicmd_in_func called with deviceID: %d, size: %d\n", deviceID, size); + debug("Dummy execscsicmd_in_func called with deviceID: %d, size: %d\n", deviceID, size); *result = 0; return NULL; } static int dummy_execscsicmd_direct_func(int deviceID, struct amigascsi* /*cmd*/) { - printf("Dummy execscsicmd_direct_func called with deviceID: %d\n", deviceID); + debug("Dummy execscsicmd_direct_func called with deviceID: %d\n", deviceID); return 0; } // static void dummy_play_subchannel_callback(uae_u8* data, int size) { -// printf("Dummy play_subchannel_callback called with size: %d\n", size); +// debug("Dummy play_subchannel_callback called with size: %d\n", size); // } // static int dummy_play_status_callback(int status, int subcode) { -// printf("Dummy play_status_callback called with status: %d, subcode: %d\n", status, subcode); +// debug("Dummy play_status_callback called with status: %d, subcode: %d\n", status, subcode); // return 0; // } static int dummy_pause_func(int deviceID, int flags) { - printf("Dummy pause_func called with deviceID: %d, flags: %d\n", deviceID, flags); + debug("Dummy pause_func called with deviceID: %d, flags: %d\n", deviceID, flags); return 0; } static int dummy_stop_func(int deviceID) { - printf("Dummy stop_func called with deviceID: %d\n", deviceID); + debug("Dummy stop_func called with deviceID: %d\n", deviceID); return 0; } static int dummy_play_func(int deviceID, int track, int index, int flags, play_status_callback /*status_callback*/, play_subchannel_callback /*subchannel_callback*/) { - printf("Dummy play_func called with deviceID: %d, track: %d, index: %d, flags: %d\n", deviceID, track, index, - flags); + debug("Dummy play_func called with deviceID: %d, track: %d, index: %d, flags: %d\n", deviceID, track, index, flags); return 0; } static uae_u32 dummy_volume_func(int deviceID, uae_u16 left, uae_u16 right) { - printf("Dummy volume_func called with deviceID: %d, left: %u, right: %u\n", deviceID, left, right); + debug("Dummy volume_func called with deviceID: %d, left: %u, right: %u\n", deviceID, left, right); return 0; } static int dummy_qcode_func(int deviceID, uae_u8* /*qcode*/, int size, bool msf) { - printf("Dummy qcode_func called with deviceID: %d, size: %d, msf: %d\n", deviceID, size, msf); + debug("Dummy qcode_func called with deviceID: %d, size: %d, msf: %d\n", deviceID, size, msf); return 0; } static int dummy_toc_func(int deviceID, struct cd_toc_head* /*toc*/) { - printf("Dummy toc_func called with deviceID: %d\n", deviceID); + debug("Dummy toc_func called with deviceID: %d\n", deviceID); return 0; } static int dummy_read_func(int deviceID, uae_u8* /*buffer*/, int size, int flags) { - printf("Dummy read_func called with deviceID: %d, size: %d, flags: %d\n", deviceID, size, flags); + debug("Dummy read_func called with deviceID: %d, size: %d, flags: %d\n", deviceID, size, flags); return 0; } static int dummy_rawread_func(int deviceID, uae_u8* /*buffer*/, int size, int subcode, int flags, uae_u32 offset) { - printf("Dummy rawread_func called with deviceID: %d, size: %d, subcode: %d, flags: %d, offset: %u\n", deviceID, - size, subcode, flags, offset); + debug("Dummy rawread_func called with deviceID: %d, size: %d, subcode: %d, flags: %d, offset: %u\n", deviceID, size, + subcode, flags, offset); return 0; } static int dummy_write_func(int deviceID, uae_u8* /*buffer*/, int size, int flags) { - printf("Dummy write_func called with deviceID: %d, size: %d, flags: %d\n", deviceID, size, flags); + debug("Dummy write_func called with deviceID: %d, size: %d, flags: %d\n", deviceID, size, flags); return 0; } int dummy_isatapi_func(int deviceID) { - printf("Dummy isatapi_func called with deviceID: %d\n", deviceID); + debug("Dummy isatapi_func called with deviceID: %d\n", deviceID); return 0; } int dummy_ismedia_func(int deviceID, int flags) { - printf("Dummy ismedia_func called with deviceID: %d, flags: %d\n", deviceID, flags); + debug("Dummy ismedia_func called with deviceID: %d, flags: %d\n", deviceID, flags); return 0; } int dummy_scsiemu_func(int deviceID, uae_u8* /*data*/) { - printf("Dummy scsiemu_func called with deviceID: %d\n", deviceID); + debug("Dummy scsiemu_func called with deviceID: %d\n", deviceID); return 0; } @@ -2132,12 +2030,12 @@ void update_memdump(uae_u32) { // dummy write_log void write_log(const char* format, ...) { - va_list parms; + va_list vargs; - va_start(parms, format); - // vprintf(format, parms); - qd::logConsole().logV(qd::LogEntry::E_INFO, format, parms); - va_end(parms); + va_start(vargs, format); + SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, format, vargs); + qd::logConsole().logV(qd::LogEntry::E_INFO, format, vargs); + va_end(vargs); } // dummy write_log diff --git a/src/eastl.cpp b/src/eastl.cpp index a0e850b2..185b3eb6 100644 --- a/src/eastl.cpp +++ b/src/eastl.cpp @@ -1,7 +1,11 @@ +// fix '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + #include #include #include -#include "sysconfig.h" void* operator new[](size_t size, const char* /*pName*/, int /*flags*/, unsigned /*debugFlags*/, const char* /*file*/, @@ -38,10 +42,38 @@ int Vsnprintf16(wchar_t* pDestination, size_t n, const wchar_t* pFormat, va_list return vswprintf(pDestination, n, pFormat, arguments); #endif } -int Vsnprintf32(char8_t* pDestination, size_t n, const char32_t* pFormat, va_list arguments) { +int Vsnprintf32(char32_t* pDestination, size_t n, const char32_t* pFormat, va_list arguments) { #ifdef _MSC_VER return _vsnprintf((char*)pDestination, n, (char*)pFormat, arguments); #else - return vsnprintf(pDestination, n, (char*)pFormat, arguments); + return vsnprintf((char*)pDestination, n, (char*)pFormat, arguments); #endif } + +////////////////////////////////////////////////////////////////////////// +#if EASTL_EASTDC_VSNPRINTF +namespace EA { +namespace StdC { +int Vsnprintf(char* EA_RESTRICT pDestination, size_t n, const char* EA_RESTRICT pFormat, va_list arguments) { + return Vsnprintf8(pDestination, n, pFormat, arguments); +} +int Vsnprintf(char16_t* EA_RESTRICT pDestination, size_t n, const char16_t* EA_RESTRICT pFormat, va_list arguments) { + return Vsnprintf16((wchar_t*)pDestination, n, (wchar_t*)pFormat, arguments); +} +int Vsnprintf(char32_t* EA_RESTRICT pDestination, size_t n, const char32_t* EA_RESTRICT pFormat, va_list arguments) { + return Vsnprintf32(pDestination, n, pFormat, arguments); +} +#if EA_CHAR8_UNIQUE +int Vsnprintf(char8_t* EA_RESTRICT pDestination, size_t n, const char8_t* EA_RESTRICT pFormat, va_list arguments) { + return Vsnprintf8((char*)pDestination, n, (char*)pFormat, arguments); +} +#endif +#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE +int Vsnprintf(wchar_t* EA_RESTRICT pDestination, size_t n, const wchar_t* EA_RESTRICT pFormat, va_list arguments) { + // return VsnprintfW(pDestination, n, pFormat, arguments); + return Vsnprintf16(pDestination, n, pFormat, arguments); +} +#endif +}; // namespace StdC +}; // namespace EA +#endif // EASTL_EASTDC_VSNPRINTF diff --git a/src/file_system.cpp b/src/file_system.cpp index 90c3849d..8774b01a 100644 --- a/src/file_system.cpp +++ b/src/file_system.cpp @@ -1,56 +1,255 @@ -#include +// clang-format off +#include "sysconfig.h" #include "sysdeps.h" +#include "options.h" +#include "memory.h" + +#include "fsusage.h" +#include "fsdb.h" +#include "zfile.h" +// clang-format on + +#include +#include +#include +#include +#include +#include // For strcpy, strcat, etc. +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#include +#pragma comment(lib, "Shlwapi.lib") +#else // POSIX + +#include +#include +#include +#include +#include + +#if defined(__APPLE__) +#include +#elif defined(__linux__) +#include +#endif + +#define FILE_ATTRIBUTE_READONLY 0x00000001 +#define FILE_ATTRIBUTE_HIDDEN 0x00000002 +#define FILE_ATTRIBUTE_SYSTEM 0x00000004 +#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 +#define FILE_ATTRIBUTE_ARCHIVE 0x00000020 + +#endif // !WIN32 + +#undef min + +static int fsdb_debug = 0; +#ifdef TRACE +#undef TRACE +#endif +#define TRACE() SDL_Log("WARN: Using of unimplemented function: '%s()'", __func__) +extern void debug(const char* x, ...); + + +/* these are deadly (but I think allowed on the Amiga): */ +#define NUM_EVILCHARS 7 +static char evilchars[NUM_EVILCHARS] = {'\\', '*', '?', '\"', '<', '>', '|'}; +#define PATHPREFIX _T("\\\\?\\") + + +#define UAEFSDB2_LEN 1632 +#define UAEFSDB_LEN 604 + + +#ifdef _WIN32 TCHAR start_path_data[MAX_DPATH]; +#else +char start_path_data[MAX_DPATH]; +#endif + int pissoff_value = 15000 * CYCLE_UNIT; int pause_emulation = 0; + int my_existsdir(const TCHAR* directoryPath) { - struct stat st; + debug("dir: '%s'", directoryPath); + try { + std::filesystem::path dirPath(directoryPath); + return std::filesystem::exists(dirPath) && std::filesystem::is_directory(dirPath) ? 1 : 0; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_existsdir: Error checking directory %s: %s", directoryPath, e.what()); + return 0; + } +} - if (stat(directoryPath, &st) == 0) { - if (S_ISDIR(st.st_mode)) { - return 1; + +int my_existsfile(const TCHAR* name) { + debug("name: '%s'", name); + try { + std::filesystem::path filePath(name); + return std::filesystem::exists(filePath) && std::filesystem::is_regular_file(filePath) ? 1 : 0; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_existsfile: Error checking file %s: %s", name, e.what()); + return 0; + } +} + + +bool my_chmod(const char* name, unsigned int mode) { + try { + std::filesystem::path filePath(name); + auto perms = std::filesystem::status(filePath).permissions(); + + // Adjust permissions based on mode + if (mode & FILEFLAG_WRITE) { + perms |= std::filesystem::perms::owner_write; + } else { + perms &= ~std::filesystem::perms::owner_write; } + + std::filesystem::permissions(filePath, perms); + return true; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_chmod: Error changing permissions for %s: %s", name, e.what()); + return false; } +} - return 0; + +int my_getvolumeinfo(const char* root) { + debug("root: %s", root); + std::filesystem::path filePath = root; + + try { + if (!std::filesystem::exists(filePath)) + return -1; + if (!std::filesystem::is_directory(filePath)) + return -2; + } catch (const std::filesystem::filesystem_error& e) { + debug("Filesystem error for %s: %s", root, e.what()); + return -1; + } + + int ret = 0; + + // Check write permissions + try { + auto perms = std::filesystem::status(filePath).permissions(); + if ((perms & std::filesystem::perms::owner_write) == std::filesystem::perms::none) { + ret |= MYVOLUMEINFO_READONLY; + } + } catch (const std::filesystem::filesystem_error& e) { + debug("Permission check error for %s: %s", root, e.what()); + } + + // Check for named streams support (platform-specific) +#if defined(_WIN32) + TCHAR volume[MAX_PATH]; + if (GetVolumePathNameA(root, volume, MAX_PATH)) { + TCHAR fsname[MAX_PATH]; + DWORD flags; + if (GetVolumeInformationA(volume, NULL, 0, NULL, NULL, &flags, fsname, MAX_PATH)) { + if (flags & FILE_NAMED_STREAMS) + ret |= MYVOLUMEINFO_STREAMS; + } + } +#elif defined(__APPLE__) + struct statfs sfs; + if (statfs(root, &sfs) == 0) { + if (strcmp(sfs.f_fstypename, "apfs") == 0 || strcmp(sfs.f_fstypename, "hfs") == 0) + ret |= MYVOLUMEINFO_STREAMS; + } +#elif defined(__linux__) + // Named streams are not generally supported on Linux. + // This can be extended for specific filesystems like ZFS if needed. +#endif + + // Use SDL2 to get base path and check if it matches the root + char* basePath = SDL_GetBasePath(); + if (basePath) { + debug("SDL Base Path: %s", basePath); + try { + if (std::filesystem::equivalent(filePath, basePath)) { + // Example logic, actual stream support is checked above. + } + } catch (const std::filesystem::filesystem_error& e) { + debug("Filesystem equivalent check error: %s", e.what()); + } + SDL_free(basePath); + } + + return ret; } -#ifdef _WIN32 -#include +int my_rmdir(const char* name) { + try { + std::filesystem::remove(name); + return 0; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_rmdir: Error removing directory %s: %s", name, e.what()); + return -1; + } +} -int my_existsfile(const TCHAR* name) { - DWORD attr; +void getpathpart(char* out, int size, const char* path) { + if (!path || !out || size <= 0) + return; - attr = GetFileAttributes(name); - if (attr == INVALID_FILE_ATTRIBUTES) + try { + std::filesystem::path p(path); + std::string parent = p.parent_path().string(); + strncpy(out, parent.c_str(), size - 1); + out[size - 1] = '\0'; + } catch (const std::exception& e) { + SDL_Log("getpathpart: Error processing path %s: %s", path, e.what()); + out[0] = '\0'; + } +} + +int my_unlink(const char* name, bool /*dontrecycle*/) { + try { + std::filesystem::remove(name); return 0; - if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) - return 1; - return 0; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_unlink: Error deleting file %s: %s", name, e.what()); + return -1; + } } -#else -int my_existsfile(const TCHAR* name) { - if (access(name, F_OK) != -1) { - return 1; - } else { +int get_fs_usage(const TCHAR* path, const TCHAR* disk, struct fs_usage* fsp) { + try { + std::filesystem::space_info spaceInfo = std::filesystem::space(path); + fsp->total = spaceInfo.capacity; + fsp->avail = spaceInfo.available; return 0; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("Filesystem error for %s: %s", path, e.what()); } + + // Fallback or error + SDL_Log("Warn using of unimplemented function: `%s` for path %s", __FUNCTION__, path); + fsp->total = 1000000; // Default dummy values + fsp->avail = 1000000; + return -1; // Indicate error or unimplemented } -#endif int isprinter() { return 0; } + void to_lower(TCHAR* s, int len) { - for (int i = 0; i < len; i++) { + for (int i = 0; i < len && s[i]; i++) { // Added s[i] check for safety s[i] = tolower(s[i]); } } @@ -58,44 +257,27 @@ void to_lower(TCHAR* s, int len) { TCHAR* utf8u(const char* s) { if (s == NULL) return NULL; - return ua(s); + return ua(s); // Assuming ua handles char* to TCHAR* (potentially wchar_t*) } char* uutf8(const TCHAR* s) { if (s == NULL) return NULL; - return ua(s); + return ua(s); // Assuming ua handles TCHAR* (potentially wchar_t*) to char* } -/* -TCHAR *au_copy (TCHAR *dst, int maxlen, const char *src) -{ - // this should match the WinUAE au_copy behavior, where either the - // entire string is copied (and null-terminated), or the result is - // an empty string - if (uae_tcslcpy (dst, src, maxlen) >= maxlen) { - dst[0] = '\0'; - } - return dst; -} - -char *ua_copy (char *dst, int maxlen, const TCHAR *src) -{ - return au_copy (dst, maxlen, src); -} -*/ - TCHAR* my_strdup_ansi(const char* src) { return strdup(src); } + #define NO_TRANSLATION TCHAR* au_fs(const char* src) { #ifdef NO_TRANSLATION if (src == NULL) return NULL; - return strdup(src); + return strdup(src); // Assumes TCHAR is char or compatible #else gsize read, written; gchar* result = g_convert(src, -1, "UTF-8", "ISO-8859-1", &read, &written, NULL); @@ -107,18 +289,19 @@ TCHAR* au_fs(const char* src) { #endif } + char* ua_fs(const TCHAR* s, int defchar) { #ifdef NO_TRANSLATION if (s == NULL) return NULL; - return strdup(s); + return strdup(s); // Assumes TCHAR is char or compatible #else // we convert from fs-uae's internal encoding (UTF-8) to latin-1 here, // so file names can be read properly in the amiga char def[] = "?"; - if (defchar < 128) { - def[0] = defchar; + if (defchar < 128 && defchar >= 0) { // Added defchar >= 0 check + def[0] = (char)defchar; } gsize read, written; @@ -135,111 +318,1004 @@ char* ua_fs(const TCHAR* s, int defchar) { #endif } + TCHAR* au_fs_copy(TCHAR* dst, int maxlen, const char* src) { #ifdef NO_TRANSLATION + if (!dst || maxlen <= 0) + return NULL; dst[0] = 0; - strncpy(dst, src, maxlen); + strncpy(dst, src, maxlen - 1); + dst[maxlen - 1] = 0; // Ensure null termination return dst; #else gsize read, written; gchar* result = g_convert(src, -1, "UTF-8", "ISO-8859-1", &read, &written, NULL); if (result == NULL) { write_log("WARNING: au_fs_copy failed to convert string %s", src); - dst[0] = '\0'; + if (dst && maxlen > 0) + dst[0] = '\0'; return dst; } - strncpy(dst, result, maxlen); + strncpy(dst, result, maxlen - 1); + dst[maxlen - 1] = 0; // Ensure null termination free(result); return dst; #endif } + char* ua_fs_copy(char* dst, int maxlen, const TCHAR* src, int defchar) { #ifdef NO_TRANSLATION + if (!dst || maxlen <= 0) + return NULL; dst[0] = 0; - strncpy(dst, src, maxlen); + strncpy(dst, src, maxlen - 1); + dst[maxlen - 1] = 0; // Ensure null termination return dst; #else char def[] = "?"; - if (defchar < 128) { - def[0] = defchar; + if (defchar < 128 && defchar >= 0) { + def[0] = (char)defchar; } gsize read, written; gchar* result = g_convert_with_fallback(src, -1, "ISO-8859-1", "UTF-8", def, &read, &written, NULL); if (result == NULL) { write_log("WARNING: ua_fs_copy failed to convert string %s", src); - dst[0] = '\0'; + if (dst && maxlen > 0) + dst[0] = '\0'; return dst; } - strncpy(dst, result, maxlen); + strncpy(dst, result, maxlen - 1); + dst[maxlen - 1] = 0; // Ensure null termination free(result); return dst; #endif } + TCHAR* target_expand_environment(const TCHAR* path, TCHAR* out, int maxlen) { + debug("path:'%s'", path); if (!path) return NULL; + + std::string s_path = path; + size_t pos = 0; + + while ((pos = s_path.find('$', pos)) != std::string::npos) { + size_t end_pos; + std::string var_name; + + if (s_path[pos + 1] == '{') { + end_pos = s_path.find('}', pos + 2); + if (end_pos == std::string::npos) + break; + var_name = s_path.substr(pos + 2, end_pos - (pos + 2)); + end_pos++; + } else { + end_pos = pos + 1; + while (end_pos < s_path.length() && (isalnum(s_path[end_pos]) || s_path[end_pos] == '_')) { + end_pos++; + } + var_name = s_path.substr(pos + 1, end_pos - (pos + 1)); + } + + const char* var_value = SDL_getenv(var_name.c_str()); + std::string value_str = var_value ? var_value : ""; + s_path.replace(pos, end_pos - pos, value_str); + pos += value_str.length(); + } + + try { + std::filesystem::path canonical_path = std::filesystem::weakly_canonical(s_path); + s_path = canonical_path.string(); + } catch (const std::filesystem::filesystem_error& e) { + debug("Filesystem error: %s", e.what()); + } + if (out == NULL) { - return strdup(path); + return strdup(s_path.c_str()); } else { - _tcscpy(out, path); + strncpy(out, s_path.c_str(), maxlen - 1); + out[maxlen - 1] = '\0'; return out; } } -bool my_stat(const TCHAR* name, struct mystat* ms) { - // UNIMPLEMENTED(); - return true; + +bool my_stat(const TCHAR* name, struct mystat* statbuf) { + try { + std::filesystem::path filePath(name); + if (!std::filesystem::exists(filePath)) { + return false; + } + + auto fileStatus = std::filesystem::status(filePath); + statbuf->size = std::filesystem::is_regular_file(filePath) ? std::filesystem::file_size(filePath) : 0; + + statbuf->mode = 0; + if (std::filesystem::is_directory(filePath)) { + statbuf->mode |= FILEFLAG_DIR; + } + if ((int)(fileStatus.permissions() & std::filesystem::perms::owner_write) == 0) { + statbuf->mode |= FILEFLAG_READ; + } else { + statbuf->mode |= FILEFLAG_READ | FILEFLAG_WRITE; + } + + auto ftime = std::filesystem::last_write_time(filePath); + auto sdlTime = std::chrono::time_point_cast(ftime).time_since_epoch(); + statbuf->mtime.tv_sec = std::chrono::duration_cast(sdlTime).count(); + statbuf->mtime.tv_usec = std::chrono::duration_cast(sdlTime).count() % 1000000; + + return true; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_stat: Error accessing %s: %s", name, e.what()); + return false; + } } + +struct my_opendir_s { + SDL_RWops* dir; + std::vector entries; + size_t index; +}; + int my_readdir(struct my_opendir_s* mod, TCHAR* name) { - UNIMPLEMENTED(); - return 0; + if (!mod || mod->index >= mod->entries.size()) + return 0; + + strncpy(name, mod->entries[mod->index].c_str(), MAX_DPATH - 1); + name[MAX_DPATH - 1] = '\0'; + mod->index++; + return 1; } struct my_opendir_s* my_opendir(const TCHAR* name, const TCHAR* mask) { - UNIMPLEMENTED(); - return NULL; + struct my_opendir_s* mod = (struct my_opendir_s*)calloc(1, sizeof(struct my_opendir_s)); + if (!mod) + return NULL; + + try { + std::filesystem::path dirPath(name); + std::string maskStr = mask ? mask : "*"; + + for (const auto& entry : std::filesystem::directory_iterator(dirPath)) { + std::string filename = entry.path().filename().string(); + if (maskStr == "*" || maskStr == "*.*" || filename == maskStr) { + mod->entries.push_back(filename); + } + } + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_opendir: Error opening directory %s: %s", name, e.what()); + free(mod); + return NULL; + } + + mod->index = 0; + return mod; } -void my_closedir(struct my_opendir_s* mod) { - UNIMPLEMENTED(); + +struct my_opendir_s* my_opendir(const TCHAR* name) { + return my_opendir(name, "*"); } -/* -int hdf_write_target(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len) { - UNIMPLEMENTED(); - return 0; + +void my_closedir(struct my_opendir_s* mod) { + if (mod) { + free(mod); + } } -*/ + int hdf_write_target(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len, uint32_t* error) { UNIMPLEMENTED(); + if (error) + *error = 1; return 0; } -struct my_opendir_s* my_opendir(const TCHAR* name) { - UNIMPLEMENTED(); - return nullptr; + +static void create_uaefsdb(a_inode* aino, uae_u8* buf, int winmode) { + std::string nn = std::filesystem::path(aino->nname).filename().string(); + std::string aname = aino->aname ? aino->aname : ""; + std::string comment = aino->comment ? aino->comment : ""; + + buf[0] = 1; + do_put_mem_long((uae_u32*)(buf + 1), aino->amigaos_mode); + + strncpy((char*)buf + 5, aname.c_str(), 256); + buf[5 + 256] = '\0'; + + strncpy((char*)buf + 5 + 257, nn.c_str(), 256); + buf[5 + 257 + 256] = '\0'; + + strncpy((char*)buf + 5 + 2 * 257, comment.c_str(), 80); + buf[5 + 2 * 257 + 80] = '\0'; + + do_put_mem_long((uae_u32*)(buf + 5 + 2 * 257 + 81), winmode); + + strncpy((char*)(buf + 604), aname.c_str(), 256); + strncpy((char*)(buf + 1118), nn.c_str(), 256); + + aino->has_dbentry = 0; +} + + +static std::string make_uaefsdbpath(const char* dir, const char* name = nullptr) { + std::filesystem::path basePath(dir); + if (name && *name) { + basePath /= name; + } + basePath /= FSDB_FILE; + return basePath.string(); +} + + +DWORD GetFileAttributesSafe(const char* name) { + if (!name) { + return -1; // INVALID_FILE_ATTRIBUTES + } + namespace fs = std::filesystem; + + fs::path filePath(name); + try { + if (!fs::exists(filePath)) { + return -1; // INVALID_FILE_ATTRIBUTES + } + + DWORD attributes = 0; + + if (fs::is_directory(filePath)) { + attributes |= FILE_ATTRIBUTE_DIRECTORY; + } + + fs::file_status fst = fs::status(filePath); + if ((fst.permissions() & fs::perms::owner_write) != fs::perms::none) { + attributes |= FILE_ATTRIBUTE_READONLY; + } + + // Check for hidden files (POSIX: files starting with '.') + std::string filename = filePath.filename().string(); + if (!filename.empty() && filename[0] == '.') { + attributes |= FILE_ATTRIBUTE_HIDDEN; + } + + return attributes; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("GetFileAttributesSafe: Error accessing %s: %s", name, e.what()); + return -1; // INVALID_FILE_ATTRIBUTES + } +} + + +bool SetFileAttributesSafe(const char* name, uint32_t attr) { + // Only "hidden" attribute is supported on POSIX (by renaming file) + bool ok = true; + bool want_hidden = (attr & FILE_ATTRIBUTE_HIDDEN) != 0; + std::filesystem::path p(name); + std::string filename = p.filename().string(); + if (want_hidden && filename[0] != '.') { + std::filesystem::path newpath = p.parent_path() / ("." + filename); + std::error_code ec; + std::filesystem::rename(p, newpath, ec); + ok = !ec; + } else if (!want_hidden && filename[0] == '.') { + std::filesystem::path newpath = p.parent_path() / filename.substr(1); + std::error_code ec; + std::filesystem::rename(p, newpath, ec); + ok = !ec; + } + // Other attributes (readonly, archive, system) are not supported here + return ok; +} + + +static int write_uaefsdb(const TCHAR* item, uae_u8* fsdb) { + // Only supports writing the .uaefsdb file as a regular file in the same directory as 'item' + // No Windows-specific file attributes or timestamps are preserved + + // Build .uaefsdb path + std::filesystem::path itemPath(item); + std::filesystem::path dir = itemPath.parent_path(); + std::filesystem::path uaefsdbPath = dir / FSDB_FILE; + + // Open file for writing (overwrite) + SDL_RWops* file = SDL_RWFromFile(uaefsdbPath.string().c_str(), "wb"); + if (!file) { + SDL_Log("write_uaefsdb: failed to open %s for writing: %s", uaefsdbPath.string().c_str(), SDL_GetError()); + return 0; + } + + size_t written = SDL_RWwrite(file, fsdb, 1, UAEFSDB2_LEN); + SDL_RWclose(file); + + if (written != UAEFSDB2_LEN) { + SDL_Log("write_uaefsdb: failed to write all data to %s", uaefsdbPath.string().c_str()); + // Try to remove incomplete file + std::error_code ec; + std::filesystem::remove(uaefsdbPath, ec); + return 0; + } + + return 1; } struct a_inode_struct; + int fsdb_set_file_attrs(a_inode_struct* aino) { - UNIMPLEMENTED(); - return 0; + if (!aino || !aino->nname) + return 0; + + uae_u8 fsdb[UAEFSDB2_LEN]; + memset(fsdb, 0, sizeof(fsdb)); + int mode = 0; + + // Set file attributes based on AmigaOS mode + if (!(aino->amigaos_mode & A_FIBF_WRITE)) + mode |= FILE_ATTRIBUTE_READONLY; + if (aino->amigaos_mode & A_FIBF_ARCHIVE) + mode |= FILE_ATTRIBUTE_ARCHIVE; + if (aino->amigaos_mode & A_FIBF_HIDDEN) + mode |= FILE_ATTRIBUTE_HIDDEN; + if (aino->amigaos_mode & A_FIBF_PURE) + mode |= FILE_ATTRIBUTE_SYSTEM; + + // Create the .uaefsdb metadata + create_uaefsdb(aino, fsdb, mode); + + // Write the metadata to the .uaefsdb file + try { + std::filesystem::path filePath(aino->nname); + std::filesystem::path dirPath = filePath.parent_path(); + std::filesystem::path uaefsdbPath = dirPath / FSDB_FILE; + + SDL_RWops* file = SDL_RWFromFile(uaefsdbPath.string().c_str(), "wb"); + if (!file) { + SDL_Log("fsdb_set_file_attrs: Failed to open %s for writing: %s", uaefsdbPath.string().c_str(), + SDL_GetError()); + return 0; + } + + size_t written = SDL_RWwrite(file, fsdb, 1, UAEFSDB2_LEN); + SDL_RWclose(file); + + if (written != UAEFSDB2_LEN) { + SDL_Log("fsdb_set_file_attrs: Failed to write all data to %s", uaefsdbPath.string().c_str()); + std::filesystem::remove(uaefsdbPath); // Remove incomplete file + return 0; + } + + return 1; // Success + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("fsdb_set_file_attrs: Filesystem error for %s: %s", aino->nname, e.what()); + return 0; + } } + void fetch_nvrampath(TCHAR* out, int size) { UNIMPLEMENTED(); + if (out && size > 0) + out[0] = '\0'; } void fetch_configurationpath(TCHAR* out, int size) { + debug("out:'%s'", out); out[0] = _T('/'); out[1] = _T('.'); out[2] = 0; } + + +/* Return nonzero for any name we can't create on the native filesystem. */ +static int fsdb_name_invalid_2x(const char* n, int dir) { + size_t i; + static char s1[MAX_DPATH]; + static char s2[MAX_DPATH]; + char a = n[0]; + char b = (a == '\0' ? a : n[1]); + char c = (b == '\0' ? b : n[2]); + char d = (c == '\0' ? c : n[3]); + size_t l = _tcslen(n); + int ll; + + /* the reserved fsdb filename */ + if (_tcscmp(n, FSDB_FILE) == 0) + return -1; + + if (dir) { + if (n[0] == '.' && l == 1) + return -1; + if (n[0] == '.' && n[1] == '.' && l == 2) + return -1; + } + + if (a >= 'a' && a <= 'z') + a -= 32; + if (b >= 'a' && b <= 'z') + b -= 32; + if (c >= 'a' && c <= 'z') + c -= 32; + + s1[0] = 0; + s2[0] = 0; + ua_fs_copy(s1, MAX_DPATH, n, -1); + au_fs_copy(s2, MAX_DPATH, s1); + if (_tcscmp(s2, n) != 0) + return 1; + + if (currprefs.win32_filesystem_mangle_reserved_names) { + /* reserved dos devices */ + ll = 0; + if (a == 'A' && b == 'U' && c == 'X') + ll = 3; /* AUX */ + if (a == 'C' && b == 'O' && c == 'N') + ll = 3; /* CON */ + if (a == 'P' && b == 'R' && c == 'N') + ll = 3; /* PRN */ + if (a == 'N' && b == 'U' && c == 'L') + ll = 3; /* NUL */ + if (a == 'L' && b == 'P' && c == 'T' && (d >= '0' && d <= '9')) + ll = 4; /* LPT# */ + if (a == 'C' && b == 'O' && c == 'M' && (d >= '0' && d <= '9')) + ll = 4; /* COM# */ + /* AUX.anything, CON.anything etc.. are also illegal names */ + if (ll && (l == ll || (l > ll && n[ll] == '.'))) + return 3; + + /* spaces and periods at the end are a no-no */ + i = l - 1; + if (n[i] == '.' || n[i] == ' ') + return 1; + } + + /* these characters are *never* allowed */ + for (i = 0; i < NUM_EVILCHARS; i++) { + if (_tcschr(n, evilchars[i]) != 0) + return 2; + } + + return 0; /* the filename passed all checks, now it should be ok */ +} + + +static int fsdb_name_invalid_2(a_inode* aino, const char* n, int dir) { + int v = fsdb_name_invalid_2x(n, dir); + if (v <= 1 || !aino) + return v; + + try { + std::filesystem::path filePath = std::filesystem::path(aino->nname) / n; + + if (!std::filesystem::exists(filePath)) { + return 1; // File does not exist + } + + if (!std::filesystem::is_regular_file(filePath) && !std::filesystem::is_directory(filePath)) { + return 1; // Not a regular file or directory + } + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("fsdb_name_invalid_2: Filesystem error for '%s': %s", n, e.what()); + return 1; // Treat as invalid if an error occurs + } + + return 0; // Valid name +} + +int fsdb_name_invalid_dir(a_inode* aino, const TCHAR* n) { + int v = fsdb_name_invalid_2(aino, (const char*)n, 1); + if (v <= 0) + return v; + + SDL_Log("FILESYS: '%s' illegal filename", n); + return v; +} + + +int fsdb_mode_supported(const a_inode*) { + UNIMPLEMENTED(); + return 0; +} + + +TCHAR* fsdb_create_unique_nname(a_inode_struct*, char const*) { + UNIMPLEMENTED(); + return nullptr; +} + +int fsdb_mode_representable_p(a_inode_struct const*, int) { + UNIMPLEMENTED(); + return 0; +} + +int fsdb_name_invalid(a_inode_struct*, char const*) { + UNIMPLEMENTED(); + return 0; +} + + +void my_canonicalize_path(const TCHAR* path, TCHAR* out, int size) { + if (!path || !out || size <= 0) { + if (out && size > 0) { + out[0] = '\0'; + } + return; + } + + try { + // Use std::filesystem to canonicalize the path + std::filesystem::path inputPath(path); + + // Handle special cases for invalid or fake paths + if (path[0] == ':' || path[0] == '\0' || _tcscmp(path, _T("\\")) == 0 || _tcscmp(path, _T("/")) == 0) { + _tcsncpy(out, path, size); + out[size - 1] = '\0'; + return; + } + + // Skip network paths to prevent delays + if (path[0] == '\\' && path[1] == '\\') { + _tcsncpy(out, path, size); + out[size - 1] = '\0'; + return; + } + + // Canonicalize the path + std::filesystem::path canonicalPath = std::filesystem::weakly_canonical(inputPath); + std::string canonicalStr = canonicalPath.string(); + + // Copy the result to the output buffer + _tcsncpy(out, canonicalStr.c_str(), size - 1); + out[size - 1] = '\0'; + } catch (const std::filesystem::filesystem_error& e) { + // Handle errors by falling back to the original path + SDL_Log("my_canonicalize_path: Error canonicalizing path %s: %s", path, e.what()); + _tcsncpy(out, path, size); + out[size - 1] = '\0'; + } +} + + +bool my_resolvessymboliclink(TCHAR* linkfile, int size) { + if (!linkfile || size <= 0) { + return false; + } + + try { + std::filesystem::path linkPath(linkfile); + if (!std::filesystem::exists(linkPath) || !std::filesystem::is_symlink(linkPath)) { + return false; + } + + std::filesystem::path resolvedPath = std::filesystem::read_symlink(linkPath); + std::filesystem::path parentPath = linkPath.parent_path(); + std::filesystem::path fullPath = std::filesystem::absolute(parentPath / resolvedPath); + + std::string resolvedStr = fullPath.string(); + strncpy(linkfile, resolvedStr.c_str(), size - 1); + linkfile[size - 1] = '\0'; + + return true; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_resolvessymboliclink: Error resolving symbolic link %s: %s", linkfile, e.what()); + return false; + } +} + +TCHAR* fsdb_search_dir(const TCHAR* dirname, TCHAR* rel, TCHAR** relalt) { + *relalt = NULL; + try { + std::filesystem::path dirPath(dirname); + std::filesystem::path relPath(rel); + std::filesystem::path fullPath = dirPath / relPath; + + if (std::filesystem::exists(fullPath)) { + return my_strdup(rel); // Exact match + } + + // Check for *.lnk shortcut + std::filesystem::path shortcutPath = fullPath; + shortcutPath += ".lnk"; + + if (std::filesystem::exists(shortcutPath) && !std::filesystem::is_directory(shortcutPath)) { + TCHAR resolvedPath[MAX_DPATH]; + if (my_resolvessymboliclink((TCHAR*)shortcutPath.string().c_str(), MAX_DPATH)) { + std::filesystem::path resolvedFilePath(resolvedPath); + if (resolvedFilePath.filename() == relPath.filename()) { + return my_strdup(rel); // Exact match after resolving + } else { + *relalt = my_strdup((resolvedFilePath.filename().string() + ".lnk").c_str()); + return my_strdup(resolvedFilePath.filename().string().c_str()); + } + } + } + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("fsdb_search_dir: Error searching directory %s: %s", dirname, e.what()); + } + + return NULL; +} + + +int fsdb_exists(char const*) { + UNIMPLEMENTED(); + return 0; +} + + +static int read_uaefsdb(const TCHAR* dir, const TCHAR* name, uae_u8* fsdb) { + try { + // Construct the path to the .uaefsdb file + std::filesystem::path uaefsdbPath = make_uaefsdbpath(dir, name); + + if (fsdb_debug) { + write_log(_T("read_uaefsdb '%s'\n"), uaefsdbPath.string().c_str()); + } + + // Open the file using SDL_RWops + SDL_RWops* file = SDL_RWFromFile(uaefsdbPath.string().c_str(), "rb"); + if (!file) { + if (fsdb_debug) { + write_log(_T("->fail: Unable to open file: %s\n"), SDL_GetError()); + } + memset(fsdb, 0, UAEFSDB2_LEN); + return 0; + } + + // Read the file content into the buffer + size_t bytesRead = SDL_RWread(file, fsdb, 1, UAEFSDB2_LEN); + SDL_RWclose(file); + + if (bytesRead == UAEFSDB_LEN || bytesRead == UAEFSDB2_LEN) { + if (fsdb_debug) { + TCHAR *an, *nn, *co; + write_log(_T("->ok\n")); + an = au_fs((char*)fsdb + 5); + nn = au_fs((char*)fsdb + 262); + co = au_fs((char*)fsdb + 519); + write_log(_T("v=%02x flags=%08x an='%s' nn='%s' c='%s'\n"), fsdb[0], ((uae_u32*)(fsdb + 1))[0], an, nn, + co); + xfree(co); + xfree(nn); + xfree(an); + } + return 1; + } + + if (fsdb_debug) { + write_log(_T("->fail: Incomplete read, bytesRead=%zu\n"), bytesRead); + } + memset(fsdb, 0, UAEFSDB2_LEN); + return 0; + } catch (const std::filesystem::filesystem_error& e) { + if (fsdb_debug) { + write_log(_T("->fail: Filesystem error: %s\n"), e.what()); + } + memset(fsdb, 0, UAEFSDB2_LEN); + return 0; + } +} + + +uae_u32 filesys_parse_mask(uae_u32 mask) { + return mask ^ 0xf; +} + +static a_inode* aino_from_buf(a_inode* base, uae_u8* buf, int* winmode) { + uae_u32 mode; + a_inode* aino = (a_inode*)calloc(1, sizeof(a_inode)); + if (!aino) + return nullptr; + + uae_u8* buf2 = buf + 604; + mode = do_get_mem_long((uae_u32*)(buf + 1)); + buf += 5; + + if (buf2[0]) { + aino->aname = strdup((char*)buf2); + } else { + aino->aname = strdup((char*)buf); + } + buf += 257; + buf2 += 257 * 2; + + if (buf2[0]) { + aino->nname = build_nname(base->nname, (char*)buf2); + } else { + char* s = strdup((char*)buf); + aino->nname = build_nname(base->nname, s); + free(s); + } + buf += 257; + + aino->comment = *buf != '\0' ? strdup((char*)buf) : nullptr; + buf += 81; + + aino->amigaos_mode = mode; + *winmode = do_get_mem_long((uae_u32*)buf); + aino->dir = ((*winmode) & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0; + *winmode &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN; + aino->has_dbentry = 0; + aino->dirty = 0; + aino->db_offset = 0; + + try { + std::filesystem::path filePath(aino->nname); + if (!std::filesystem::exists(filePath)) { + SDL_Log("File does not exist: %s", aino->nname); + return aino; + } + aino->dir = std::filesystem::is_directory(filePath) ? 1 : 0; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("Error accessing file attributes for %s: %s", aino->nname, e.what()); + } + + return aino; +} + + +/* For an a_inode we have newly created based on a filename we found on the + * native fs, fill in information about this file/directory. */ +int fsdb_fill_file_attrs(a_inode* base, a_inode* aino) { + int winmode, oldamode; + uae_u8 fsdb[UAEFSDB2_LEN]; + int reset = 0; + + try { + std::filesystem::path filePath(aino->nname); + if (!std::filesystem::exists(filePath)) { + SDL_Log("File does not exist: %s", aino->nname); + return 0; + } + + aino->dir = std::filesystem::is_directory(filePath) ? 1 : 0; + + if (std::filesystem::is_symlink(filePath)) { + aino->softlink = 1; + } + + int perms = (int)std::filesystem::status(filePath).permissions(); + bool isHidden = filePath.filename().string().front() == '.'; + + if ((base->volflags & MYVOLUMEINFO_STREAMS) && read_uaefsdb(aino->nname, nullptr, fsdb)) { + aino->amigaos_mode = do_get_mem_long((uae_u32*)(fsdb + 1)); + free(aino->comment); + aino->comment = nullptr; + if (fsdb[5 + 2 * 257]) { + aino->comment = strdup((char*)fsdb + 5 + 2 * 257); + } + free(aino_from_buf(base, fsdb, &winmode)); + if (winmode == perms) { + return 1; + } + SDL_Log("FS: '%s' protection flags edited from external source\n", aino->nname); + reset = 1; + } + + oldamode = aino->amigaos_mode; + aino->amigaos_mode = A_FIBF_EXECUTE | A_FIBF_READ; + if (((int)perms & (int)std::filesystem::perms::owner_write) == 0) { + aino->amigaos_mode |= A_FIBF_WRITE | A_FIBF_DELETE; + } + if (isHidden) { + aino->amigaos_mode |= A_FIBF_HIDDEN; + } + aino->amigaos_mode = filesys_parse_mask(aino->amigaos_mode); + aino->amigaos_mode |= oldamode & A_FIBF_SCRIPT; + + if (reset && (base->volflags & MYVOLUMEINFO_STREAMS)) { + create_uaefsdb(aino, fsdb, (int)perms); + write_uaefsdb(aino->nname, fsdb); + } + + return 1; + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("Error filling file attributes for %s: %s", aino->nname, e.what()); + return 0; + } +} + +struct my_openfile_s { + SDL_RWops* h = nullptr; +}; + +void my_close(struct my_openfile_s* mos) { + if (!mos) + return; + if (mos->h) { + SDL_RWclose(mos->h); + mos->h = nullptr; + } + free(mos); +} + +bool my_createshortcut(const char* /*src*/, const char* /*dst*/, const char* /*desc*/) { + // Cross-platform shortcut creation not implemented + return false; +} + +bool my_isfilehidden(const char* path) { +#ifdef _WIN32 + DWORD attributes = GetFileAttributesA(path); + return (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_HIDDEN); +#else + // On POSIX, hidden files start with '.' + const char* filename = strrchr(path, '/'); + filename = filename ? filename + 1 : path; + return filename[0] == '.'; +#endif +} + +int my_issamevolume(const char* path1, const char* path2, char* volume) { + // Use SDL2 and std::filesystem for cross-platform support + if (!path1 || !path2) + return 0; + + // Normalize paths using SDL and std::filesystem + std::string abs1, abs2; + { + char* base1 = SDL_GetBasePath(); + char* base2 = SDL_GetBasePath(); + try { + abs1 = std::filesystem::absolute(path1).string(); + abs2 = std::filesystem::absolute(path2).string(); + } catch (...) { + if (base1) + SDL_free(base1); + if (base2) + SDL_free(base2); + return 0; + } + if (base1) + SDL_free(base1); + if (base2) + SDL_free(base2); + } + +#if defined(_WIN32) + // On Windows, use the root drive letter as the volume + char root1[MAX_PATH] = {0}, root2[MAX_PATH] = {0}; + if (!GetVolumePathNameA(abs1.c_str(), root1, MAX_PATH) || !GetVolumePathNameA(abs2.c_str(), root2, MAX_PATH)) + return 0; + if (volume) + strncpy(volume, root1, MAX_PATH - 1); + return _stricmp(root1, root2) == 0; +#else + // On POSIX, compare device IDs + struct stat st1, st2; + if (stat(abs1.c_str(), &st1) != 0 || stat(abs2.c_str(), &st2) != 0) + return 0; + if (volume) + volume[0] = 0; + return st1.st_dev == st2.st_dev; +#endif +} + +uae_s64 my_lseek(struct my_openfile_s* mos, uae_s64 offset, int whence) { + if (!mos || !mos->h) + return -1; + Sint64 result = SDL_RWseek(mos->h, offset, whence); + return (result < 0) ? -1 : (uae_s64)result; +} + +uae_s64 my_fsize(struct my_openfile_s* mos) { + if (!mos || !mos->h) + return -1; + Sint64 size = SDL_RWsize(mos->h); + return (size < 0) ? -1 : (uae_s64)size; +} + + +int my_mkdir(const TCHAR* name) { + try { + std::filesystem::path dirPath(name); + if (std::filesystem::create_directory(dirPath)) { + return 0; // Success + } else { + return -1; // Directory already exists or failed + } + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_mkdir: Error creating directory %s: %s", name, e.what()); + return -1; // Error + } +} + + +struct my_openfile_s* my_open(const TCHAR* name, int flags) { + struct my_openfile_s* mos = (struct my_openfile_s*)calloc(1, sizeof(struct my_openfile_s)); + if (!mos) + return NULL; + + const char* mode = nullptr; + if ((flags & O_RDWR) == O_RDWR) { + if (flags & O_CREAT) + mode = "w+b"; + else + mode = "r+b"; + } else if (flags & O_WRONLY) { + if (flags & O_CREAT) + mode = "wb"; + else + mode = "rb"; // fallback, but writing to read-only is not allowed + } else { + mode = "rb"; + } + + // SDL_RWFromFile expects UTF-8 on all platforms + mos->h = SDL_RWFromFile(name, mode); + + if (!mos->h) { + free(mos); + return NULL; + } + return mos; +} + + +FILE* my_opentext(const char* name) { + FILE* f; + uae_u8 tmp[4]; + size_t v; + + f = _tfopen(name, _T("rb")); + if (!f) + return NULL; + v = fread(tmp, 1, sizeof tmp, f); + fclose(f); + if (v == 4) { + if (tmp[0] == 0xef && tmp[1] == 0xbb && tmp[2] == 0xbf) + return _tfopen(name, _T("r, ccs=UTF-8")); + if (tmp[0] == 0xff && tmp[1] == 0xfe) + return _tfopen(name, _T("r, ccs=UTF-16LE")); + } + return _tfopen(name, _T("r")); +} + +unsigned int my_read(struct my_openfile_s* mos, void* b, unsigned int size) { + if (!mos || !mos->h || !b || size == 0) + return 0; + Sint64 result = SDL_RWread(mos->h, b, 1, size); + if (result <= 0) + return 0; + return static_cast(result); +} + +unsigned int my_write(struct my_openfile_s* mos, void* b, unsigned int size) { + if (!mos || !mos->h || !b || size == 0) + return 0; + Sint64 result = SDL_RWwrite(mos->h, b, 1, size); + if (result <= 0) + return 0; + return static_cast(result); +} + +void my_setfilehidden(const char* path, bool hidden) { + try { + std::filesystem::path filePath(path); + if (!std::filesystem::exists(filePath)) { + SDL_Log("my_setfilehidden: File does not exist: %s", path); + return; + } + + std::string filename = filePath.filename().string(); + std::filesystem::path parentPath = filePath.parent_path(); + + if (hidden && filename[0] != '.') { + // Add a dot to make the file hidden + std::filesystem::path newPath = parentPath / ("." + filename); + std::filesystem::rename(filePath, newPath); + } else if (!hidden && filename[0] == '.') { + // Remove the dot to unhide the file + std::filesystem::path newPath = parentPath / filename.substr(1); + std::filesystem::rename(filePath, newPath); + } + } catch (const std::filesystem::filesystem_error& e) { + SDL_Log("my_setfilehidden: Error setting hidden attribute for %s: %s", path, e.what()); + } +} diff --git a/src/generic/base.h b/src/generic/base.h index 88429f62..b7a23e40 100644 --- a/src/generic/base.h +++ b/src/generic/base.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #define SAFE_DELETE(p) \ diff --git a/src/generic/thread.h b/src/generic/thread.h index 662b35e9..da7de2b2 100644 --- a/src/generic/thread.h +++ b/src/generic/thread.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include namespace qd { namespace thread { @@ -77,5 +78,10 @@ class Event { }; // class thread::Event ////////////////////////////////////////////////////////////////////////// + +inline bool isMainThread() { + return SDL_ThreadID() == SDL_GetThreadID(nullptr); +} + }; // namespace thread }; // namespace qd diff --git a/src/hardfile_host.cpp b/src/hardfile_host.cpp index 209012fe..e546d122 100644 --- a/src/hardfile_host.cpp +++ b/src/hardfile_host.cpp @@ -104,7 +104,7 @@ static void rdbdump(FILE* h, uae_u64 offset, uae_u8* buf, int blocksize) { break; size_t outlen = fread(buf, 1, blocksize, h); if (outlen != blocksize) { - write_log("rdbdump: warning: read %d bytes (not blocksize %d)\n", outlen, blocksize); + write_log("rdbdump: warning: read %u bytes (not blocksize %u)\n", (uint32_t)outlen, (uint32_t)blocksize); } fwrite(buf, 1, blocksize, f); offset += blocksize; @@ -623,7 +623,7 @@ static int hdf_write_2(struct hardfiledata* hfd, void* buffer, uae_u64 offset, i outlen = fwrite(hfd->cache, 1, len, hfd->handle->h); // fflush(hfd->handle->h); if (g_debug) { - write_log("wrote %u bytes (wanted %d) at offset %llx\n", outlen, len, offset); + write_log("wrote %u bytes (wanted %d) at offset %llx\n", (uint32_t)outlen, len, offset); } const TCHAR* name = hfd->emptyname == NULL ? _T("") : hfd->emptyname; if (offset == 0) { @@ -649,7 +649,8 @@ int hdf_write_target(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int uae_u8* p = (uae_u8*)buffer; if (g_debug) { - write_log("hdf_write_target off %llx len %d virtual size %lld\n", offset, len, hfd->virtual_size); + write_log("hdf_write_target off %llx len %d virtual size %lld\n", (int64_t)offset, len, + (int64_t)hfd->virtual_size); } if (hfd->drive_empty) { if (g_debug) { @@ -690,10 +691,10 @@ int hdf_resize_target(struct hardfiledata* hfd, uae_u64 newsize) { uae_log( "hdf_resize_target: failed to write byte at position " "%lld errno %d\n", - newsize - 1, errno); + (uae_s64)newsize - 1, (int)errno); return 0; } - uae_log("hdf_resize_target: %lld -> %lld\n", hfd->physsize, newsize); + uae_log("hdf_resize_target: %lld -> %lld\n", (int64_t)hfd->physsize, (int64_t)newsize); hfd->physsize = newsize; return 1; } diff --git a/src/quaesar.cpp b/src/quaesar.cpp index 4154c6dd..a19702e3 100644 --- a/src/quaesar.cpp +++ b/src/quaesar.cpp @@ -29,6 +29,10 @@ qd::App* app = nullptr; extern void real_main(int argc, TCHAR** argv); extern void keyboard_settrans(); +namespace qd { +extern void quae_parse_cmdline(int argc, TCHAR** argv); +}; // namespace qd + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TODO: Move this somewhere else @@ -49,24 +53,42 @@ bool ends_with(const char* str, const char* suffix) { } -int uae_thread_main_func(void* /*args*/ = nullptr) { - real_main(0, nullptr); +static std::vector uaeCliArgVals; + +int uae_thread_main_func(void*) { + std::vector argv; + argv.push_back("quasar.exe"); + argv.reserve(uaeCliArgVals.size() * 2 + 1); + for (const std::string& s : uaeCliArgVals) { + argv.push_back("-s"); + argv.push_back(s.c_str()); + } + qd::quae_parse_cmdline((int)argv.size(), const_cast(&argv[0])); + + ::real_main(0, nullptr); return 0; } // Quaesar main int SDL_main(int argc, char* argv[]) { + for (int i = 0; i < argc; ++i) + SDL_Log("arg_%i: '%s'", i, argv[i]); + syncbase = 1000000; app = qd::App::get(); Options options; CLI::App cliApp{"Quaesar"}; - - cliApp.add_option("input", options.input, "Executable or image file (adf, dms)")->check(CLI::ExistingFile); - cliApp.add_option("-k,--kickstart", options.kickstart, "Path to the kickstart ROM")->check(CLI::ExistingFile); + cliApp.allow_extras(); + cliApp.add_option("input", options.input, "Executable or image file (adf, dms)"); // ->check(CLI::ExistingFile); + cliApp.add_option("-k,--kickstart", options.kickstart, "Path to the kickstart ROM"); // ->check(CLI::ExistingFile); cliApp.add_option("--serial_port", options.serial_port, "Serial port path"); - CLI11_PARSE(cliApp, argc, argv); + cliApp.add_option("-s", uaeCliArgVals, + "key followed by the original WinUAE commands. Example:\n" + " quaesar.exe -k c:\\Amiga\\KICK13.rom -s filesystem=rw,dh0:c:\\Amiga\\hd0"); + + cliApp.parse(argc, argv); keyboard_settrans(); default_prefs(&currprefs, true, 0); @@ -75,8 +97,13 @@ int SDL_main(int argc, char* argv[]) { if (!options.input.empty()) { // TODO: cleanup if (ends_with(options.input.c_str(), ".exe") || !ends_with(options.input.c_str(), ".adf")) { - Adf::create_for_exefile(options.input.c_str()); - strcpy(currprefs.floppyslots[0].df, "dummy.adf"); + if (FILE* check_file = fopen(options.input.c_str(), "rb")) { + fclose(check_file); + Adf::create_for_exefile(options.input.c_str()); + strcpy(currprefs.floppyslots[0].df, "dummy.adf"); + } else { + SDL_Log("can't open input file:'%s'", options.input.c_str()); + } } else { strcpy(currprefs.floppyslots[0].df, options.input.c_str()); } @@ -95,6 +122,8 @@ int SDL_main(int argc, char* argv[]) { // currprefs.turbo_emulation = 1; // it disables sound currprefs.sound_stereo_separation = 0; currprefs.uaeboard = 1; + currprefs.win32_filesystem_mangle_reserved_names = true; // required for FS + currprefs.filesys_custom_uaefsdb = false; // hack to not implement 'custom_fsdb_*' funcs now strcpy(currprefs.romfile, options.kickstart.c_str()); diff --git a/src/shortcut/shortcut_mgr.cpp b/src/shortcut/shortcut_mgr.cpp index b21e68c3..54e52897 100644 --- a/src/shortcut/shortcut_mgr.cpp +++ b/src/shortcut/shortcut_mgr.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include @@ -25,6 +26,11 @@ eastl::string Shortcut::toString() const { return result; } + +Shortcut::~Shortcut() { +} + + ImGuiKeyChord Shortcut::getChord() const { ImGuiKeyChord nChord = 0; const Shortcut::Keys& keysList = getKeys(); @@ -74,7 +80,13 @@ bool ShortcutsMgr::triggerShortcut(qd::shortcut::EId id) { } +ShortcutsMgr::~ShortcutsMgr() { + done(); +} + + void ShortcutsMgr::init() { + assert(qd::thread::isMainThread()); done(); for (int id = 0; id < (int)shortcut::EId::MAX_COUNT; ++id) { Shortcut* curShortcut = shortcut::makeInstance((shortcut::EId)id); @@ -91,6 +103,7 @@ void ShortcutsMgr::init() { void ShortcutsMgr::done() { + assert(qd::thread::isMainThread()); while (!mShortcuts.empty()) { auto& p = mShortcuts.back(); delete p.second; diff --git a/src/shortcut/shortcut_mgr.h b/src/shortcut/shortcut_mgr.h index a257dce5..6ad171ca 100644 --- a/src/shortcut/shortcut_mgr.h +++ b/src/shortcut/shortcut_mgr.h @@ -49,6 +49,7 @@ class Shortcut { public: Shortcut() = default; + ~Shortcut(); qd::shortcut::EId getId() const { return mId; } @@ -93,9 +94,7 @@ class ShortcutsMgr { return triggerShortcut(shortcut->getId()); } - ~ShortcutsMgr() { - done(); - } + ~ShortcutsMgr(); private: ShortcutsMgr() { diff --git a/src/sysconfig.h b/src/sysconfig.h index 5f2cd130..b1511fa4 100644 --- a/src/sysconfig.h +++ b/src/sysconfig.h @@ -1,13 +1,22 @@ #ifndef WINUAE_SYSCONFIG_H #define WINUAE_SYSCONFIG_H -// #include #ifdef _WIN32 #define ftello64 _ftelli64 #define fseeko64 _fseeki64 +#elif defined(__APPLE__) +#define _ftelli64 ftell +#define _fseeki64 fseek +#define _fseeko64 fseeko +#define fseeko64 fseeko +#define ftello64 ftell +#else // (LINUX OR UNIX) +#define _ftelli64 ftello64 +#define _fseeki64 fseeko64 #endif + #ifndef _WIN32 #include "winuae_compat.h" #endif @@ -608,13 +617,33 @@ typedef long uae_atomic; #define FSDB_DIR_SEPARATOR '\\' #define FSDB_DIR_SEPARATOR_S _T("\\") + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#define FILEFLAG_DIR 0x1 +#define FILEFLAG_ARCHIVE 0x2 +#define FILEFLAG_WRITE 0x4 +#define FILEFLAG_READ 0x8 +#define FILEFLAG_EXECUTE 0x10 +#define FILEFLAG_SCRIPT 0x20 +#define FILEFLAG_PURE 0x40 + +#define HWND uint32_t +#define HRESULT uint32_t +#define WPARAM uint16_t +#define LPARAM uint32_t +#define BOOL int; +#define USHORT uint16_t +#endif + + /* Define to 1 if `S_un' is a member of `struct in_addr'. */ // #define HAVE_STRUCT_IN_ADDR_S_UN 1 -#define UNIMPLEMENTED() \ - do { \ - fprintf(stderr, "Function '%s' is unimplemented. Exiting...\n", __func__); \ - exit(EXIT_FAILURE); \ +#define UNIMPLEMENTED() \ + do { \ + fprintf(stderr, "ERROR: Function '%s' NOT IMPLEMENTED. Exiting...\n", __func__); \ + assert(0 && "FUNCTION NOT IMPLEMENTED"); \ + exit(EXIT_FAILURE); \ } while (0) // #define TRACE() do { printf("%s\n", __func__); } while (0) diff --git a/src/ui/gui_manager.cpp b/src/ui/gui_manager.cpp index 30b9c057..8c405b04 100644 --- a/src/ui/gui_manager.cpp +++ b/src/ui/gui_manager.cpp @@ -1,5 +1,5 @@ #include "gui_manager.h" -#include <../../external/dear_imgui/imgui_internal.h> +#include #include #include @@ -13,7 +13,7 @@ GuiManager::GuiManager(Debugger* in_dbg) : dbg(in_dbg) { // create all windows UiViewCreate cv(this); auto viewMgr = UiViewClassRegistry::get(); - for (auto it : viewMgr->m_classInfoMap) { + for (auto it : viewMgr->mClassInfoMap) { UiView* curView = viewMgr->makeInstance(it.first, &cv); addView(curView); } @@ -29,13 +29,10 @@ void GuiManager::drawImGuiMainFrame() { ImGui::SetNextWindowPos(viewport->WorkPos); ImGui::SetNextWindowSize(viewport->WorkSize); ImGui::SetNextWindowViewport(viewport->ID); - // ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - // ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGuiWindowFlags wndFlags = 0; wndFlags |= ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; wndFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; - // wndFlags |= ImGuiWindowFlags_MenuBar; bool open = true; if (ImGui::Begin("Quaesar debugger", &open, wndFlags)) { @@ -43,7 +40,6 @@ void GuiManager::drawImGuiMainFrame() { _drawMainToolBar(); _drawDebuggerWindows(); } - // ImGui::PopStyleVar(0); ImGui::End(); } @@ -52,12 +48,10 @@ void GuiManager::_drawMainToolBar() { ImGuiIO& io = ImGui::GetIO(); ImGuiWindowFlags wndFlags = 0; wndFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar; - // wndFlags |= ImGuiWindowFlags_MenuBar; ImVec2 rgn = ImGui::GetContentRegionAvail(); if (ImGui::BeginChild("ToolBar", ImVec2(rgn.x, 20.f), ImGuiChildFlags_None, wndFlags)) { ImGuiWindow* window = ImGui::GetCurrentWindow(); - // ImGui::BeginMenuBar(); window->DC.LayoutType = ImGuiLayoutType_Horizontal; Debugger* dbg = getDbg(); @@ -80,11 +74,12 @@ void GuiManager::_drawMainToolBar() { uv0 = ImVec2(0.0f, 0.0f); // TODO ICONS uv1 = ImVec2(uv0.x + size.x / my_tex_w, uv1.x + size.y / my_tex_h); - pCurShortcut = shMgr->getShortcut(shortcut::EId::DebugTraceStepInto); - if (ImGui::ImageButton("##StepInto", my_tex_id, size, uv0, uv1, ImVec4(0, 0, 0, 1))) { - shMgr->triggerShortcut(pCurShortcut); + if (pCurShortcut = shMgr->getShortcut(shortcut::EId::DebugTraceStepInto)) { + if (ImGui::ImageButton("##StepInto", my_tex_id, size, uv0, uv1, ImVec4(0, 0, 0, 1))) { + shMgr->triggerShortcut(pCurShortcut); + } + ImGui::SetItemTooltipV(pCurShortcut->toString().c_str(), nullptr); } - ImGui::SetItemTooltipV(pCurShortcut->toString().c_str(), nullptr); // ImGui::Separator(); // @@ -105,8 +100,6 @@ void GuiManager::_drawMainToolBar() { if (ImGui::Button("Wait Scanlines")) { shMgr->triggerShortcut(pCurShortcut); } - - // ImGui::EndMenuBar(); } ImGui::EndChild(); ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal); diff --git a/src/ui/gui_manager.h b/src/ui/gui_manager.h index bb4364b8..8215c48e 100644 --- a/src/ui/gui_manager.h +++ b/src/ui/gui_manager.h @@ -1,13 +1,16 @@ #pragma once #include #include +#include #include + +FORWARD_DECLARATION_2(qd, UiView); +FORWARD_DECLARATION_3(qd, action, Action); + + namespace qd { -class UiView; -namespace action { -class Action; -}; + class GuiManager { eastl::vector windows; diff --git a/uae_src/debug.cpp b/uae_src/debug.cpp index 39c6ca65..5cbdff86 100644 --- a/uae_src/debug.cpp +++ b/uae_src/debug.cpp @@ -52,7 +52,6 @@ #include "readcpu.h" #include "cputbl.h" #include "keybuf.h" -#include static int trace_mode; static uae_u32 trace_param[3]; diff --git a/uae_src/filesys.cpp b/uae_src/filesys.cpp index cfd3266c..d3dfa47e 100644 --- a/uae_src/filesys.cpp +++ b/uae_src/filesys.cpp @@ -73,7 +73,7 @@ #endif #define TRACING_ENABLED 1 -int log_filesys = 0; +int log_filesys = 1; // debug #define TRAPMD 1 diff --git a/uae_src/main.cpp b/uae_src/main.cpp index 92284345..d402d59d 100644 --- a/uae_src/main.cpp +++ b/uae_src/main.cpp @@ -1308,3 +1308,13 @@ int main (int argc, TCHAR **argv) uae_u8 singlefile_config[50000] = { "_CONFIG_STARTS_HERE" }; uae_u8 singlefile_data[1500000] = { "_DATA_STARTS_HERE" }; #endif + + +////////////////////////////////////////////////////////////////////////// +namespace qd { +void quae_parse_cmdline(int argc, TCHAR** argv) +{ + ::parse_cmdline(argc, argv); +} +}; // namespace qd +////////////////////////////////////////////////////////////////////////// diff --git a/uae_src/traps.cpp b/uae_src/traps.cpp index 215b16ce..94602439 100644 --- a/uae_src/traps.cpp +++ b/uae_src/traps.cpp @@ -110,6 +110,9 @@ uaecptr find_trap (const TCHAR *name) */ unsigned int define_trap (TrapHandler handler_func, int flags, const TCHAR *name) { + // DART + write_log("UAE traps:'%s'", name); + if (trap_count == MAX_TRAPS) { write_log (_T("Ran out of emulator traps\n")); abort ();