cmake_minimum_required(VERSION 3.24)
project(DKRLegacyModTests LANGUAGES C CXX)
set(BUILD_TESTING ON)
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
get_filename_component(DKRPORT_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE)
include("${DKRPORT_ROOT}/runtime-recomp/cmake/LegacyMods.cmake")
enable_testing()
add_executable(DKRLegacyCacheCapacityTests ../legacy_cache_capacity_tests.cpp)
target_link_libraries(DKRLegacyCacheCapacityTests PRIVATE DKRLegacyModCore)
add_executable(DKRLauncherRecoveryPolicyTests ../launcher_recovery_policy_tests.cpp)
target_include_directories(DKRLauncherRecoveryPolicyTests PRIVATE ../../src/game)
add_test(NAME DKRLauncherRecoveryPolicyTests COMMAND DKRLauncherRecoveryPolicyTests)
add_executable(DKROnlineGamePakTests ../online_game_pak_tests.cpp)
target_link_libraries(DKROnlineGamePakTests PRIVATE DKRLegacyImportLibrary DKRCustomTracksCore)
add_test(NAME DKROnlineGamePakTests COMMAND DKROnlineGamePakTests)
add_executable(DKROnlineModMusicTests ../online_mod_music_tests.cpp)
target_link_libraries(DKROnlineModMusicTests PRIVATE DKRLegacyModLaunch)
add_test(NAME DKROnlineModMusicTests COMMAND DKROnlineModMusicTests)
add_executable(DKRNativeModWorldTests ../native_mod_world_tests.cpp ../native_mod_world_test_boundaries.cpp ../../src/game/runtime_legacy_mods.cpp)
target_link_libraries(DKRNativeModWorldTests PRIVATE DKRLegacyGuestIO DKRLegacyModLaunch)
target_include_directories(DKRNativeModWorldTests PRIVATE ../../src/game
    "${DKRPORT_ROOT}/extern/n64-modern-runtime/librecomp/include"
    "${DKRPORT_ROOT}/extern/n64-modern-runtime/ultramodern/include"
    "${DKRPORT_ROOT}/extern/n64-modern-runtime/thirdparty/concurrentqueue")
if(MSVC)
    target_compile_options(DKRNativeModWorldTests PRIVATE /EHs /EHc-)
endif()
add_executable(DKROwnedModBoundaryTests ../owned_mod_boundary_tests.cpp ../owned_mod_boundary_guest.c ../replay_probe/probe_bridge.c)
target_include_directories(DKROwnedModBoundaryTests PRIVATE .. ../../src/game "${DKRPORT_ROOT}/extern/n64-modern-runtime/N64Recomp/include")
add_test(NAME DKROwnedModBoundaryTests COMMAND DKROwnedModBoundaryTests)
add_executable(DKROnlineModProfileTests ../online_mod_profile_tests.cpp ../../src/game/rom_revision.cpp ../../src/game/startup_performance.cpp)
add_executable(DKROnlineModSyncTests ../online_mod_sync_tests.cpp ../../src/game/rom_revision.cpp ../../src/game/startup_performance.cpp)
target_link_libraries(DKROnlineModSyncTests PRIVATE DKRLegacyImportLibrary DKRLegacyModLaunch)
target_include_directories(DKROnlineModSyncTests PRIVATE "${DKRPORT_ROOT}/extern/n64-modern-runtime/thirdparty")
target_link_libraries(DKROnlineModProfileTests PRIVATE DKRLegacyImportLibrary DKROnlineModPreparation DKRLegacyModLaunch)
target_include_directories(DKROnlineModProfileTests PRIVATE "${DKRPORT_ROOT}/extern/n64-modern-runtime/thirdparty")
add_test(NAME DKROnlineModProfileTests COMMAND DKROnlineModProfileTests)
add_executable(DKROnlineModTransferTests ../online_mod_transfer_tests.cpp)
target_link_libraries(DKROnlineModTransferTests PRIVATE DKRLegacyModCore)
add_test(NAME DKROnlineModTransferTests COMMAND DKROnlineModTransferTests)
add_executable(DKROnlineModManifestTests ../online_mod_manifest_tests.cpp)
target_link_libraries(DKROnlineModManifestTests PRIVATE DKRLegacyImportLibrary)
add_test(NAME DKROnlineModManifestTests COMMAND DKROnlineModManifestTests)
add_executable(DKRLegacyCharacterAiTests ../legacy_character_ai_tests.cpp)
target_link_libraries(DKRLegacyCharacterAiTests PRIVATE DKRLegacyGuestIO)
add_test(NAME DKRLegacyCharacterAiTests COMMAND DKRLegacyCharacterAiTests)
add_executable(DKRLegacyCharacterPresentationTests ../legacy_character_presentation_tests.cpp)
target_link_libraries(DKRLegacyCharacterPresentationTests PRIVATE DKRLegacyGuestIO)
add_test(NAME DKRLegacyCharacterPresentationTests COMMAND DKRLegacyCharacterPresentationTests)
add_executable(DKRLegacyModManagementTests ../legacy_mod_management_tests.cpp)
target_link_libraries(DKRLegacyModManagementTests PRIVATE DKRLegacyImportLibrary)
add_test(NAME DKRLegacyModManagementTests COMMAND DKRLegacyModManagementTests)
set_tests_properties(DKRLegacyModManagementTests PROPERTIES TIMEOUT 90)
set(_mod_imgui "${DKRPORT_ROOT}/extern/rt64/src/contrib/imgui")
add_executable(DKRLegacyModBrowserUiTests ../legacy_mod_browser_ui_tests.cpp
    "${_mod_imgui}/imgui.cpp" "${_mod_imgui}/imgui_draw.cpp"
    "${_mod_imgui}/imgui_widgets.cpp" "${_mod_imgui}/imgui_tables.cpp"
    ../../src/game/generated/racing_banana_font.c ../../src/game/generated/jumpman_font.c
    ../../src/game/generated/selawik_font.c)
