diff --git a/Makefile b/Makefile index 2444468c..e9ebc5d0 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,8 @@ TEXTURE_FIX ?= 0 EXT_OPTIONS_MENU ?= 1 # Disable text-based save-files by default TEXTSAVES ?= 0 +# Load textures from external PNG files +EXTERNAL_TEXTURES ?= 0 # Various workarounds for weird toolchains @@ -552,6 +554,14 @@ ifeq ($(LEGACY_GL),1) CFLAGS += -DLEGACY_GL endif +# Load external textures +ifeq ($(EXTERNAL_TEXTURES),1) + CC_CHECK += -DEXTERNAL_TEXTURES + CFLAGS += -DEXTERNAL_TEXTURES + # tell skyconv to write names instead of actual texture data and save the split tiles so we can use them later + SKYCONV_ARGS := --store-names --write-tiles "$(BUILD_DIR)/textures/skybox_tiles" +endif + ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) ifeq ($(TARGET_WEB),1) @@ -606,6 +616,16 @@ SHA1SUM = sha1sum all: $(EXE) +ifeq ($(EXTERNAL_TEXTURES),1) +# prepares the resource folder for external data +res: $(EXE) + @mkdir -p $(BUILD_DIR)/res + @cp -r -f textures/ $(BUILD_DIR)/res/ + @cp -r -f $(BUILD_DIR)/textures/skybox_tiles/ $(BUILD_DIR)/res/textures/ + @find actors -name \*.png -exec cp --parents {} $(BUILD_DIR)/res/ \; + @find levels -name \*.png -exec cp --parents {} $(BUILD_DIR)/res/ \; +endif + clean: $(RM) -r $(BUILD_DIR_BASE) @@ -700,13 +720,19 @@ endif ################################################################ # RGBA32, RGBA16, IA16, IA8, IA4, IA1, I8, I4 +ifeq ($(EXTERNAL_TEXTURES),1) +$(BUILD_DIR)/%: %.png + printf "%s%b" "$(patsubst %.png,%,$^)" '\x00' > $@ +else $(BUILD_DIR)/%: %.png $(N64GRAPHICS) -i $@ -g $< -f $(lastword $(subst ., ,$@)) +endif $(BUILD_DIR)/%.inc.c: $(BUILD_DIR)/% %.png hexdump -v -e '1/1 "0x%X,"' $< > $@ echo >> $@ +ifeq ($(EXTERNAL_TEXTURES),0) # Color Index CI8 $(BUILD_DIR)/%.ci8: %.ci8.png $(N64GRAPHICS_CI) -i $@ -g $< -f ci8 @@ -714,6 +740,7 @@ $(BUILD_DIR)/%.ci8: %.ci8.png # Color Index CI4 $(BUILD_DIR)/%.ci4: %.ci4.png $(N64GRAPHICS_CI) -i $@ -g $< -f ci4 +endif ################################################################ @@ -857,7 +884,7 @@ $(BUILD_DIR)/%.o: %.s $(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LD) -L $(BUILD_DIR) -o $@ $(O_FILES) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS) -.PHONY: all clean distclean default diff test load libultra +.PHONY: all clean distclean default diff test load libultra res .PRECIOUS: $(BUILD_DIR)/bin/%.elf $(SOUND_BIN_DIR)/%.ctl $(SOUND_BIN_DIR)/%.tbl $(SOUND_SAMPLE_TABLES) $(SOUND_BIN_DIR)/%.s $(BUILD_DIR)/% .DELETE_ON_ERROR: diff --git a/Makefile.split b/Makefile.split index 9619c603..c7bdaa2e 100644 --- a/Makefile.split +++ b/Makefile.split @@ -5,7 +5,7 @@ # obtain a list of segments from the *.c files in bin directory SEGMENTS := $(notdir $(basename $(wildcard bin/*.c))) $(addprefix $(VERSION)/,$(notdir $(basename $(wildcard bin/$(VERSION)/*.c)))) $(addsuffix _skybox,$(notdir $(basename $(wildcard textures/skyboxes/*.png)))) ACTORS := $(filter %/,$(wildcard actors/*/)) -TEXTURE_DIRS := $(addprefix textures/,$(SEGMENTS)) $(ACTORS) textures/intro_raw +TEXTURE_DIRS := $(addprefix textures/,$(SEGMENTS)) $(ACTORS) textures/intro_raw textures/skybox_tiles # NOTE: textures assume naming convention "texture..png" generates "texture." @@ -165,9 +165,9 @@ $(eval $(call level_rules,menu,generic)) # Menu (File Select) # Ending cake textures are generated in a special way $(BUILD_DIR)/levels/ending/cake_eu.inc.c: levels/ending/cake_eu.png - $(SKYCONV) --type cake-eu --split $^ $(BUILD_DIR)/levels/ending + $(SKYCONV) $(SKYCONV_ARGS) --type cake-eu --split $^ $(BUILD_DIR)/levels/ending $(BUILD_DIR)/levels/ending/cake.inc.c: levels/ending/cake.png - $(SKYCONV) --type cake --split $^ $(BUILD_DIR)/levels/ending + $(SKYCONV) $(SKYCONV_ARGS) --type cake --split $^ $(BUILD_DIR)/levels/ending # -------------------------------------- # Texture Bin Rules @@ -235,7 +235,7 @@ $(BUILD_DIR)/bin/eu/translation_fr.elf: SEGMENT_ADDRESS := 0x19000000 # -------------------------------------- $(BUILD_DIR)/bin/%_skybox.c: textures/skyboxes/%.png - $(SKYCONV) --type sky --split $^ $(BUILD_DIR)/bin + $(SKYCONV) $(SKYCONV_ARGS) --type sky --split $^ $(BUILD_DIR)/bin $(BUILD_DIR)/bin/%_skybox.elf: SEGMENT_ADDRESS := 0x0A000000 diff --git a/tools/stb/stb_image.h b/include/stb/stb_image.h similarity index 100% rename from tools/stb/stb_image.h rename to include/stb/stb_image.h diff --git a/tools/stb/stb_image_write.h b/include/stb/stb_image_write.h similarity index 100% rename from tools/stb/stb_image_write.h rename to include/stb/stb_image_write.h diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 17a7e25d..6f2c4a25 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -4,6 +4,7 @@ #include #define CONFIGFILE_DEFAULT "sm64config.txt" +#define DATAPATH_DEFAULT "res" #define MAX_BINDS 3 #define MAX_VOLUME 127 diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index e2aadfa1..210c34ff 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -5,6 +5,11 @@ #include #include +#ifdef EXTERNAL_TEXTURES +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + #ifndef _LANGUAGE_C #define _LANGUAGE_C #endif @@ -315,6 +320,7 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co return false; } +#ifndef EXTERNAL_TEXTURES static void import_texture_rgba32(int tile) { uint32_t width = rdp.texture_tile.line_size_bytes / 2; uint32_t height = (rdp.loaded_texture[tile].size_bytes / 2) / rdp.texture_tile.line_size_bytes; @@ -486,6 +492,7 @@ static void import_texture_ci8(int tile) { gfx_rapi->upload_texture(rgba32_buf, width, height); } +#endif // EXTERNAL_TEXTURES static void import_texture(int tile) { uint8_t fmt = rdp.texture_tile.fmt; @@ -495,6 +502,22 @@ static void import_texture(int tile) { return; } +#ifdef EXTERNAL_TEXTURES + // the "texture data" is actually a C string with the path to our texture in it + // load it from an external image in our data path + static char fpath[1024]; + int w, h; + const char *texname = (const char*)rdp.loaded_texture[tile].addr; + snprintf(fpath, sizeof(fpath), "%s/%s.png", DATAPATH_DEFAULT, texname); + u8 *data = stbi_load(fpath, &w, &h, NULL, 4); + if (!data) { + fprintf(stderr, "texture not found: `%s`\n", fpath); + abort(); + } + gfx_rapi->upload_texture(data, w, h); + stbi_image_free(data); // don't need this anymore +#else + // the texture data is actual texture data int t0 = get_time(); if (fmt == G_IM_FMT_RGBA) { if (siz == G_IM_SIZ_32b) { @@ -536,6 +559,7 @@ static void import_texture(int tile) { } int t1 = get_time(); //printf("Time diff: %d\n", t1 - t0); +#endif } static void gfx_normalize_vector(float v[3]) { diff --git a/tools/Makefile b/tools/Makefile index 0d8e6dd7..d81f5f9a 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -4,7 +4,7 @@ ifeq ($(UNAME),Darwin) endif CC := gcc -CFLAGS := -Llib -Iinclude -I . -Wall -Wextra -Wno-unused-parameter $(OSX_BUILD) -pedantic -std=c99 -O3 -s +CFLAGS := -Llib -I../include -I . -Wall -Wextra -Wno-unused-parameter $(OSX_BUILD) -pedantic -std=c99 -O3 -s PROGRAMS := n64graphics n64graphics_ci mio0 n64cksum textconv patch_libultra_math iplfontutil aifc_decode aiff_extract_codebook vadpcm_enc tabledesign extract_data_for_mio skyconv n64graphics_SOURCES := n64graphics.c utils.c diff --git a/tools/n64graphics_ci_dir/n64graphics_ci.c b/tools/n64graphics_ci_dir/n64graphics_ci.c index 6ec4476a..05fe88aa 100644 --- a/tools/n64graphics_ci_dir/n64graphics_ci.c +++ b/tools/n64graphics_ci_dir/n64graphics_ci.c @@ -6,9 +6,9 @@ #define STBI_NO_HDR #define STBI_NO_TGA #define STB_IMAGE_IMPLEMENTATION -#include "../stb/stb_image.h" +#include #define STB_IMAGE_WRITE_IMPLEMENTATION -#include "../stb/stb_image_write.h" +#include #include "exoquant/exoquant.h" diff --git a/tools/skyconv.c b/tools/skyconv.c index 4fb0523e..a66c5c1b 100644 --- a/tools/skyconv.c +++ b/tools/skyconv.c @@ -75,6 +75,7 @@ char *writeDir; char skyboxName[256]; bool expanded = false; bool writeTiles; +bool storeNamesOnly = false; static void allocate_tiles() { const ImageProps props = IMAGE_PROPERTIES[type][true]; @@ -291,11 +292,18 @@ static void write_skybox_c() { /* write c data to disc */ for (int i = 0; i < props.numRows * props.numCols; i++) { if (!tiles[i].useless) { - fprintf(cFile, "ALIGNED8 static const u8 %s_skybox_texture_%05X[] = {\n", skyboxName, tiles[i].pos); - - print_raw_data(cFile, &tiles[i]); - - fputs("};\n\n", cFile); + if (storeNamesOnly) { + fprintf( + cFile, + "ALIGNED8 static const u8 %s_skybox_texture_%05X[] = " + "\"textures/skybox_tiles/%s.%d.rgba16\";\n\n", + skyboxName, tiles[i].pos, skyboxName, tiles[i].pos + ); + } else { + fprintf(cFile, "ALIGNED8 static const u8 %s_skybox_texture_%05X[] = {\n", skyboxName, tiles[i].pos); + print_raw_data(cFile, &tiles[i]); + fputs("};\n\n", cFile); + } } } @@ -334,9 +342,18 @@ static void write_cake_c() { int numTiles = TABLE_DIMENSIONS[type].cols * TABLE_DIMENSIONS[type].rows; for (int i = 0; i < numTiles; ++i) { - fprintf(cFile, "ALIGNED8 static const u8 cake_end_texture_%s%d[] = {\n", euSuffx, i); - print_raw_data(cFile, &tiles[i]); - fputs("};\n\n", cFile); + if (storeNamesOnly) { + fprintf( + cFile, + "ALIGNED8 static const u8 cake_end_texture_%s%d[] = " + "\"textures/skybox_tiles/cake%s.%d.rgba16\";\n\n", + euSuffx, i, *euSuffx ? "_eu" : "", tiles[i].pos + ); + } else { + fprintf(cFile, "ALIGNED8 static const u8 cake_end_texture_%s%d[] = {\n", euSuffx, i); + print_raw_data(cFile, &tiles[i]); + fputs("};\n\n", cFile); + } } fclose(cFile); } @@ -473,7 +490,8 @@ static void usage() { "Usage: %s --type sky|cake|cake_eu {--combine INPUT OUTPUT | --split INPUT OUTPUT}\n" "\n" "Optional arguments:\n" - " --write-tiles OUTDIR Also create the individual tiles' PNG files\n", programName); + " --write-tiles OUTDIR Also create the individual tiles' PNG files\n" + " --store-names Store texture file names instead of actual data\n", programName); } // Modified from n64split @@ -529,6 +547,10 @@ static int parse_arguments(int argc, char *argv[]) { writeTiles = true; writeDir = argv[i]; } + + if (strcmp(argv[i], "--store-names") == 0) { + storeNamesOnly = true; + } } return 1;