add option to load textures from external files

this stores the null terminated texture name instead of the texture data

activated with EXTERNAL_TEXTURES=1
This commit is contained in:
fgsfds 2020-05-25 04:21:36 +03:00
parent 87d6f30a08
commit 9825b02f50
9 changed files with 91 additions and 17 deletions

View file

@ -42,6 +42,8 @@ TEXTURE_FIX ?= 0
EXT_OPTIONS_MENU ?= 1 EXT_OPTIONS_MENU ?= 1
# Disable text-based save-files by default # Disable text-based save-files by default
TEXTSAVES ?= 0 TEXTSAVES ?= 0
# Load textures from external PNG files
EXTERNAL_TEXTURES ?= 0
# Various workarounds for weird toolchains # Various workarounds for weird toolchains
@ -552,6 +554,14 @@ ifeq ($(LEGACY_GL),1)
CFLAGS += -DLEGACY_GL CFLAGS += -DLEGACY_GL
endif 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) ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS)
ifeq ($(TARGET_WEB),1) ifeq ($(TARGET_WEB),1)
@ -606,6 +616,16 @@ SHA1SUM = sha1sum
all: $(EXE) 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: clean:
$(RM) -r $(BUILD_DIR_BASE) $(RM) -r $(BUILD_DIR_BASE)
@ -700,13 +720,19 @@ endif
################################################################ ################################################################
# RGBA32, RGBA16, IA16, IA8, IA4, IA1, I8, I4 # 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 $(BUILD_DIR)/%: %.png
$(N64GRAPHICS) -i $@ -g $< -f $(lastword $(subst ., ,$@)) $(N64GRAPHICS) -i $@ -g $< -f $(lastword $(subst ., ,$@))
endif
$(BUILD_DIR)/%.inc.c: $(BUILD_DIR)/% %.png $(BUILD_DIR)/%.inc.c: $(BUILD_DIR)/% %.png
hexdump -v -e '1/1 "0x%X,"' $< > $@ hexdump -v -e '1/1 "0x%X,"' $< > $@
echo >> $@ echo >> $@
ifeq ($(EXTERNAL_TEXTURES),0)
# Color Index CI8 # Color Index CI8
$(BUILD_DIR)/%.ci8: %.ci8.png $(BUILD_DIR)/%.ci8: %.ci8.png
$(N64GRAPHICS_CI) -i $@ -g $< -f ci8 $(N64GRAPHICS_CI) -i $@ -g $< -f ci8
@ -714,6 +740,7 @@ $(BUILD_DIR)/%.ci8: %.ci8.png
# Color Index CI4 # Color Index CI4
$(BUILD_DIR)/%.ci4: %.ci4.png $(BUILD_DIR)/%.ci4: %.ci4.png
$(N64GRAPHICS_CI) -i $@ -g $< -f ci4 $(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) $(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) $(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)/% .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: .DELETE_ON_ERROR:

View file

