mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-20 08:15:46 +00:00
Move dead submodules in-tree
Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
parent
c0cceff365
commit
6c655321e6
4081 changed files with 1185566 additions and 45 deletions
1
externals/nx_tzdb/tzdb_to_nx
vendored
1
externals/nx_tzdb/tzdb_to_nx
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 97929690234f2b4add36b33657fe3fe09bd57dfd
|
52
externals/nx_tzdb/tzdb_to_nx/.github/workflows/cmake.yml
vendored
Normal file
52
externals/nx_tzdb/tzdb_to_nx/.github/workflows/cmake.yml
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
name: CMake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
|
||||
# You can convert this to a matrix build if you need cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ubuntu-latest,macos-latest]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: |
|
||||
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
echo "nx_tzdb_dir=$(grep NX_TZDB_DIR ${{github.workspace}}/build/CMakeCache.txt | sed 's/.*=//g')" > "$GITHUB_ENV"
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target x80e
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
mkdir -p ${{github.workspace}}/artifacts
|
||||
cp -Rv ${{ env.nx_tzdb_dir }} ${{github.workspace}}/artifacts/
|
||||
|
||||
- name: Version
|
||||
run: |
|
||||
echo "nx_version=$(cat ${{ env.nx_tzdb_dir }}/version.txt)" > "$GITHUB_ENV"
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.nx_version }}_${{ matrix.platform }}
|
||||
path: artifacts/nx
|
2
externals/nx_tzdb/tzdb_to_nx/.gitignore
vendored
Normal file
2
externals/nx_tzdb/tzdb_to_nx/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.cache
|
||||
build
|
3
externals/nx_tzdb/tzdb_to_nx/.gitmodules
vendored
Normal file
3
externals/nx_tzdb/tzdb_to_nx/.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "externals/tz/tz"]
|
||||
path = externals/tz/tz
|
||||
url = https://github.com/eggert/tz.git
|
19
externals/nx_tzdb/tzdb_to_nx/CMakeLists.txt
vendored
Normal file
19
externals/nx_tzdb/tzdb_to_nx/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(tzdb2nx VERSION 1.0)
|
||||
|
||||
option(TZDB2NX_ZONEINFO_DIR "Specify a custom zoneinfo directory containing time zone data you wish to use" "")
|
||||
option(TZDB2NX_VERSION "Specify a custom zoneinfo version with the directory" "")
|
||||
|
||||
if (TZDB2NX_ZONEINFO_DIR AND NOT TZDB2NX_VERSION)
|
||||
message(FATAL_ERROR "TZDB2NX_ZONEINFO_DIR was specified but TZDB2NX_VERSION was left undefined.")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
if (APPLE)
|
||||
find_package(Intl REQUIRED)
|
||||
endif()
|
||||
|
||||
add_subdirectory(externals)
|
||||
add_subdirectory(src)
|
10
externals/nx_tzdb/tzdb_to_nx/CMakeModules/list_directory.cmake
vendored
Normal file
10
externals/nx_tzdb/tzdb_to_nx/CMakeModules/list_directory.cmake
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
set(WITH_DIRECTORIES ${CMAKE_ARGV3})
|
||||
set(RECURSE ${CMAKE_ARGV4})
|
||||
|
||||
set(HOW_TO_GLOB "GLOB")
|
||||
if (RECURSE)
|
||||
set(HOW_TO_GLOB "GLOB_RECURSE")
|
||||
endif()
|
||||
|
||||
file(${HOW_TO_GLOB} FILE_LIST LIST_DIRECTORIES ${WITH_DIRECTORIES} RELATIVE ${CMAKE_SOURCE_DIR} "*")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${FILE_LIST};")
|
21
externals/nx_tzdb/tzdb_to_nx/LICENSE
vendored
Normal file
21
externals/nx_tzdb/tzdb_to_nx/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2023 lat9nq
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the “Software”), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
22
externals/nx_tzdb/tzdb_to_nx/README.md
vendored
Normal file
22
externals/nx_tzdb/tzdb_to_nx/README.md
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# tzdb_to_nx
|
||||
|
||||
This is a CMake/C++ project to convert RFC 8536 time zone data to the Nintendo Switch's format.
|
||||
This makes use a lot of Unix system calls as well as a bash script to convert the data, so it likely requires a bit of work to port to a non-POSIX platform, such as Windows.
|
||||
|
||||
Intended for use with the [yuzu Emulator](https://yuzu-emu.org/) project, but the project in the future likely won't ship synthesized Switch archives.
|
||||
That leaves this project in a place where it is not likely to be used, but will remain here as a reference.
|
||||
|
||||
- tzdb: CMake and bash script to build and convert time zone data from https://www.iana.org/time-zones into the Nintendo Switch's format.
|
||||
- tzdb2nx: C++ program that converts a single tzif file to the Nintendo's format.
|
||||
|
||||
The fine folks over at [SwitchBrew](https://switchbrew.org/wiki/PSC_services#ITimeZoneService) have left very helpful information on reading the data.
|
||||
Nintendo's file is simply the TZif version 2 data, with standard_indicators and ut_indicators data stripped out (and the necessary modifications needed in the header to make the data valid).
|
||||
This means the TZif 1 data is not present, so essentially we are left with the second half of each file.
|
||||
|
||||
Nintendo also does not seem to run the `zic` program on their output when they build the time zone data.
|
||||
I have left the relevant build command for that in src/tzdb/CMakeLists.txt commented out, but it isn't used here.
|
||||
This lets the project produce data identical to Nintendo's firmware for time zones, however this code does not produce the time zone data on US/Pacific-New or America/East-Saskatchewan (I may have bunged up the actual paths for these as this is 3 day old memory).
|
||||
|
||||
The CMake and C++ code in this repository is licensed under the MIT License.
|
||||
The source files date.c, newstrftime.3 and strftime.c from submodule eggert/tz use the BSD-3 clause license [[source]](https://github.com/eggert/tz/blob/main/LICENSE).
|
||||
The time zone data output from this repository, like those found in archives in the Release setcion, is in the public domain [[source]](https://github.com/eggert/tz/blob/main/LICENSE).
|
1
externals/nx_tzdb/tzdb_to_nx/externals/CMakeLists.txt
vendored
Normal file
1
externals/nx_tzdb/tzdb_to_nx/externals/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
add_subdirectory(tz)
|
78
externals/nx_tzdb/tzdb_to_nx/externals/tz/CMakeLists.txt
vendored
Normal file
78
externals/nx_tzdb/tzdb_to_nx/externals/tz/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
set(TZ_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tz" CACHE PATH "Time zone source directory")
|
||||
set(TZ_DIR "${CMAKE_CURRENT_BINARY_DIR}/tz")
|
||||
set(TZ_TMP_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/tmpsrc")
|
||||
set(TZIF_LIST_FILE "${CMAKE_CURRENT_BINARY_DIR}/tzif_list.txt" CACHE PATH "List of zone info files")
|
||||
if (TZDB2NX_ZONEINFO_DIR)
|
||||
set(TZ_ZONEINFO_DIR "${TZDB2NX_ZONEINFO_DIR}" CACHE PATH "Time zone info data directory")
|
||||
else()
|
||||
set(TZ_ZONEINFO_DIR "${TZ_DIR}/usr/share/zoneinfo" CACHE PATH "Time zone info data directory")
|
||||
endif()
|
||||
|
||||
find_program(GNU_MAKE make)
|
||||
if (NOT GNU_MAKE)
|
||||
message(FATAL_ERROR "GNU make not found")
|
||||
endif()
|
||||
|
||||
find_program(GIT_PROGRAM git)
|
||||
if (NOT GIT_PROGRAM)
|
||||
message(FATAL_ERROR "git program not found")
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS "${TZ_DIR}" OR NOT EXISTS "${TZIF_LIST_FILE}")
|
||||
if (NOT TZDB2NX_ZONEINFO_DIR) # If a custom zoneinfo directory was specified
|
||||
# tz's makefile can only build in-tree, so copy the whole source tree to a
|
||||
# separate directory before building.
|
||||
execute_process(
|
||||
COMMAND
|
||||
${GIT_PROGRAM} clone --depth 1 "file://${TZ_SOURCE_DIR}" "${TZ_TMP_SOURCE_DIR}"
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
set(TZ_MAKEFLAGS "LDLIBS=${Intl_LIBRARY}")
|
||||
else()
|
||||
set(TZ_MAKEFLAGS)
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${GNU_MAKE} DESTDIR=${TZ_DIR} ${TZ_MAKEFLAGS} install
|
||||
WORKING_DIRECTORY
|
||||
${TZ_TMP_SOURCE_DIR}
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
unset(TZ_MAKEFLAGS)
|
||||
|
||||
# Step taken by Arch Linux packaging, but Nintendo apparently skips it
|
||||
# execute_process(
|
||||
# COMMAND
|
||||
# "${TZDB_LOCATION}/zic" -b fat -d ${TZDB_ZONEINFO} africa antarctica asia australasia europe northamerica southamerica etcetera backward factory
|
||||
# WORKING_DIRECTORY
|
||||
# "${TZDB_LOCATION}"
|
||||
# COMMAND_ERROR_IS_FATAL ANY
|
||||
# )
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/CMakeModules/list_directory.cmake false ON
|
||||
WORKING_DIRECTORY
|
||||
"${TZ_ZONEINFO_DIR}"
|
||||
OUTPUT_VARIABLE
|
||||
TZIF_SCAN
|
||||
)
|
||||
|
||||
set(TZIF_LIST "")
|
||||
foreach(CANDIDATE ${TZIF_SCAN})
|
||||
if (CANDIDATE STREQUAL "\n")
|
||||
continue()
|
||||
endif()
|
||||
set(TZIF_FILE "${TZ_ZONEINFO_DIR}/${CANDIDATE}")
|
||||
file(READ "${TZIF_FILE}" HEADER LIMIT 4)
|
||||
string(SUBSTRING "${HEADER}" 0 4 HEADER) # Remove trailing newline
|
||||
if (HEADER STREQUAL "TZif")
|
||||
file(APPEND "${TZIF_LIST_FILE}" "${TZIF_FILE}\n")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
1
externals/nx_tzdb/tzdb_to_nx/externals/tz/tz
vendored
Submodule
1
externals/nx_tzdb/tzdb_to_nx/externals/tz/tz
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 16ce126a87c5f130cde8b8dce73b38952a19f085
|
11
externals/nx_tzdb/tzdb_to_nx/src/CMakeLists.txt
vendored
Normal file
11
externals/nx_tzdb/tzdb_to_nx/src/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
add_compile_options(
|
||||
-Werror=all
|
||||
-Werror=extra
|
||||
|
||||
-Werror=shadow
|
||||
)
|
||||
|
||||
include_directories(.)
|
||||
|
||||
add_subdirectory(tzdb2nx)
|
||||
add_subdirectory(tzdb)
|
90
externals/nx_tzdb/tzdb_to_nx/src/tzdb/CMakeLists.txt
vendored
Normal file
90
externals/nx_tzdb/tzdb_to_nx/src/tzdb/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
find_program(GIT_PROGRAM git)
|
||||
if (NOT GIT_PROGRAM)
|
||||
message(FATAL_ERROR "git program not found")
|
||||
endif()
|
||||
|
||||
find_program(GNU_DATE date)
|
||||
if (NOT GNU_DATE)
|
||||
message(FATAL_ERROR "date program not found")
|
||||
endif()
|
||||
|
||||
set(NX_TZDB_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx" CACHE PATH "Path to Switch-style time zone data")
|
||||
set(NX_ZONEINFO_DIR "${NX_TZDB_DIR}/zoneinfo")
|
||||
|
||||
set(TZDB_VERSION_FILE ${TZ_SOURCE_DIR}/NEWS)
|
||||
|
||||
if (NOT "${TZDB2NX_VERSION}" STREQUAL "")
|
||||
set(TZDB_VERSION "${TZDB2NX_VERSION}\n")
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND
|
||||
${GIT_PROGRAM} log --pretty=%at -n1 NEWS
|
||||
OUTPUT_VARIABLE
|
||||
TZ_COMMIT_TIME
|
||||
WORKING_DIRECTORY
|
||||
${TZ_SOURCE_DIR}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
string(REPLACE "\n" "" TZ_COMMIT_TIME "${TZ_COMMIT_TIME}")
|
||||
|
||||
if (APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
|
||||
set(VERSION_COMMAND ${GNU_DATE} -r ${TZ_COMMIT_TIME} +%y%m%d)
|
||||
else ()
|
||||
set(VERSION_COMMAND ${GNU_DATE} +%y%m%d --date=@${TZ_COMMIT_TIME})
|
||||
endif ()
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${VERSION_COMMAND}
|
||||
OUTPUT_VARIABLE
|
||||
TZDB_VERSION
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
endif()
|
||||
|
||||
set(NX_VERSION_FILE ${NX_TZDB_DIR}/version.txt)
|
||||
file(WRITE ${NX_VERSION_FILE} "${TZDB_VERSION}")
|
||||
|
||||
add_custom_target(x80e
|
||||
DEPENDS
|
||||
tzdb2nx
|
||||
${NX_VERSION_FILE})
|
||||
|
||||
set(BINARY_LIST_TXT ${NX_TZDB_DIR}/binaryList.txt)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${BINARY_LIST_TXT}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/generate_binary_list_txt.cmake ${BINARY_LIST_TXT} ${PROJECT_SOURCE_DIR}/CMakeModules/list_directory.cmake
|
||||
WORKING_DIRECTORY
|
||||
${NX_ZONEINFO_DIR})
|
||||
|
||||
add_custom_target(time_zone_binary_list
|
||||
DEPENDS ${BINARY_LIST_TXT})
|
||||
add_dependencies(x80e time_zone_binary_list)
|
||||
|
||||
set(TZ_DATA_LIST "")
|
||||
|
||||
file(STRINGS "${TZIF_LIST_FILE}" TZ_FILES)
|
||||
foreach(FILE ${TZ_FILES})
|
||||
file(RELATIVE_PATH TARG "${TZ_ZONEINFO_DIR}" "${FILE}")
|
||||
get_filename_component(TARG_PATH "${NX_ZONEINFO_DIR}/${TARG}" DIRECTORY)
|
||||
string(REGEX REPLACE "\/" "_" TARG_SANITIZED "${TARG}")
|
||||
set(NX_TZ_TARGET ${NX_ZONEINFO_DIR}/${TARG})
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${NX_TZ_TARGET}
|
||||
COMMAND
|
||||
mkdir -p ${TARG_PATH}
|
||||
COMMAND
|
||||
${TZDB2NX_PATH} ${FILE} ${NX_ZONEINFO_DIR}/${TARG}
|
||||
DEPENDS
|
||||
tzdb2nx)
|
||||
|
||||
list(APPEND TZ_DATA_LIST ${NX_TZ_TARGET})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(time_zone_data
|
||||
DEPENDS ${TZ_DATA_LIST})
|
||||
|
||||
add_dependencies(x80e time_zone_data)
|
||||
add_dependencies(time_zone_binary_list time_zone_data)
|
52
externals/nx_tzdb/tzdb_to_nx/src/tzdb/generate_binary_list_txt.cmake
vendored
Normal file
52
externals/nx_tzdb/tzdb_to_nx/src/tzdb/generate_binary_list_txt.cmake
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
set(BINARY_LIST_TXT ${CMAKE_ARGV3})
|
||||
set(LIST_DIR_CMAKE ${CMAKE_ARGV4})
|
||||
|
||||
# Fill text file with zone names
|
||||
# Issue: Hyphens/underscores are not handled the same way Nintendo handles them
|
||||
function(get_files_nx TARG SUB_DIR)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -P ${LIST_DIR_CMAKE} false OFF
|
||||
WORKING_DIRECTORY
|
||||
${TARG}
|
||||
OUTPUT_VARIABLE
|
||||
FILE_LIST
|
||||
)
|
||||
list(SORT FILE_LIST)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -P ${LIST_DIR_CMAKE} true OFF
|
||||
WORKING_DIRECTORY
|
||||
${TARG}
|
||||
OUTPUT_VARIABLE
|
||||
DIR_LIST
|
||||
)
|
||||
|
||||
foreach(FILE ${FILE_LIST})
|
||||
if(FILE STREQUAL "\n")
|
||||
continue()
|
||||
endif()
|
||||
list(REMOVE_ITEM DIR_LIST FILE)
|
||||
if (SUB_DIR)
|
||||
file(APPEND ${BINARY_LIST_TXT} "${SUB_DIR}/${FILE}\r\n")
|
||||
else()
|
||||
file(APPEND ${BINARY_LIST_TXT} "${FILE}\r\n")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(SORT DIR_LIST)
|
||||
|
||||
foreach(DIR ${DIR_LIST})
|
||||
if (NOT DIR OR DIR STREQUAL "\n")
|
||||
continue()
|
||||
endif()
|
||||
if (SUB_DIR)
|
||||
get_files_nx(${TARG}/${DIR} ${SUB_DIR}/${DIR})
|
||||
else()
|
||||
get_files_nx(${TARG}/${DIR} ${DIR})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
get_files_nx(${CMAKE_SOURCE_DIR} "")
|
||||
|
6
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/CMakeLists.txt
vendored
Normal file
6
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
add_executable(tzdb2nx
|
||||
main.cpp
|
||||
tzif.cpp
|
||||
tzif.h)
|
||||
|
||||
set(TZDB2NX_PATH "$<TARGET_FILE:tzdb2nx>" CACHE PATH "Path to tzdb2nx path")
|
158
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/main.cpp
vendored
Normal file
158
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/main.cpp
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
#include "tzif.h"
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
constexpr std::size_t ten_megabytes{(1 << 20) * 10};
|
||||
|
||||
static void ShortHelp(const char *argv0) {
|
||||
std::fprintf(stderr, "Usage: %s [INFILE] [OUTFILE]\n", argv0);
|
||||
}
|
||||
|
||||
static void PrintArg(const char *short_arg, const char *long_arg,
|
||||
const char *text) {
|
||||
std::fprintf(stderr, "%5s, %-20s %s\n", short_arg, long_arg, text);
|
||||
}
|
||||
|
||||
static void PrintHelp(const char *argv0) {
|
||||
ShortHelp(argv0);
|
||||
std::fprintf(stderr,
|
||||
"Converts a TZif file INFILE from the RFC8536 format to a "
|
||||
"Nintendo Switch compatible file OUTFILE.\nWith no arguments, "
|
||||
"tzdb2nx can read and write from stdin/stdout, "
|
||||
"respectively.\nGiving no arguments without input will print "
|
||||
"usage information and exit the program.\n\nArguments:\n");
|
||||
PrintArg("-h", "--help", "Print this help text and exit");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int f{STDIN_FILENO};
|
||||
const char *filename{"(stdin)"};
|
||||
std::size_t filesize{ten_megabytes};
|
||||
|
||||
const char *optstring = "h";
|
||||
int c;
|
||||
const struct option longopts[] = {
|
||||
{
|
||||
"help",
|
||||
no_argument,
|
||||
nullptr,
|
||||
'h',
|
||||
},
|
||||
{
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, optstring, longopts, nullptr)) != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
PrintHelp(argv[0]);
|
||||
return -1;
|
||||
case '?':
|
||||
ShortHelp(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
filename = argv[1];
|
||||
f = open(filename, O_RDONLY);
|
||||
|
||||
if (f == -1) {
|
||||
const int err = errno;
|
||||
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
struct stat statbuf;
|
||||
fstat(f, &statbuf);
|
||||
|
||||
filesize = statbuf.st_size;
|
||||
} else {
|
||||
struct pollfd fds {
|
||||
f, POLLIN, 0,
|
||||
};
|
||||
|
||||
const int result = poll(&fds, 1, 0);
|
||||
if (result == 0) {
|
||||
std::fprintf(stderr, "%s: No input\n", filename);
|
||||
ShortHelp(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
u_int8_t *buf = new u_int8_t[filesize];
|
||||
|
||||
filesize = read(f, buf, filesize);
|
||||
if (filesize == static_cast<std::size_t>(-1)) {
|
||||
const int err = errno;
|
||||
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
|
||||
return err;
|
||||
}
|
||||
int result = close(f);
|
||||
if (result == -1) {
|
||||
const int err = errno;
|
||||
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if (filesize < 4) {
|
||||
std::fprintf(stderr, "%s: Too small\n", filename);
|
||||
return -1;
|
||||
}
|
||||
if (std::strncmp(reinterpret_cast<const char *>(buf), "TZif", 4) != 0) {
|
||||
std::fprintf(stderr, "%s: Bad magic number\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::unique_ptr<Tzif::Data> tzif_data = Tzif::ReadData(buf, filesize);
|
||||
if (tzif_data == nullptr) {
|
||||
std::fprintf(stderr, "%s: Error occured while reading data\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
|
||||
std::vector<u_int8_t> output_buffer;
|
||||
tzif_data->ReformatNintendo(output_buffer);
|
||||
|
||||
filename = "(stdout)";
|
||||
f = STDOUT_FILENO;
|
||||
if (argc > 2) {
|
||||
filename = argv[2];
|
||||
f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
|
||||
|
||||
if (f == -1) {
|
||||
const int err = errno;
|
||||
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
result = write(f, output_buffer.data(), output_buffer.size());
|
||||
if (result == -1) {
|
||||
const int err = errno;
|
||||
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
result = close(f);
|
||||
if (result == -1) {
|
||||
const int err = errno;
|
||||
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
146
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/tzif.cpp
vendored
Normal file
146
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/tzif.cpp
vendored
Normal file
|
@ -0,0 +1,146 @@
|
|||
#include "tzif.h"
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace Tzif {
|
||||
|
||||
static std::size_t SkipToVersion2(const u_int8_t *data, std::size_t size) {
|
||||
char magic[5];
|
||||
const u_int8_t *p{data};
|
||||
|
||||
std::memcpy(magic, data, 4);
|
||||
magic[4] = '\0';
|
||||
|
||||
if (std::strcmp(magic, "TZif") != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
p++;
|
||||
if (p >= data + size) {
|
||||
return -1;
|
||||
}
|
||||
} while (std::strncmp(reinterpret_cast<const char *>(p), "TZif", 4) != 0);
|
||||
|
||||
return p - data;
|
||||
}
|
||||
|
||||
template <typename Type> constexpr static void SwapEndianess(Type *value) {
|
||||
u_int8_t *data = reinterpret_cast<u_int8_t *>(value);
|
||||
|
||||
union {
|
||||
u_int8_t data[sizeof(Type)];
|
||||
Type value;
|
||||
} temp;
|
||||
|
||||
for (u_int32_t i = 0; i < sizeof(Type); i++) {
|
||||
u_int32_t alt_index = sizeof(Type) - i - 1;
|
||||
temp.data[alt_index] = data[i];
|
||||
}
|
||||
|
||||
*value = temp.value;
|
||||
}
|
||||
|
||||
static void FlipHeader(Header &header) {
|
||||
SwapEndianess(&header.isutcnt);
|
||||
SwapEndianess(&header.isstdcnt);
|
||||
SwapEndianess(&header.leapcnt);
|
||||
SwapEndianess(&header.timecnt);
|
||||
SwapEndianess(&header.typecnt);
|
||||
SwapEndianess(&header.charcnt);
|
||||
}
|
||||
|
||||
std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size) {
|
||||
const std::size_t v2_offset = SkipToVersion2(data, size);
|
||||
if (v2_offset == static_cast<std::size_t>(-1)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const u_int8_t *p = data + v2_offset;
|
||||
|
||||
Header header;
|
||||
std::memcpy(&header, p, sizeof(header));
|
||||
p += sizeof(header);
|
||||
|
||||
FlipHeader(header);
|
||||
|
||||
const std::size_t data_block_length =
|
||||
header.timecnt * sizeof(int64_t) + header.timecnt * sizeof(u_int8_t) +
|
||||
header.typecnt * sizeof(TimeTypeRecord) +
|
||||
header.charcnt * sizeof(int8_t) + header.isstdcnt * sizeof(u_int8_t) +
|
||||
header.isutcnt * sizeof(u_int8_t);
|
||||
|
||||
if (v2_offset + data_block_length + sizeof(Header) > size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<DataImpl> impl = std::make_unique<DataImpl>();
|
||||
impl->header = header;
|
||||
|
||||
const auto copy =
|
||||
[]<typename Type>(std::unique_ptr<Type[]> &array, int length,
|
||||
const u_int8_t *const &ptr) -> const u_int8_t * {
|
||||
const std::size_t region_length = length * sizeof(Type);
|
||||
array = std::make_unique<Type[]>(length);
|
||||
std::memcpy(array.get(), ptr, region_length);
|
||||
return ptr + region_length;
|
||||
};
|
||||
|
||||
p = copy(impl->transition_times, header.timecnt, p);
|
||||
p = copy(impl->transition_types, header.timecnt, p);
|
||||
p = copy(impl->local_time_type_records, header.typecnt, p);
|
||||
p = copy(impl->time_zone_designations, header.charcnt, p);
|
||||
p = copy(impl->standard_indicators, header.isstdcnt, p);
|
||||
p = copy(impl->ut_indicators, header.isutcnt, p);
|
||||
|
||||
const std::size_t footer_string_length = data + size - p - 2;
|
||||
p++;
|
||||
|
||||
if (p + footer_string_length > data + size ||
|
||||
p + footer_string_length < data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
impl->footer.tz_string = std::make_unique<char[]>(footer_string_length);
|
||||
std::memcpy(impl->footer.tz_string.get(), p, footer_string_length);
|
||||
impl->footer.footer_string_length = footer_string_length;
|
||||
|
||||
return impl;
|
||||
}
|
||||
|
||||
static void PushToBuffer(std::vector<u_int8_t> &buffer, const void *data,
|
||||
std::size_t size) {
|
||||
const u_int8_t *p{reinterpret_cast<const u_int8_t *>(data)};
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
buffer.push_back(*p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
void DataImpl::ReformatNintendo(std::vector<u_int8_t> &buffer) const {
|
||||
buffer.clear();
|
||||
|
||||
Header header_copy{header};
|
||||
header_copy.isstdcnt = 0;
|
||||
header_copy.isutcnt = 0;
|
||||
FlipHeader(header_copy);
|
||||
|
||||
PushToBuffer(buffer, &header_copy, sizeof(Header));
|
||||
PushToBuffer(buffer, transition_times.get(),
|
||||
header.timecnt * sizeof(int64_t));
|
||||
PushToBuffer(buffer, transition_types.get(),
|
||||
header.timecnt * sizeof(u_int8_t));
|
||||
PushToBuffer(buffer, local_time_type_records.get(),
|
||||
header.typecnt * sizeof(TimeTypeRecord));
|
||||
PushToBuffer(buffer, time_zone_designations.get(),
|
||||
header.charcnt * sizeof(int8_t));
|
||||
// omit standard_indicators
|
||||
// omit ut_indicators
|
||||
PushToBuffer(buffer, &footer.nl_a, 1);
|
||||
PushToBuffer(buffer, footer.tz_string.get(), footer.footer_string_length);
|
||||
PushToBuffer(buffer, &footer.nl_b, 1);
|
||||
}
|
||||
|
||||
} // namespace Tzif
|
72
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/tzif.h
vendored
Normal file
72
externals/nx_tzdb/tzdb_to_nx/src/tzdb2nx/tzif.h
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
namespace Tzif {
|
||||
|
||||
typedef struct {
|
||||
char magic[4];
|
||||
u_int8_t version;
|
||||
u_int8_t reserved[15];
|
||||
u_int32_t isutcnt;
|
||||
u_int32_t isstdcnt;
|
||||
u_int32_t leapcnt;
|
||||
u_int32_t timecnt;
|
||||
u_int32_t typecnt;
|
||||
u_int32_t charcnt;
|
||||
} Header;
|
||||
static_assert(sizeof(Header) == 0x2c);
|
||||
|
||||
class Footer {
|
||||
public:
|
||||
explicit Footer() = default;
|
||||
~Footer() = default;
|
||||
|
||||
const char nl_a{'\n'};
|
||||
std::unique_ptr<char[]> tz_string;
|
||||
const char nl_b{'\n'};
|
||||
|
||||
std::size_t footer_string_length;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
u_int32_t utoff;
|
||||
u_int8_t dst;
|
||||
u_int8_t idx;
|
||||
} TimeTypeRecord;
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(TimeTypeRecord) == 0x6);
|
||||
|
||||
class Data {
|
||||
public:
|
||||
explicit Data() = default;
|
||||
virtual ~Data() = default;
|
||||
|
||||
virtual void ReformatNintendo(std::vector<u_int8_t> &buffer) const = 0;
|
||||
};
|
||||
|
||||
class DataImpl : public Data {
|
||||
public:
|
||||
explicit DataImpl() = default;
|
||||
~DataImpl() override = default;
|
||||
|
||||
void ReformatNintendo(std::vector<u_int8_t> &buffer) const override;
|
||||
|
||||
Header header;
|
||||
Footer footer;
|
||||
|
||||
std::unique_ptr<int64_t[]> transition_times;
|
||||
std::unique_ptr<u_int8_t[]> transition_types;
|
||||
std::unique_ptr<TimeTypeRecord[]> local_time_type_records;
|
||||
std::unique_ptr<int8_t[]> time_zone_designations;
|
||||
std::unique_ptr<u_int8_t[]> standard_indicators;
|
||||
std::unique_ptr<u_int8_t[]> ut_indicators;
|
||||
};
|
||||
|
||||
std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size);
|
||||
|
||||
} // namespace Tzif
|
Loading…
Add table
Add a link
Reference in a new issue