target_include_directories(DKRLegacyModBrowserUiTests PRIVATE "${_mod_imgui}" ../../src/game)
target_link_libraries(DKRLegacyModBrowserUiTests PRIVATE DKRLegacyImportLibrary)
if(MSVC)
    target_compile_options(DKRLegacyModBrowserUiTests PRIVATE /UNDEBUG)
else()
    target_compile_options(DKRLegacyModBrowserUiTests PRIVATE -UNDEBUG)
endif()
add_test(NAME DKRLegacyModBrowserUiTests COMMAND DKRLegacyModBrowserUiTests)
set_tests_properties(DKRLegacyModBrowserUiTests PROPERTIES TIMEOUT 90)
add_executable(DKRLegacyModLibraryTests ../legacy_mod_library_tests.cpp ../../src/game/dkr_save_codec.cpp)
target_link_libraries(DKRLegacyModLibraryTests PRIVATE DKRLegacyModLaunch)
add_test(NAME DKRLegacyModLibraryTests COMMAND DKRLegacyModLibraryTests "$<TARGET_FILE:DKRLegacyModWorker>")
set_tests_properties(DKRLegacyModLibraryTests PROPERTIES TIMEOUT 60)
find_package(Python3 COMPONENTS Interpreter REQUIRED)
add_test(NAME DKRLegacyModPipelineGuards COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/../legacy_mod_pipeline_tests.py")
add_executable(DKRLegacyDkrmapArtworkTests ../legacy_dkrmap_artwork_tests.cpp ../../src/game/dkr_save_codec.cpp)
target_link_libraries(DKRLegacyDkrmapArtworkTests PRIVATE DKRLegacyModLaunch)
add_test(NAME DKRLegacyDkrmapArtworkTests COMMAND DKRLegacyDkrmapArtworkTests)
# The bank checks need an owned ROM; it is never part of a public fixture.
set(DKR_LEGACY_TEST_ROM "" CACHE FILEPATH "Owned US v1.0/v1.1 ROM for ROM-backed legacy checks")
if(NOT DKR_LEGACY_TEST_ROM STREQUAL "")
    add_test(NAME DKRLegacyDkrmapArtworkRomTests
             COMMAND DKRLegacyDkrmapArtworkTests "${DKR_LEGACY_TEST_ROM}")
endif()
add_executable(DKRLegacyModTests ../legacy_mod_tests.cpp)
target_link_libraries(DKRLegacyModTests PRIVATE DKRLegacyModCore DKRLegacyModProcess)
add_test(NAME DKRLegacyModTests COMMAND DKRLegacyModTests)
add_executable(DKRLegacyTrackArtifactTests ../legacy_track_artifact_tests.cpp)
target_link_libraries(DKRLegacyTrackArtifactTests PRIVATE DKRLegacyModCore)
add_test(NAME DKRLegacyTrackArtifactTests COMMAND DKRLegacyTrackArtifactTests)
set_tests_properties(DKRLegacyModTests PROPERTIES TIMEOUT 60)
add_executable(DKRLegacyModInspect ../legacy_mod_inspect.cpp)
target_link_libraries(DKRLegacyModInspect PRIVATE DKRLegacyModCore)
add_executable(DKRLegacyModCorpusTests ../legacy_mod_corpus_tests.cpp)
add_executable(DKRLegacyCompatibilityTests ../legacy_compatibility_tests.cpp)
target_link_libraries(DKRLegacyCompatibilityTests PRIVATE DKRLegacyImportLibrary)
target_link_libraries(DKRLegacyModCorpusTests PRIVATE DKRLegacyModCore DKRLegacyModProcess)
add_executable(DKRLegacyImportLibraryTests ../legacy_import_library_tests.cpp)
target_link_libraries(DKRLegacyImportLibraryTests PRIVATE DKRLegacyImportLibrary)
add_test(NAME DKRLegacyImportLibraryTests COMMAND DKRLegacyImportLibraryTests "$<TARGET_FILE:DKRLegacyModWorker>")
set_tests_properties(DKRLegacyImportLibraryTests PROPERTIES TIMEOUT 60)
add_executable(DKRLegacyTrackCatalogTests ../legacy_track_catalog_tests.cpp)
target_link_libraries(DKRLegacyTrackCatalogTests PRIVATE DKRLegacyImportLibrary)
add_test(NAME DKRLegacyTrackCatalogTests COMMAND DKRLegacyTrackCatalogTests "$<TARGET_FILE:DKRLegacyModWorker>")
add_executable(DKRLegacyTrackMenuTests ../legacy_track_menu_tests.cpp)
target_link_libraries(DKRLegacyTrackMenuTests PRIVATE DKRLegacyModCore)
add_test(NAME DKRLegacyTrackMenuTests COMMAND DKRLegacyTrackMenuTests)
add_executable(DKRLegacyTrackMenuAdapterTests ../legacy_track_menu_adapter_tests.cpp)
target_link_libraries(DKRLegacyTrackMenuAdapterTests PRIVATE DKRLegacyGuestIO)
add_test(NAME DKRLegacyTrackMenuAdapterTests COMMAND DKRLegacyTrackMenuAdapterTests)
add_executable(DKRLegacyCharacterTests ../legacy_character_tests.cpp)
target_link_libraries(DKRLegacyCharacterTests PRIVATE DKRLegacyModCore)
add_test(NAME DKRLegacyCharacterTests COMMAND DKRLegacyCharacterTests)
add_executable(DKRLegacyCharacterAudioTests ../legacy_character_audio_tests.cpp)
target_link_libraries(DKRLegacyCharacterAudioTests PRIVATE DKRLegacyModCore)
add_test(NAME DKRLegacyCharacterAudioTests COMMAND DKRLegacyCharacterAudioTests)
add_executable(DKRLegacyCharacterCatalogTests ../legacy_character_catalog_tests.cpp)
target_link_libraries(DKRLegacyCharacterCatalogTests PRIVATE DKRLegacyImportLibrary)
add_test(NAME DKRLegacyCharacterCatalogTests COMMAND DKRLegacyCharacterCatalogTests "$<TARGET_FILE:DKRLegacyModWorker>")
add_executable(DKRLegacyCharacterMenuTests ../legacy_character_menu_tests.cpp)
target_link_libraries(DKRLegacyCharacterMenuTests PRIVATE DKRLegacyGuestIO)
add_test(NAME DKRLegacyCharacterMenuTests COMMAND DKRLegacyCharacterMenuTests)

set(DKR_LEGACY_MENU_PIPELINE_ROOT "" CACHE PATH "Private regenerated native-menu qualification sources")
if(NOT DKR_LEGACY_MENU_PIPELINE_ROOT STREQUAL "")
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyMenuGuestV${rev})
        set(generated "${DKR_LEGACY_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_menu_guest_pipeline_tests.cpp "${generated}/bgload_start.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
endif()

# Optional regenerated character function; input remains read-only.
set(DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT "" CACHE PATH "Private regenerated additive character-menu qualification sources")
if(NOT DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT STREQUAL "")
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacySpawnAssetTypeGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_spawn_asset_type_guest_tests.cpp "${generated}/spawn_object.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}" ../../src/game/mods)
        target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyAssetCapacityGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_asset_capacity_guest_tests.cpp
            "${generated}/tex_init_textures.c" "${generated}/load_texture.c"
            "${generated}/tex_load_sprite.c" "${generated}/allocate_object_model_pools.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
    if(EXISTS "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v77/track_setup_racers.c")
        foreach(rev IN ITEMS 77 80)
            set(target DKRLegacyCharacterAiGuestV${rev})
            set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
            add_executable(${target} ../legacy_character_ai_guest_tests.cpp "${generated}/track_setup_racers.c")
            target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
            target_include_directories(${target} PRIVATE "${generated}")
            target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
            if(MSVC)
                # Visual Studio evaluates mixed-target language options as
                # CXX; force this C-compatible declaration header for both.
                target_compile_options(${target} PRIVATE /FIfuncs.h "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
            else()
                target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
            endif()
            add_test(NAME ${target} COMMAND ${target})
        endforeach()
    endif()
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyHeapGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_heap_guest_tests.cpp)
        foreach(fn IN ITEMS mempool_init_main mempool_init mempool_alloc mempool_slot_find mempool_slot_assign mempool_free_timer
                mempool_free_addr mempool_get_pool mempool_slot_clear)
            target_sources(${target} PRIVATE "${generated}/${fn}.c")
        endforeach()
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyModelCacheGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_model_cache_guest_tests.cpp
            "${generated}/object_model_init.c" "${generated}/model_instance_init.c" "${generated}/mempool_init_main.c"
            "${generated}/init_object_shading.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyCharacterPresentationGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_character_presentation_guest_tests.cpp)
        foreach(fn IN ITEMS postrace_load results_render func_80098774 play_random_character_voice racer_play_sound
                sound_play_spatial audspat_play_sound_at_position sound_play_direct sound_play
                hud_eggs_portrait hud_lives_render hud_treasure hud_main_hub hud_element_render menu_cinematic_loop)
            target_sources(${target} PRIVATE "${generated}/${fn}.c")
        endforeach()
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyCharacterMenuGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_character_menu_guest_tests.cpp "${generated}/charselect_move.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
endif()

