aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan200101 <sentrycraft123@gmail.com>2022-02-27 17:04:11 +0100
committerJan200101 <sentrycraft123@gmail.com>2022-02-27 17:04:11 +0100
commit346f8781f25255a35e708b22aea7e582853422bb (patch)
treedd1012d40a444c1733a89a5b1c4870e2e2c1edf4
download3ds-splash-346f8781f25255a35e708b22aea7e582853422bb.tar.gz
3ds-splash-346f8781f25255a35e708b22aea7e582853422bb.zip
baseline
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt18
-rw-r--r--LICENSE22
-rw-r--r--README.md11
-rw-r--r--cmake/Findlibpng.cmake68
-rw-r--r--src/CMakeLists.txt27
-rw-r--r--src/image.c141
-rw-r--r--src/image.h13
-rw-r--r--src/main.c133
9 files changed, 434 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..3ba38ad
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.18)
+
+if(CMAKE_POLICY_DEFAULT_CMP0017 OR CMAKE_POLICY_DEFAULT_CMP0020)
+ # touch these to remove warnings
+endif()
+
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING
+ "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
+endif()
+
+project(splash VERSION 0.0.0 LANGUAGES C)
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+add_compile_definitions(VERSION=${CMAKE_PROJECT_VERSION})
+
+add_subdirectory(src) \ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1b5a336
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2022 Jan Drögehoff
+
+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.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bc4eab7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,11 @@
+# 3ds-splash
+
+C program intended to convert splash screen binaries to image files and back
+developed as a reference for any future implementation dealing with this
+
+### Dependencies
+- libpng
+
+### [License](LICENSE)
+
+3ds-splash is licensed under MIT \ No newline at end of file
diff --git a/cmake/Findlibpng.cmake b/cmake/Findlibpng.cmake
new file mode 100644
index 0000000..62c4d87
--- /dev/null
+++ b/cmake/Findlibpng.cmake
@@ -0,0 +1,68 @@
+#
+# LIBPNG_INCLUDE_DIRS
+# LIBPNG_LIBRARIES
+# LIBPNG_CFLAGS
+# LIBPNG_FOUND
+
+
+find_package(PkgConfig QUIET)
+if (PKG_CONFIG_FOUND)
+ pkg_check_modules(_LIBPNG libpng)
+
+ if (BUILD_STATIC AND NOT _LIBPNG_FOUND)
+ message(FATAL_ERROR "Cannot find static build information")
+ endif()
+endif()
+set(LIBPNG_FOUND ${_LIBPNG_FOUND})
+
+if (_LIBPNG_FOUND) # we can rely on pkg-config
+
+ if (NOT BUILD_STATIC)
+ set(LIBPNG_LIBRARIES ${_LIBPNG_LIBRARIES})
+ set(LIBPNG_INCLUDE_DIRS ${_LIBPNG_INCLUDE_DIRS})
+ set(LIBPNG_CFLAGS ${_LIBPNG_CFLAGS_OTHER})
+ else()
+ set(LIBPNG_LIBRARIES ${_LIBPNG_STATIC_LIBRARIES})
+ set(LIBPNG_INCLUDE_DIRS ${_LIBPNG_STATIC_INCLUDE_DIRS})
+ set(LIBPNG_CFLAGS ${_LIBPNG_STATIC_CFLAGS_OTHER})
+ endif()
+else()
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_lib_suffix 64)
+ else()
+ set(_lib_suffix 32)
+ endif()
+
+ find_path(LIBPNG_INC
+ NAMES png.h
+ HINTS
+ ENV LIBPNGPath${_lib_suffix}
+ ENV LIBPNGPath
+ ${_LIBPNG_INCLUDE_DIRS}
+ PATHS
+ /usr/include/libpng16 /usr/local/include/libpng16
+ /usr/include/libpng /usr/local/include/libpng)
+
+ find_library(LIBPNG_LIB
+ NAMES ${_LIBPNG_LIBRARIES} libpng.so libpng16.so
+ HINTS
+ ENV LIBPNGPath${_lib_suffix}
+ ENV LIBPNGPath
+ ${_LIBPNG_LIBRARY_DIRS}
+ ${_LIBPNG_STATIC_LIBRARY_DIRS}
+ PATHS
+ /usr/lib${_lib_suffix} /usr/local/lib${_lib_suffix}
+ /usr/lib /usr/local/lib)
+
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(LIBPNG DEFAULT_MSG LIBPNG_LIB LIBPNG_INC)
+ mark_as_advanced(LIBPNG_INC LIBPNG_LIB)
+
+ if(LIBPNG_FOUND)
+ set(LIBPNG_INCLUDE_DIRS ${LIBPNG_INC})
+ set(LIBPNG_LIBRARIES ${LIBPNG_LIB})
+ if (BUILD_STATIC)
+ set(LIBPNG_LIBRARIES ${LIBPNG_LIBRARIES} ${_LIBPNG_STATIC_LIBRARIES})
+ endif()
+ endif()
+endif() \ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..63e18a6
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,27 @@
+
+find_package(libpng REQUIRED)
+
+list(APPEND
+ SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/image.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/image.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/main.c
+)
+
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+
+set(CFLAGS
+ -Wall -Wextra -pedantic
+ -Wconversion -Wshadow -Wstrict-aliasing
+ -Winit-self -Wcast-align -Wpointer-arith
+ -Wmissing-declarations -Wmissing-include-dirs
+ -Wno-unused-parameter -Wuninitialized
+)
+
+add_executable(splash ${SOURCES})
+target_compile_options(splash PUBLIC ${CFLAGS})
+
+target_include_directories(splash PUBLIC ${LIBPNG_INCLUDE_DIRS})
+
+target_link_libraries(splash LINK_PUBLIC ${LIBPNG_LIBRARIES})
+target_link_libraries(splash LINK_PUBLIC m)
diff --git a/src/image.c b/src/image.c
new file mode 100644
index 0000000..618a854
--- /dev/null
+++ b/src/image.c
@@ -0,0 +1,141 @@
+#include <stdlib.h>
+#include <png.h>
+
+#include "image.h"
+
+size_t bin_to_rgba(uint8_t** bufp, size_t size)
+{
+ size_t out_size = (size / 3) * 4;
+ uint8_t* buf = malloc(out_size);
+
+ for (size_t i = 0, j = 0; i < size; i+=3, j+=4)
+ {
+ (buf+j)[0] = (*bufp+i)[2];
+ (buf+j)[1] = (*bufp+i)[1];
+ (buf+j)[2] = (*bufp+i)[0];
+ (buf+j)[3] = 0xFF;
+ }
+ free(*bufp);
+ *bufp = buf;
+ return out_size;
+}
+
+
+size_t rgba_to_bin(uint8_t** bufp, size_t size)
+{
+ size_t out_size = (size / 4) * 3;
+ uint8_t* buf = malloc(out_size);
+
+ for (size_t i = 0, j = 0; i < size; i+=4, j+=3)
+ {
+ (buf+j)[0] = (*bufp+i)[2];
+ (buf+j)[1] = (*bufp+i)[1];
+ (buf+j)[2] = (*bufp+i)[0];
+ }
+ free(*bufp);
+ *bufp = buf;
+ return out_size;
+}
+
+size_t png_to_rgba(uint8_t** bufp, size_t size)
+{
+ size_t out_size = 0;
+
+ uint32_t* buf = (uint32_t*)*bufp;
+ FILE* fp = fmemopen(buf, size, "rb");;
+ png_bytep* row_pointers = NULL;
+
+ png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_infop info = png_create_info_struct(png);
+
+ png_init_io(png, fp);
+ png_read_info(png, info);
+
+ if(png_get_bit_depth(png, info) == 16) png_set_strip_16(png);
+
+ uint32_t w = png_get_image_width(png, info);
+ uint32_t h = png_get_image_height(png, info);
+
+ printf("%i, %i\n", w, h);
+
+ png_byte color_type = png_get_color_type(png, info);
+
+ if(color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png);
+
+ if(png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png);
+
+ row_pointers = malloc(sizeof(png_bytep) * h);
+ out_size = sizeof(uint32_t) * (w * h);
+ uint32_t* out = malloc(out_size);
+ for(uint32_t y = 0; y < h; y++)
+ {
+ row_pointers[y] = (png_byte*)(out+(w*y));
+ }
+
+ png_read_image(png, row_pointers);
+
+ png_destroy_read_struct(&png, &info, NULL);
+
+ if (fp) fclose(fp);
+ if (row_pointers) free(row_pointers);
+
+ free(*bufp);
+ *bufp = (uint8_t*)out;
+
+ return out_size;
+}
+
+#define DEFAULT_WIDTH 240
+
+size_t rgba_to_png(uint8_t** bufp, size_t size)
+{
+ uint32_t* buf = (uint32_t*)*bufp;
+
+ size_t out_size = size;
+ uint32_t* out = malloc(out_size);
+ memset(out, 0, out_size);
+ //FILE *fp = fopen("out.png", "wb");
+ FILE* fp = fmemopen(out, size, "wb");
+ png_bytep* row_pointers = NULL;
+
+ uint32_t w = 240;
+ uint32_t h = (uint32_t)((size/4)/w);
+
+ printf("%i, %i\n", w, h);
+
+ printf("%li\n", size);
+
+ /* initialize stuff */
+ png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_infop info_ptr = png_create_info_struct(png);
+
+ png_init_io(png, fp);
+
+ png_set_IHDR(png, info_ptr, w, h,
+ 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+ png_write_info(png, info_ptr);
+
+ row_pointers = malloc(sizeof(png_bytep) * h);
+ for(uint32_t y = 0; y < h; y++)
+ {
+ row_pointers[y] = (png_byte*)(buf+(w*y));
+ }
+
+ png_write_image(png, row_pointers);
+
+ png_write_end(png, NULL);
+
+ free(row_pointers);
+ fclose(fp);
+
+ while (!out[out_size/4]) --out_size;
+
+ free(buf);
+ *bufp = out;
+
+ return out_size;
+} \ No newline at end of file
diff --git a/src/image.h b/src/image.h
new file mode 100644
index 0000000..5c14fdf
--- /dev/null
+++ b/src/image.h
@@ -0,0 +1,13 @@
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+size_t bin_to_rgba(uint8_t**, size_t);
+size_t rgba_to_bin(uint8_t**, size_t);
+
+size_t png_to_rgba(uint8_t**, size_t);
+size_t rgba_to_png(uint8_t**, size_t);
+
+#endif \ No newline at end of file
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..b4fea17
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "image.h"
+
+#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0])
+
+#define FORMAT_ERROR "%s is not in a supported format\n"
+
+typedef size_t (*splash_func)(uint8_t**, size_t);
+typedef struct {
+ char* extension;
+ splash_func func;
+} splash_types;
+
+const splash_types in_conversions[] = {
+ { .extension = "bin", .func = bin_to_rgba },
+ { .extension = "png", .func = png_to_rgba },
+};
+
+const splash_types out_conversions[] = {
+ { .extension = "bin", .func = rgba_to_bin },
+ { .extension = "png", .func = rgba_to_png },
+};
+
+int main(int argc, char** argv)
+{
+ FILE* in_fd = NULL;
+ FILE* out_fd = NULL;
+
+ int retval = EXIT_SUCCESS;
+ if (argc < 3)
+ {
+ fprintf(stderr, "%s [input] [output]\n", argv[0]);
+ retval = EXIT_FAILURE;
+ goto exit;
+ }
+
+ char* in_path = argv[1];
+ size_t in_path_len = strlen(in_path);
+ splash_func in_func = NULL;
+
+ char* out_path = argv[2];
+ size_t out_path_len = strlen(out_path);
+ splash_func out_func = NULL;
+
+ for (size_t i = 0; i <= ARRAY_LEN(in_conversions); ++i)
+ {
+ if (i == ARRAY_LEN(in_conversions))
+ {
+ fprintf(stderr, FORMAT_ERROR, in_path);
+ retval = EXIT_FAILURE;
+ goto exit;
+ }
+
+ char* extension = in_conversions[i].extension;
+ if (!strcmp(in_path+(in_path_len-strlen(extension)), extension))
+ {
+ in_func = in_conversions[i].func;
+ break;
+ }
+ }
+
+ for (size_t i = 0; i <= ARRAY_LEN(out_conversions); ++i)
+ {
+ if (i == ARRAY_LEN(out_conversions))
+ {
+ fprintf(stderr, FORMAT_ERROR, out_path);
+ retval = EXIT_FAILURE;
+ goto exit;
+ }
+
+ char* extension = out_conversions[i].extension;
+ if (!strcmp(out_path+(out_path_len-strlen(extension)), extension))
+ {
+ out_func = out_conversions[i].func;
+ break;
+ }
+ }
+
+
+ in_fd = fopen(in_path, "rb");
+ if (!in_fd)
+ {
+ fprintf(stderr, "cannot open %s\n", in_path);
+ retval = EXIT_FAILURE;
+ goto exit;
+ }
+
+ fseek(in_fd, 0L, SEEK_END);
+ size_t in_size = (size_t)ftell(in_fd);
+ rewind(in_fd);
+
+ if (!in_size)
+ {
+ fprintf(stderr, "%s is empty\n", in_path);
+ retval = EXIT_FAILURE;
+ goto exit;
+ }
+
+ out_fd = fopen(out_path, "wb");
+ if (!out_fd)
+ {
+ fprintf(stderr, "cannot open %s\n", out_path);
+ retval = EXIT_FAILURE;
+ goto exit;
+ }
+
+ uint8_t* buf = malloc(in_size+1);
+ fread(buf, 1, in_size, in_fd);
+ buf[in_size] = '\0';
+
+ if (in_func)
+ {
+ in_size = in_func(&buf, in_size);
+ }
+
+ if (out_func)
+ {
+ in_size = out_func(&buf, in_size);
+ }
+
+ fwrite(buf, 1, in_size, out_fd);
+
+ exit:
+
+ if (in_fd) fclose(in_fd);
+ if (out_fd) fclose(out_fd);
+
+ return retval;
+} \ No newline at end of file