From f15846eb4054145117ca5e03306a0d01331d3de3 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 2 May 2026 23:50:28 +0000 Subject: [PATCH] Revert "[externals] nuke nx_tzdb" This reverts commit a0b68e383df1d39022479f11b1864484ce354db9. --- externals/CMakeLists.txt | 3 + externals/cpmfile.json | 10 ++ externals/nx_tzdb/CMakeLists.txt | 111 ++++++++++++++++++ externals/nx_tzdb/ListFilesInDirectory.cmake | 8 ++ externals/nx_tzdb/NxTzdbCreateHeader.cmake | 50 ++++++++ externals/nx_tzdb/include/nx_tzdb.h | 27 +++++ externals/nx_tzdb/tzdb_template.h.in | 18 +++ src/core/CMakeLists.txt | 2 + .../system_archive/time_zone_binary.cpp | 86 ++++++++++++++ .../system_archive/time_zone_binary.h | 12 ++ 10 files changed, 327 insertions(+) create mode 100644 externals/nx_tzdb/CMakeLists.txt create mode 100644 externals/nx_tzdb/ListFilesInDirectory.cmake create mode 100644 externals/nx_tzdb/NxTzdbCreateHeader.cmake create mode 100644 externals/nx_tzdb/include/nx_tzdb.h create mode 100644 externals/nx_tzdb/tzdb_template.h.in create mode 100644 src/core/file_sys/system_archive/time_zone_binary.cpp create mode 100644 src/core/file_sys/system_archive/time_zone_binary.h diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index bcb85ce265..e230f709fa 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -243,6 +243,9 @@ if (YUZU_USE_EXTERNAL_FFMPEG OR YUZU_USE_BUNDLED_FFMPEG) message(STATUS "FFmpeg Libraries: ${FFmpeg_LIBRARIES}") endif() +# TZDB (Time Zone Database) +add_subdirectory(nx_tzdb) + add_library(tz tz/tz/tz.cpp) target_include_directories(tz PUBLIC ./tz) diff --git a/externals/cpmfile.json b/externals/cpmfile.json index e1363c9260..0f8d34230c 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -220,6 +220,16 @@ "version": "8.0.1-c7b5f1537d", "min_version": "4.1" }, + "tzdb": { + "package": "nx_tzdb", + "repo": "eden-emu/tzdb_to_nx", + "git_host": "git.eden-emu.dev", + "artifact": "%VERSION%.tar.gz", + "tag": "%VERSION%", + "hash": "cce65a12bf90f4ead43b24a0b95dfad77ac3d9bfbaaf66c55e6701346e7a1e44ca5d2f23f47ee35ee02271eb1082bf1762af207aad9fb236f1c8476812d008ed", + "version": "121125", + "git_version": "230326" + }, "vulkan-headers": { "repo": "KhronosGroup/Vulkan-Headers", "package": "VulkanHeaders", diff --git a/externals/nx_tzdb/CMakeLists.txt b/externals/nx_tzdb/CMakeLists.txt new file mode 100644 index 0000000000..a82bf0b132 --- /dev/null +++ b/externals/nx_tzdb/CMakeLists.txt @@ -0,0 +1,111 @@ +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +# SPDX-FileCopyrightText: 2023 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +set(NX_TZDB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include") + +add_library(nx_tzdb INTERFACE) + +find_program(GIT git) +find_program(GNU_MAKE make) +find_program(DATE_PROG date) + +set(CAN_BUILD_NX_TZDB true) + +if (NOT (GIT AND GNU_MAKE AND DATE_PROG) OR CMAKE_SYSTEM_NAME STREQUAL "Windows" OR ANDROID) + # tzdb_to_nx currently requires a posix-compliant host + # MinGW and Android are handled here due to the executable format being different from the host system + # TODO (lat9nq): cross-compiling support + + set(CAN_BUILD_NX_TZDB false) +endif() + +if (CAN_BUILD_NX_TZDB AND NOT YUZU_DOWNLOAD_TIME_ZONE_DATA) + message(FATAL_ERROR "Building tzdb is currently unsupported. Check back later.") + add_subdirectory(tzdb_to_nx) + add_dependencies(nx_tzdb x80e) + + set(NX_TZDB_BASE_DIR "${NX_TZDB_DIR}") + set(NX_TZDB_TZ_DIR "${NX_TZDB_BASE_DIR}/zoneinfo") +endif() + +if(NOT YUZU_TZDB_PATH STREQUAL "") + set(NX_TZDB_BASE_DIR "${YUZU_TZDB_PATH}") +elseif (MSVC AND NOT CXX_CLANG AND ENABLE_LTO) + # TODO(crueter): boot up the windows vm + set(NX_TZDB_VERSION "250725") + set(NX_TZDB_ARCHIVE "${CPM_SOURCE_CACHE}/nx_tzdb/${NX_TZDB_VERSION}.zip") + + set(NX_TZDB_BASE_DIR "${CPM_SOURCE_CACHE}/nx_tzdb/tz") + + set(NX_TZDB_DOWNLOAD_URL "https://git.crueter.xyz/misc/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip") + + message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...") + file(DOWNLOAD ${NX_TZDB_DOWNLOAD_URL} ${NX_TZDB_ARCHIVE} + STATUS NX_TZDB_DOWNLOAD_STATUS) + + list(GET NX_TZDB_DOWNLOAD_STATUS 0 NX_TZDB_DOWNLOAD_STATUS_CODE) + if (NOT NX_TZDB_DOWNLOAD_STATUS_CODE EQUAL 0) + message(FATAL_ERROR "Time zone data download failed (status code ${NX_TZDB_DOWNLOAD_STATUS_CODE})") + endif() + + file(ARCHIVE_EXTRACT + INPUT + ${NX_TZDB_ARCHIVE} + DESTINATION + ${NX_TZDB_BASE_DIR}) +else() + message(STATUS "Downloading time zone data...") + AddJsonPackage(tzdb) + + set(NX_TZDB_BASE_DIR "${nx_tzdb_SOURCE_DIR}") +endif() + +set(NX_TZDB_TZ_DIR "${NX_TZDB_BASE_DIR}/zoneinfo") + +target_include_directories(nx_tzdb + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include + INTERFACE ${NX_TZDB_INCLUDE_DIR}) + +function(CreateHeader ZONE_PATH HEADER_NAME) + set(HEADER_PATH "${NX_TZDB_INCLUDE_DIR}/nx_tzdb/${HEADER_NAME}.h") + add_custom_command( + OUTPUT + ${NX_TZDB_INCLUDE_DIR}/nx_tzdb/${HEADER_NAME}.h + COMMAND + ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/NxTzdbCreateHeader.cmake + ${ZONE_PATH} + ${HEADER_NAME} + ${NX_TZDB_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS + tzdb_template.h.in + NxTzdbCreateHeader.cmake) + + target_sources(nx_tzdb PRIVATE ${HEADER_PATH}) +endfunction() + +CreateHeader(${NX_TZDB_BASE_DIR} base) +CreateHeader(${NX_TZDB_TZ_DIR} zoneinfo) +CreateHeader(${NX_TZDB_TZ_DIR}/Africa africa) +CreateHeader(${NX_TZDB_TZ_DIR}/America america) +CreateHeader(${NX_TZDB_TZ_DIR}/America/Argentina america_argentina) +CreateHeader(${NX_TZDB_TZ_DIR}/America/Indiana america_indiana) +CreateHeader(${NX_TZDB_TZ_DIR}/America/Kentucky america_kentucky) +CreateHeader(${NX_TZDB_TZ_DIR}/America/North_Dakota america_north_dakota) +CreateHeader(${NX_TZDB_TZ_DIR}/Antarctica antarctica) +CreateHeader(${NX_TZDB_TZ_DIR}/Arctic arctic) +CreateHeader(${NX_TZDB_TZ_DIR}/Asia asia) +CreateHeader(${NX_TZDB_TZ_DIR}/Atlantic atlantic) +CreateHeader(${NX_TZDB_TZ_DIR}/Australia australia) +CreateHeader(${NX_TZDB_TZ_DIR}/Brazil brazil) +CreateHeader(${NX_TZDB_TZ_DIR}/Canada canada) +CreateHeader(${NX_TZDB_TZ_DIR}/Chile chile) +CreateHeader(${NX_TZDB_TZ_DIR}/Etc etc) +CreateHeader(${NX_TZDB_TZ_DIR}/Europe europe) +CreateHeader(${NX_TZDB_TZ_DIR}/Indian indian) +CreateHeader(${NX_TZDB_TZ_DIR}/Mexico mexico) +CreateHeader(${NX_TZDB_TZ_DIR}/Pacific pacific) +CreateHeader(${NX_TZDB_TZ_DIR}/US us) diff --git a/externals/nx_tzdb/ListFilesInDirectory.cmake b/externals/nx_tzdb/ListFilesInDirectory.cmake new file mode 100644 index 0000000000..35a9e726ab --- /dev/null +++ b/externals/nx_tzdb/ListFilesInDirectory.cmake @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2023 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +# CMake does not have a way to list the files in a specific directory, +# so we need this script to do that for us in a platform-agnostic fashion + +file(GLOB FILE_LIST LIST_DIRECTORIES false RELATIVE ${CMAKE_SOURCE_DIR} "*") +execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${FILE_LIST};") diff --git a/externals/nx_tzdb/NxTzdbCreateHeader.cmake b/externals/nx_tzdb/NxTzdbCreateHeader.cmake new file mode 100644 index 0000000000..95606d8629 --- /dev/null +++ b/externals/nx_tzdb/NxTzdbCreateHeader.cmake @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2023 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +set(ZONE_PATH ${CMAKE_ARGV3}) +set(HEADER_NAME ${CMAKE_ARGV4}) +set(NX_TZDB_INCLUDE_DIR ${CMAKE_ARGV5}) +set(NX_TZDB_SOURCE_DIR ${CMAKE_ARGV6}) + +execute_process( + COMMAND ${CMAKE_COMMAND} -P ${NX_TZDB_SOURCE_DIR}/ListFilesInDirectory.cmake + WORKING_DIRECTORY ${ZONE_PATH} + OUTPUT_VARIABLE FILE_LIST) + +if (NOT FILE_LIST) + message(FATAL_ERROR "No timezone files found in directory ${ZONE_PATH}, did the download fail?") +endif() + +set(DIRECTORY_NAME ${HEADER_NAME}) + +set(FILE_DATA "") +foreach(ZONE_FILE ${FILE_LIST}) + if (ZONE_FILE STREQUAL "\n") + continue() + endif() + + string(APPEND FILE_DATA "{\"${ZONE_FILE}\",\n{") + + file(READ ${ZONE_PATH}/${ZONE_FILE} ZONE_DATA HEX) + string(LENGTH "${ZONE_DATA}" ZONE_DATA_LEN) + foreach(I RANGE 0 ${ZONE_DATA_LEN} 2) + math(EXPR BREAK_LINE "(${I} + 2) % 38") + + string(SUBSTRING "${ZONE_DATA}" "${I}" 2 HEX_DATA) + if (NOT HEX_DATA) + break() + endif() + + string(APPEND FILE_DATA "0x${HEX_DATA},") + if (BREAK_LINE EQUAL 0) + string(APPEND FILE_DATA "\n") + else() + string(APPEND FILE_DATA " ") + endif() + endforeach() + + string(APPEND FILE_DATA "}},\n") +endforeach() + +file(READ ${NX_TZDB_SOURCE_DIR}/tzdb_template.h.in NX_TZDB_TEMPLATE_H_IN) +file(CONFIGURE OUTPUT ${NX_TZDB_INCLUDE_DIR}/nx_tzdb/${HEADER_NAME}.h CONTENT "${NX_TZDB_TEMPLATE_H_IN}") diff --git a/externals/nx_tzdb/include/nx_tzdb.h b/externals/nx_tzdb/include/nx_tzdb.h new file mode 100644 index 0000000000..1f7c6069ae --- /dev/null +++ b/externals/nx_tzdb/include/nx_tzdb.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "nx_tzdb/africa.h" +#include "nx_tzdb/america.h" +#include "nx_tzdb/america_argentina.h" +#include "nx_tzdb/america_indiana.h" +#include "nx_tzdb/america_kentucky.h" +#include "nx_tzdb/america_north_dakota.h" +#include "nx_tzdb/antarctica.h" +#include "nx_tzdb/arctic.h" +#include "nx_tzdb/asia.h" +#include "nx_tzdb/atlantic.h" +#include "nx_tzdb/australia.h" +#include "nx_tzdb/base.h" +#include "nx_tzdb/brazil.h" +#include "nx_tzdb/canada.h" +#include "nx_tzdb/chile.h" +#include "nx_tzdb/etc.h" +#include "nx_tzdb/europe.h" +#include "nx_tzdb/indian.h" +#include "nx_tzdb/mexico.h" +#include "nx_tzdb/pacific.h" +#include "nx_tzdb/us.h" +#include "nx_tzdb/zoneinfo.h" diff --git a/externals/nx_tzdb/tzdb_template.h.in b/externals/nx_tzdb/tzdb_template.h.in new file mode 100644 index 0000000000..289d002ea8 --- /dev/null +++ b/externals/nx_tzdb/tzdb_template.h.in @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +namespace NxTzdb { + +// clang-format off +const static std::map> @DIRECTORY_NAME@ = +{ +@FILE_DATA@}; +// clang-format on + +} // namespace NxTzdb diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 3faa0505aa..39aebd5f48 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -160,6 +160,8 @@ add_library(core STATIC file_sys/system_archive/system_archive.h file_sys/system_archive/system_version.cpp file_sys/system_archive/system_version.h + file_sys/system_archive/time_zone_binary.cpp + file_sys/system_archive/time_zone_binary.h file_sys/vfs/vfs.cpp file_sys/vfs/vfs.h file_sys/vfs/vfs_cached.cpp diff --git a/src/core/file_sys/system_archive/time_zone_binary.cpp b/src/core/file_sys/system_archive/time_zone_binary.cpp new file mode 100644 index 0000000000..316ff0dc6f --- /dev/null +++ b/src/core/file_sys/system_archive/time_zone_binary.cpp @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "common/swap.h" +#include "core/file_sys/system_archive/time_zone_binary.h" +#include "core/file_sys/vfs/vfs_vector.h" + +#include "nx_tzdb.h" + +namespace FileSys::SystemArchive { + +const static std::map>&> + tzdb_zoneinfo_dirs = {{"Africa", NxTzdb::africa}, + {"America", NxTzdb::america}, + {"Antarctica", NxTzdb::antarctica}, + {"Arctic", NxTzdb::arctic}, + {"Asia", NxTzdb::asia}, + {"Atlantic", NxTzdb::atlantic}, + {"Australia", NxTzdb::australia}, + {"Brazil", NxTzdb::brazil}, + {"Canada", NxTzdb::canada}, + {"Chile", NxTzdb::chile}, + {"Etc", NxTzdb::etc}, + {"Europe", NxTzdb::europe}, + {"Indian", NxTzdb::indian}, + {"Mexico", NxTzdb::mexico}, + {"Pacific", NxTzdb::pacific}, + {"US", NxTzdb::us}}; + +const static std::map>&> + tzdb_america_dirs = {{"Argentina", NxTzdb::america_argentina}, + {"Indiana", NxTzdb::america_indiana}, + {"Kentucky", NxTzdb::america_kentucky}, + {"North_Dakota", NxTzdb::america_north_dakota}}; + +static void GenerateFiles(std::vector& directory, + const std::map>& files) { + for (const auto& [filename, data] : files) { + const auto data_copy{data}; + const std::string filename_copy{filename}; + VirtualFile file{ + std::make_shared(std::move(data_copy), std::move(filename_copy))}; + directory.push_back(file); + } +} + +static std::vector GenerateZoneinfoFiles() { + std::vector zoneinfo_files; + GenerateFiles(zoneinfo_files, NxTzdb::zoneinfo); + return zoneinfo_files; +} + +VirtualDir TimeZoneBinary() { + std::vector america_sub_dirs; + for (const auto& [dir_name, files] : tzdb_america_dirs) { + std::vector vfs_files; + GenerateFiles(vfs_files, files); + america_sub_dirs.push_back(std::make_shared( + std::move(vfs_files), std::vector{}, dir_name)); + } + + std::vector zoneinfo_sub_dirs; + for (const auto& [dir_name, files] : tzdb_zoneinfo_dirs) { + std::vector vfs_files; + GenerateFiles(vfs_files, files); + if (dir_name == "America") { + zoneinfo_sub_dirs.push_back(std::make_shared( + std::move(vfs_files), std::move(america_sub_dirs), dir_name)); + } else { + zoneinfo_sub_dirs.push_back(std::make_shared( + std::move(vfs_files), std::vector{}, dir_name)); + } + } + + std::vector zoneinfo_dir{std::make_shared( + GenerateZoneinfoFiles(), std::move(zoneinfo_sub_dirs), "zoneinfo")}; + std::vector root_files; + GenerateFiles(root_files, NxTzdb::base); + + return std::make_shared(std::move(root_files), std::move(zoneinfo_dir), + "data"); +} + +} // namespace FileSys::SystemArchive diff --git a/src/core/file_sys/system_archive/time_zone_binary.h b/src/core/file_sys/system_archive/time_zone_binary.h new file mode 100644 index 0000000000..e44fc50077 --- /dev/null +++ b/src/core/file_sys/system_archive/time_zone_binary.h @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/file_sys/vfs/vfs_types.h" + +namespace FileSys::SystemArchive { + +VirtualDir TimeZoneBinary(); + +} // namespace FileSys::SystemArchive