# Optional regenerated character function; input remains read-only.
set(DKR_LEGACY_CHARACTER_PIPELINE_ROOT "" CACHE PATH "Private regenerated character qualification sources")
if(NOT DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT STREQUAL "")
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyCharacterAudioGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_MENU_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        if(rev EQUAL 77)
            set(bank_helper static_3_800C75B0)
        else()
            set(bank_helper static_3_800C7B10)
        endif()
        add_executable(${target} ../legacy_character_audio_tests.cpp
            "${generated}/alBnkfNew.c" "${generated}/${bank_helper}.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        target_compile_definitions(${target} PRIVATE DKR_TEST_AUDIO_GUEST=1)
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
endif()
if(NOT DKR_LEGACY_CHARACTER_PIPELINE_ROOT STREQUAL "")
    foreach(rev IN ITEMS 77 80)
        set(target DKRLegacyCharacterGuestV${rev})
        set(generated "${DKR_LEGACY_CHARACTER_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        add_executable(${target} ../legacy_character_guest_tests.cpp "${generated}/spawn_object.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>" "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h;-fno-sanitize=shift-base>")
        endif()
        add_test(NAME ${target} COMMAND ${target})
    endforeach()
endif()

# Optional private-fixture qualification: consume Patch Pipeline output, never
# alter it. Only asset APIs, DMA functions and original list/free helpers link.
set(DKR_LEGACY_PIPELINE_ROOT "" CACHE PATH "Directory containing regenerated RecompiledFuncs-v77/v80")
if(NOT DKR_LEGACY_PIPELINE_ROOT STREQUAL "")
    foreach(rev IN ITEMS 77 80)
        set(generated "${DKR_LEGACY_PIPELINE_ROOT}/RecompiledFuncs-v${rev}")
        set(copy_sources "${generated}/dmacopy.c")
        if(rev EQUAL 80)
            list(APPEND copy_sources "${generated}/dmacopy_v1.c")
        endif()
        set(target DKRLegacyGuestPipelineV${rev})
        add_executable(${target} ../legacy_guest_pipeline_tests.cpp
            ${copy_sources} "${generated}/__amDMA.c"
            "${generated}/alLink.c" "${generated}/alUnlink.c" "${generated}/tex_free.c" "${generated}/alSeqFileNew.c"
            "${generated}/asset_table_load.c" "${generated}/asset_load.c"
            "${generated}/asset_rom_offset.c" "${generated}/asset_table_size.c"
            "${generated}/asset_table_load_addr.c" "${generated}/asset_table_load_zipped.c")
        target_link_libraries(${target} PRIVATE DKRLegacyGuestIO)
        target_include_directories(${target} PRIVATE "${generated}")
        target_compile_definitions(${target} PRIVATE DKR_TEST_REVISION=${rev})
        # The recompiler's one-function-per-file mode omits funcs.h includes.
        # Apply its own generated declarations through the build boundary.
        if(MSVC)
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:/FIfuncs.h>")
            # Runtime guest callbacks can unwind through regenerated C. Do not
            # assume C-linkage callbacks are nonthrowing in this fault harness.
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/EHs;/EHc->")
        else()
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-include;funcs.h>")
            # Regenerated MIPS LUI uses signed 32-bit shifts deliberately. Keep
            # ASan and other UBSan checks, but not signed shift-base checks in
            # generated C. New project-owned C++ retains the full sanitizer set.
            target_compile_options(${target} PRIVATE "$<$<COMPILE_LANGUAGE:C>:-fno-sanitize=shift-base>")
        endif()
    endforeach()
endif()