@ -5,7 +5,7 @@
# obtain a list of segments from the *.c files in bin directory # 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)))) 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/*/)) 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.<encoding>.png" generates "texture.<encoding>" # NOTE: textures assume naming convention "texture.<encoding>.png" generates "texture.<encoding>"
@ -165,9 +165,9 @@ $(eval $(call level_rules,menu,generic)) # Menu (File Select)
# Ending cake textures are generated in a special way # Ending cake textures are generated in a special way
$(BUILD_DIR)/levels/ending/cake_eu.inc.c: levels/ending/cake_eu.png $(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 $(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 # 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 $(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 $(BUILD_DIR)/bin/%_skybox.elf: SEGMENT_ADDRESS := 0x0A000000

View file

@ -4,6 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
#define CONFIGFILE_DEFAULT "sm64config.txt" #define CONFIGFILE_DEFAULT "sm64config.txt"
#define DATAPATH_DEFAULT "res"
#define MAX_BINDS 3 #define MAX_BINDS 3
#define MAX_VOLUME 127 #define MAX_VOLUME 127

View file

@ -5,6 +5,11 @@
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#ifdef EXTERNAL_TEXTURES
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#endif
#ifndef _LANGUAGE_C #ifndef _LANGUAGE_C
#define _LANGUAGE_C #define _LANGUAGE_C
#endif #endif
@ -315,6 +320,7 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
return false; return false;
} }
#ifndef EXTERNAL_TEXTURES
static void import_texture_rgba32(int tile) { static void import_texture_rgba32(int tile) {
uint32_t width = rdp.texture_tile.line_size_bytes / 2; 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; 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); gfx_rapi->upload_texture(rgba32_buf, width, height);
} }
#endif // EXTERNAL_TEXTURES
static void import_texture(int tile) { static void import_texture(int tile) {
uint8_t fmt = rdp.texture_tile.fmt; uint8_t fmt = rdp.texture_tile.fmt;
@ -495,6 +502,22 @@ static void import_texture(int tile) {
return; 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(); int t0 = get_time();
if (fmt == G_IM_FMT_RGBA) { if (fmt == G_IM_FMT_RGBA) {
if (siz == G_IM_SIZ_32b) { if (siz == G_IM_SIZ_32b) {
@ -536,6 +559,7 @@ static void import_texture(int tile) {
} }
int t1 = get_time(); int t1 = get_time();
//printf("Time diff: %d\n", t1 - t0); //printf("Time diff: %d\n", t1 - t0);
#endif
} }
static void gfx_normalize_vector(float v[3]) { static void gfx_normalize_vector(float v[3]) {

View file

@ -4,7 +4,7 @@ ifeq ($(UNAME),Darwin)
endif endif
CC := gcc 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 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 n64graphics_SOURCES := n64graphics.c utils.c

View file

@ -6,9 +6,9 @@
#define STBI_NO_HDR #define STBI_NO_HDR
#define STBI_NO_TGA #define STBI_NO_TGA
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "../stb/stb_image.h" #include <stb/stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION
#include "../stb/stb_image_write.h" #include <stb/stb_image_write.h>
#include "exoquant/exoquant.h" #include "exoquant/exoquant.h"

View file

@ -75,6 +75,7 @@ char *writeDir;
char skyboxName[256]; char skyboxName[256];
bool expanded = false; bool expanded = false;
bool writeTiles; bool writeTiles;
bool storeNamesOnly = false;
static void allocate_tiles() { static void allocate_tiles() {
const ImageProps props = IMAGE_PROPERTIES[type][true]; 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++) { for (int i = 0; i < props.numRows * props.numCols; i++) {
if (!tiles[i].useless) { if (!tiles[i].useless) {
fprintf(cFile, "ALIGNED8 static const u8 %s_skybox_texture_%05X[] = {\n", skyboxName, tiles[i].pos); if (storeNamesOnly) {
fprintf(
print_raw_data(cFile, &tiles[i]); cFile,
"ALIGNED8 static const u8 %s_skybox_texture_%05X[] = "
fputs("};\n\n", cFile); "\"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; int numTiles = TABLE_DIMENSIONS[type].cols * TABLE_DIMENSIONS[type].rows;
for (int i = 0; i < numTiles; ++i) { for (int i = 0; i < numTiles; ++i) {
fprintf(cFile, "ALIGNED8 static const u8 cake_end_texture_%s%d[] = {\n", euSuffx, i); if (storeNamesOnly) {
print_raw_data(cFile, &tiles[i]); fprintf(
fputs("};\n\n", cFile); 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); fclose(cFile);
} }
@ -473,7 +490,8 @@ static void usage() {
"Usage: %s --type sky|cake|cake_eu {--combine INPUT OUTPUT | --split INPUT OUTPUT}\n" "Usage: %s --type sky|cake|cake_eu {--combine INPUT OUTPUT | --split INPUT OUTPUT}\n"
"\n" "\n"
"Optional arguments:\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 // Modified from n64split
@ -529,6 +547,10 @@ static int parse_arguments(int argc, char *argv[]) {
writeTiles = true; writeTiles = true;
writeDir = argv[i]; writeDir = argv[i];
} }
if (strcmp(argv[i], "--store-names") == 0) {
storeNamesOnly = true;
}
} }
return 1; return 1;