Merge remote-tracking branch 'upstream/nightly' into rumble_back

This commit is contained in:
Zerocker 2020-05-29 23:19:09 +09:00
commit 3f1fd3aba8
29 changed files with 1953 additions and 133 deletions

View File

@ -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
@ -126,7 +128,6 @@ endif
# Stuff for showing the git hash in the intro on nightly builds
# From https://stackoverflow.com/questions/44038428/include-git-commit-hash-and-or-branch-name-in-c-c-source
ifeq ($(shell git rev-parse --abbrev-ref HEAD),nightly)
$(info Hello Caldera!!! I'm here all week!)
GIT_HASH=`git rev-parse --short HEAD`
COMPILE_TIME=`date -u +'%Y-%m-%d %H:%M:%S UTC'`
VERSION_CFLAGS += -DNIGHTLY -DGIT_HASH="\"$(GIT_HASH)\"" -DCOMPILE_TIME="\"$(COMPILE_TIME)\""
@ -490,8 +491,8 @@ PYTHON := python3
SDLCONFIG := $(CROSS)sdl2-config
ifeq ($(WINDOWS_BUILD),1)
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(SDLCONFIG) --cflags`
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags`
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(SDLCONFIG) --cflags` -DUSE_SDL=2
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags` -DUSE_SDL=2
else ifeq ($(TARGET_WEB),1)
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -s USE_SDL=2
@ -499,8 +500,8 @@ CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fn
# Linux / Other builds below
else
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(SDLCONFIG) --cflags`
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags`
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(SDLCONFIG) --cflags` -DUSE_SDL=2
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags` -DUSE_SDL=2
endif
# Check for enhancement options
@ -553,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)
@ -598,6 +607,7 @@ EMU_FLAGS = --noosd
LOADER = loader64
LOADER_FLAGS = -vwf
SHA1SUM = sha1sum
ZEROTERM = $(PYTHON) $(TOOLS_DIR)/zeroterm.py
###################### Dependency Check #####################
@ -607,6 +617,19 @@ SHA1SUM = sha1sum
all: $(EXE)
ifeq ($(EXTERNAL_TEXTURES),1)
# depend on resources as well
all: res
# 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)
@ -701,13 +724,19 @@ endif
################################################################
# RGBA32, RGBA16, IA16, IA8, IA4, IA1, I8, I4
ifeq ($(EXTERNAL_TEXTURES),1)
$(BUILD_DIR)/%: %.png
$(ZEROTERM) "$(patsubst %.png,%,$^)" > $@
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
@ -715,6 +744,7 @@ $(BUILD_DIR)/%.ci8: %.ci8.png
# Color Index CI4
$(BUILD_DIR)/%.ci4: %.ci4.png
$(N64GRAPHICS_CI) -i $@ -g $< -f ci4
endif
################################################################
@ -858,7 +888,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:

View File

@ -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.<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
$(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

View File

@ -78,10 +78,10 @@ static const Vtx flame_seg6_vertex_0601C000[] = {
{{{ 150, 150, 0}, 0, { 2016, 992}, {0xff, 0xff, 0xff, 0xff}}},
{{{ 150, 300, 0}, 0, { 2016, 0}, {0xff, 0xff, 0xff, 0xff}}},
{{{ -150, 300, 0}, 0, { 0, 0}, {0xff, 0xff, 0xff, 0xff}}},
{{{ -150, 0, 0}, 0, { 0, 992}, {0xff, 0xff, 0xff, 0xff}}},
{{{ 150, 0, 0}, 0, { 2016, 992}, {0xff, 0xff, 0xff, 0xff}}},
{{{ 150, 150, 0}, 0, { 2016, 0}, {0xff, 0xff, 0xff, 0xff}}},
{{{ -150, 150, 0}, 0, { 0, 0}, {0xff, 0xff, 0xff, 0xff}}},
{{{ -150, 0, 0}, 0, { 0, 2016}, {0xff, 0xff, 0xff, 0xff}}},
{{{ 150, 0, 0}, 0, { 2016, 2016}, {0xff, 0xff, 0xff, 0xff}}},
{{{ 150, 150, 0}, 0, { 2016, 992}, {0xff, 0xff, 0xff, 0xff}}},
{{{ -150, 150, 0}, 0, { 0, 992}, {0xff, 0xff, 0xff, 0xff}}},
};
// 0x0601C080 - 0x0601C0B0
@ -117,10 +117,9 @@ const Gfx flame_seg6_dl_0601C0E0[] = {
// 0x0601C108 - 0x0601C1A8
const Gfx flame_seg6_dl_0601C108[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06000000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06000000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06000000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -129,10 +128,9 @@ const Gfx flame_seg6_dl_0601C108[] = {
// 0x0601C1A8 - 0x0601C248
const Gfx flame_seg6_dl_0601C1A8[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06002000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06002000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06002000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -141,10 +139,9 @@ const Gfx flame_seg6_dl_0601C1A8[] = {
// 0x0601C248 - 0x0601C2E8
const Gfx flame_seg6_dl_0601C248[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06004000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06004000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06004000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -153,10 +150,9 @@ const Gfx flame_seg6_dl_0601C248[] = {
// 0x0601C2E8 - 0x0601C388
const Gfx flame_seg6_dl_0601C2E8[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06006000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06006000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06006000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -165,10 +161,9 @@ const Gfx flame_seg6_dl_0601C2E8[] = {
// 0x0601C388 - 0x0601C428
const Gfx flame_seg6_dl_0601C388[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06008000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06008000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06008000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -177,10 +172,9 @@ const Gfx flame_seg6_dl_0601C388[] = {
// 0x0601C428 - 0x0601C4C8
const Gfx flame_seg6_dl_0601C428[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_0600A000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_0600A000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_0600A000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -189,10 +183,8 @@ const Gfx flame_seg6_dl_0601C428[] = {
// 0x0601C4C8 - 0x0601C568
const Gfx flame_seg6_dl_0601C4C8[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_0600C000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_0600C000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_0600C000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -201,10 +193,9 @@ const Gfx flame_seg6_dl_0601C4C8[] = {
// 0x0601C568 - 0x0601C608
const Gfx flame_seg6_dl_0601C568[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_0600E000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_0600E000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_0600E000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -213,10 +204,9 @@ const Gfx flame_seg6_dl_0601C568[] = {
// 0x0601C608 - 0x0601C6A8
const Gfx flame_seg6_dl_0601C608[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06010000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06010000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06010000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -225,10 +215,9 @@ const Gfx flame_seg6_dl_0601C608[] = {
// 0x0601C6A8 - 0x0601C748
const Gfx flame_seg6_dl_0601C6A8[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06012000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06012000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06012000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -237,10 +226,9 @@ const Gfx flame_seg6_dl_0601C6A8[] = {
// 0x0601C748 - 0x0601C7E8
const Gfx flame_seg6_dl_0601C748[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06014000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06014000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06014000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -249,10 +237,9 @@ const Gfx flame_seg6_dl_0601C748[] = {
// 0x0601C7E8 - 0x0601C888
const Gfx flame_seg6_dl_0601C7E8[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06016000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06016000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06016000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -261,10 +248,9 @@ const Gfx flame_seg6_dl_0601C7E8[] = {
// 0x0601C888 - 0x0601C928
const Gfx flame_seg6_dl_0601C888[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_06018000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_06018000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_06018000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),
@ -273,10 +259,9 @@ const Gfx flame_seg6_dl_0601C888[] = {
// 0x0601C928 - 0x0601C9C8
const Gfx flame_seg6_dl_0601C928[] = {
gsSPDisplayList(flame_seg6_dl_0601C080),
gsDPLoadTextureBlock(flame_seg6_texture_0601A000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(flame_seg6_texture_0601A000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(flame_seg6_vertex_0601C000, 8, 0),
gsSPDisplayList(flame_seg6_dl_0601C0B0),
gsDPLoadTextureBlock(flame_seg6_texture_0601A000 + 0x1000, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(flame_seg6_dl_0601C0C8),
gsSPDisplayList(flame_seg6_dl_0601C0E0),
gsSPEndDisplayList(),

View File

@ -28,10 +28,10 @@ static const Vtx impact_smoke_seg6_vertex_06062A28[] = {
{{{ 150, 150, 0}, 0, { 2016, 992}, {0x28, 0x19, 0x14, 0xff}}},
{{{ 150, 300, 0}, 0, { 2016, 0}, {0x28, 0x19, 0x14, 0xff}}},
{{{ -150, 300, 0}, 0, { 0, 0}, {0x28, 0x19, 0x14, 0xff}}},
{{{ -150, 0, 0}, 0, { 0, 992}, {0x28, 0x19, 0x14, 0xff}}},
{{{ 150, 0, 0}, 0, { 2016, 992}, {0x28, 0x19, 0x14, 0xff}}},
{{{ 150, 150, 0}, 0, { 2016, 0}, {0x28, 0x19, 0x14, 0xff}}},
{{{ -150, 150, 0}, 0, { 0, 0}, {0x28, 0x19, 0x14, 0xff}}},
{{{ -150, 0, 0}, 0, { 0, 2016}, {0x28, 0x19, 0x14, 0xff}}},
{{{ 150, 0, 0}, 0, { 2016, 2016}, {0x28, 0x19, 0x14, 0xff}}},
{{{ 150, 150, 0}, 0, { 2016, 992}, {0x28, 0x19, 0x14, 0xff}}},
{{{ -150, 150, 0}, 0, { 0, 992}, {0x28, 0x19, 0x14, 0xff}}},
};
// 0x06062AA8 - 0x06062AD8
@ -68,10 +68,9 @@ const Gfx impact_smoke_seg6_dl_06062B08[] = {
// 0x06062B38 - 0x06062BD8
const Gfx impact_smoke_seg6_dl_06062B38[] = {
gsSPDisplayList(impact_smoke_seg6_dl_06062AA8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605AA28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605AA28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(impact_smoke_seg6_vertex_06062A28, 8, 0),
gsSPDisplayList(impact_smoke_seg6_dl_06062AD8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605AA28 + 0x1000, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(impact_smoke_seg6_dl_06062AF0),
gsSPDisplayList(impact_smoke_seg6_dl_06062B08),
gsSPEndDisplayList(),
@ -80,10 +79,9 @@ const Gfx impact_smoke_seg6_dl_06062B38[] = {
// 0x06062BD8 - 0x06062C78
const Gfx impact_smoke_seg6_dl_06062BD8[] = {
gsSPDisplayList(impact_smoke_seg6_dl_06062AA8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605CA28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605CA28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(impact_smoke_seg6_vertex_06062A28, 8, 0),
gsSPDisplayList(impact_smoke_seg6_dl_06062AD8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605CA28 + 0x1000, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(impact_smoke_seg6_dl_06062AF0),
gsSPDisplayList(impact_smoke_seg6_dl_06062B08),
gsSPEndDisplayList(),
@ -92,10 +90,9 @@ const Gfx impact_smoke_seg6_dl_06062BD8[] = {
// 0x06062C78 - 0x06062D18
const Gfx impact_smoke_seg6_dl_06062C78[] = {
gsSPDisplayList(impact_smoke_seg6_dl_06062AA8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605EA28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605EA28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(impact_smoke_seg6_vertex_06062A28, 8, 0),
gsSPDisplayList(impact_smoke_seg6_dl_06062AD8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_0605EA28 + 0x1000, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(impact_smoke_seg6_dl_06062AF0),
gsSPDisplayList(impact_smoke_seg6_dl_06062B08),
gsSPEndDisplayList(),
@ -104,10 +101,9 @@ const Gfx impact_smoke_seg6_dl_06062C78[] = {
// 0x06062D18 - 0x06062DB8
const Gfx impact_smoke_seg6_dl_06062D18[] = {
gsSPDisplayList(impact_smoke_seg6_dl_06062AA8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_06060A28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_06060A28, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD),
gsSPVertex(impact_smoke_seg6_vertex_06062A28, 8, 0),
gsSPDisplayList(impact_smoke_seg6_dl_06062AD8),
gsDPLoadTextureBlock(impact_smoke_seg6_texture_06060A28 + 0x1000, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD),
gsSPDisplayList(impact_smoke_seg6_dl_06062AF0),
gsSPDisplayList(impact_smoke_seg6_dl_06062B08),
gsSPEndDisplayList(),

View File

@ -66,6 +66,7 @@
#define TEXT_BIND_DOWN _("STICK DOWN")
#define TEXT_BIND_LEFT _("STICK LEFT")
#define TEXT_BIND_RIGHT _("STICK RIGHT")
#define TEXT_OPT_DEADZONE _("STICK DEADZONE")
#define TEXT_OPT_CHEAT1 _("ENABLE CHEATS")
#define TEXT_OPT_CHEAT2 _("MOONJUMP (PRESS L)")
@ -126,6 +127,7 @@
#define TEXT_BIND_DOWN _("Stick Down")
#define TEXT_BIND_LEFT _("Stick Left")
#define TEXT_BIND_RIGHT _("Stick Right")
#define TEXT_OPT_DEADZONE _("Stick Deadzone")
#define TEXT_OPT_CHEAT1 _("Enable cheats")
#define TEXT_OPT_CHEAT2 _("Moonjump (Press L)")

View File

@ -129,7 +129,7 @@ void newcam_init(struct Camera *c, u8 dv)
case LEVEL_CCM: if (gCurrAreaIndex == 1) {newcam_yaw = -0x4000; newcam_tilt = 2000; newcam_distance_target = newcam_distance_values[1];} else newcam_mode = NC_MODE_SLIDE; break;
case LEVEL_WDW: newcam_yaw = 0x2000; newcam_tilt = 3000; newcam_distance_target = newcam_distance_values[1]; break;
case 27: newcam_mode = NC_MODE_SLIDE; break;
case LEVEL_THI: if (gCurrAreaIndex == 2) newcam_mode = NC_MODE_SLIDE; break;
case LEVEL_TTM: if (gCurrAreaIndex == 2) newcam_mode = NC_MODE_SLIDE; break;
}
newcam_distance = newcam_distance_target;

View File

@ -128,7 +128,7 @@ u8 gMenuHoldKeyIndex = 0;
u8 gMenuHoldKeyTimer = 0;
s32 gDialogResponse = 0;
#if defined(VERSION_JP) || defined(VERSION_SH) || defined(VERSION_EU)
#if !defined(EXTERNAL_TEXTURES) && (defined(VERSION_JP) || defined(VERSION_SH) || defined(VERSION_EU))
#ifdef VERSION_EU
#define CHCACHE_BUFLEN (8 * 8) // EU only converts 8x8
#else
@ -242,11 +242,15 @@ static inline void alloc_ia8_text_from_i1(u8 *out, u16 *in, s16 width, s16 heigh
}
static inline u8 *convert_ia8_char(u8 c, u16 *tex, s16 w, s16 h) {
#ifdef EXTERNAL_TEXTURES
return (u8 *)tex; // the data's just a name
#else
if (!charCache[c].used) {
charCache[c].used = 1;
alloc_ia8_text_from_i1(charCache[c].data, tex, w, h);
}
return charCache[c].data;
#endif
}
#endif
@ -298,11 +302,15 @@ static void alloc_ia4_tex_from_i1(u8 *out, u8 *in, s16 width, s16 height) {
}
static u8 *convert_ia4_char(u8 c, u8 *tex, s16 w, s16 h) {
#ifdef EXTERNAL_TEXTURES
return tex; // the data's just a name
#else
if (!charCache[c].used) {
charCache[c].used = 1;
alloc_ia4_tex_from_i1(charCache[c].data, tex, w, h);
}
return charCache[c].data;
#endif
}
void render_generic_char_at_pos(s16 xPos, s16 yPos, u8 c) {

View File

@ -119,6 +119,7 @@ static const u8 bindStr[][32] = {
{ TEXT_BIND_DOWN },
{ TEXT_BIND_LEFT },
{ TEXT_BIND_RIGHT },
{ TEXT_OPT_DEADZONE },
};
static const u8 *filterChoices[] = {
@ -237,6 +238,9 @@ static struct Option optsControls[] = {
DEF_OPT_BIND( bindStr[13], configKeyStickDown ),
DEF_OPT_BIND( bindStr[14], configKeyStickLeft ),
DEF_OPT_BIND( bindStr[15], configKeyStickRight ),
// max deadzone is 31000; this is less than the max range of ~32768, but this
// way, the player can't accidentally lock themselves out of using the stick
DEF_OPT_SCROLL( bindStr[16], &configStickDeadzone, 0, 100, 1 ),
};
static struct Option optsVideo[] = {
@ -503,7 +507,7 @@ void optmenu_toggle(void) {
newcam_init_settings(); // load bettercam settings from config vars
#endif
controller_reconfigure(); // rebind using new config values
configfile_save(gCLIOpts.ConfigFile);
configfile_save(configfile_name());
}
}

View File

@ -2,6 +2,7 @@
#include "configfile.h"
#include "cheats.h"
#include "pc_main.h"
#include "platform.h"
#include <strings.h>
#include <stdlib.h>
@ -15,15 +16,27 @@ static void print_help(void) {
printf("Super Mario 64 PC Port\n");
printf("%-20s\tEnables the cheat menu.\n", "--cheats");
printf("%-20s\tSaves the configuration file as CONFIGNAME.\n", "--configfile CONFIGNAME");
printf("%-20s\tOverrides the default read-only data path ('!' expands to executable path).\n", "--datapath DATAPATH");
printf("%-20s\tOverrides the default save/config path ('!' expands to executable path).\n", "--savepath SAVEPATH");
printf("%-20s\tStarts the game in full screen mode.\n", "--fullscreen");
printf("%-20s\tSkips the Peach and Castle intro when starting a new game.\n", "--skip-intro");
printf("%-20s\tStarts the game in windowed mode.\n", "--windowed");
}
static inline int arg_string(const char *name, const char *value, char *target) {
const unsigned int arglen = strlen(value);
if (arglen >= SYS_MAX_PATH) {
fprintf(stderr, "Supplied value for `%s` is too long.\n", name);
return 0;
}
strncpy(target, value, arglen);
target[arglen] = '\0';
return 1;
}
void parse_cli_opts(int argc, char* argv[]) {
// Initialize options with false values.
memset(&gCLIOpts, 0, sizeof(gCLIOpts));
strncpy(gCLIOpts.ConfigFile, CONFIGFILE_DEFAULT, sizeof(gCLIOpts.ConfigFile));
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--skip-intro") == 0) // Skip Peach Intro
@ -38,25 +51,19 @@ void parse_cli_opts(int argc, char* argv[]) {
else if (strcmp(argv[i], "--cheats") == 0) // Enable cheats menu
Cheats.EnableCheats = true;
else if (strcmp(argv[i], "--configfile") == 0 && (i + 1) < argc)
arg_string("--configfile", argv[++i], gCLIOpts.ConfigFile);
else if (strcmp(argv[i], "--datapath") == 0 && (i + 1) < argc)
arg_string("--datapath", argv[++i], gCLIOpts.DataPath);
else if (strcmp(argv[i], "--savepath") == 0 && (i + 1) < argc)
arg_string("--savepath", argv[++i], gCLIOpts.SavePath);
// Print help
else if (strcmp(argv[i], "--help") == 0) {
print_help();
game_exit();
}
else if (strcmp(argv[i], "--configfile") == 0) {
if (i+1 < argc) {
const unsigned int arglen = strlen(argv[i+1]);
if (arglen >= sizeof(gCLIOpts.ConfigFile)) {
fprintf(stderr, "Configuration file supplied has a name too long.\n");
} else {
strncpy(gCLIOpts.ConfigFile, argv[i+1], arglen);
gCLIOpts.ConfigFile[arglen] = '\0';
}
}
// Skip the next string since it's the configuration file name.
i++;
}
}
}

View File

@ -1,10 +1,14 @@
#ifndef _CLIOPTS_H
#define _CLIOPTS_H
#include "platform.h"
struct PCCLIOptions {
unsigned int SkipIntro;
unsigned int FullScreen;
char ConfigFile[1024];
char ConfigFile[SYS_MAX_PATH];
char SavePath[SYS_MAX_PATH];
char DataPath[SYS_MAX_PATH];
};
extern struct PCCLIOptions gCLIOpts;

View File

@ -7,7 +7,9 @@
#include <ctype.h>
#include <SDL2/SDL.h>
#include "platform.h"
#include "configfile.h"
#include "cliopts.h"
#include "gfx/gfx_screen_config.h"
#include "controller/controller_api.h"
@ -64,7 +66,10 @@ unsigned int configKeyStickUp[MAX_BINDS] = { 0x0011, VK_INVALID, VK_INVALID
unsigned int configKeyStickDown[MAX_BINDS] = { 0x001F, VK_INVALID, VK_INVALID };
unsigned int configKeyStickLeft[MAX_BINDS] = { 0x001E, VK_INVALID, VK_INVALID };
unsigned int configKeyStickRight[MAX_BINDS] = { 0x0020, VK_INVALID, VK_INVALID };
unsigned int configStickDeadzone = 16; // 16*DEADZONE_STEP=4960 (the original default deadzone)
#ifdef EXTERNAL_TEXTURES
bool configPrecacheRes = false;
#endif
#ifdef BETTERCAMERA
// BetterCamera settings
unsigned int configCameraXSens = 50;
@ -103,6 +108,10 @@ static const struct ConfigOption options[] = {
{.name = "key_stickdown", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickDown},
{.name = "key_stickleft", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickLeft},
{.name = "key_stickright", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickRight},
{.name = "stick_deadzone", .type = CONFIG_TYPE_UINT, .uintValue = &configStickDeadzone},
#ifdef EXTERNAL_TEXTURES
{.name = "precache", .type = CONFIG_TYPE_BOOL, .boolValue = &configPrecacheRes},
#endif
#ifdef BETTERCAMERA
{.name = "bettercam_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configEnableCamera},
{.name = "bettercam_mouse_look", .type = CONFIG_TYPE_BOOL, .boolValue = &configCameraMouse},
@ -192,6 +201,18 @@ static unsigned int tokenize_string(char *str, int maxTokens, char **tokens) {
return count;
}
// Gets the config file path and caches it
const char *configfile_name(void) {
static char cfgpath[SYS_MAX_PATH] = { 0 };
if (!cfgpath[0]) {
if (gCLIOpts.ConfigFile[0])
snprintf(cfgpath, sizeof(cfgpath), "%s", gCLIOpts.ConfigFile);
else
snprintf(cfgpath, sizeof(cfgpath), "%s/%s", sys_save_path(), CONFIGFILE_DEFAULT);
}
return cfgpath;
}
// Loads the config file specified by 'filename'
void configfile_load(const char *filename) {
FILE *file;

View File

@ -35,6 +35,10 @@ extern unsigned int configKeyStickUp[];
extern unsigned int configKeyStickDown[];
extern unsigned int configKeyStickLeft[];
extern unsigned int configKeyStickRight[];
extern unsigned int configStickDeadzone;
#ifdef EXTERNAL_TEXTURES
extern bool configPrecacheRes;
#endif
#ifdef BETTERCAMERA
extern unsigned int configCameraXSens;
extern unsigned int configCameraYSens;
@ -50,5 +54,6 @@ extern bool configHUD;
void configfile_load(const char *filename);
void configfile_save(const char *filename);
const char *configfile_name(void);
#endif

View File

@ -1,7 +1,7 @@
#ifndef CONTROLLER_API
#define CONTROLLER_API
#define DEADZONE 4960
#define DEADZONE_STEP 310 // original deadzone is 4960
#define VK_INVALID 0xFFFF
#define VK_SIZE 0x1000

View File

@ -51,7 +51,8 @@ void osContGetReadData(OSContPad *pad) {
#ifdef BETTERCAMERA
uint32_t magnitude_sq = (uint32_t)(rightx * rightx) + (uint32_t)(righty * righty);
if (magnitude_sq > (uint32_t)(DEADZONE * DEADZONE)) {
uint32_t stickDeadzoneActual = configStickDeadzone * DEADZONE_STEP;
if (magnitude_sq > (uint32_t)(stickDeadzoneActual * stickDeadzoneActual)) {
c_rightx = rightx / 0x100;
int stick_y = -righty / 0x100;
c_righty = stick_y == 128 ? 127 : stick_y;

View File

@ -182,7 +182,8 @@ static void controller_sdl_read(OSContPad *pad) {
if (rtrig > 30 * 256) pad->button |= R_TRIG;
uint32_t magnitude_sq = (uint32_t)(leftx * leftx) + (uint32_t)(lefty * lefty);
if (magnitude_sq > (uint32_t)(DEADZONE * DEADZONE)) {
uint32_t stickDeadzoneActual = configStickDeadzone * DEADZONE_STEP;
if (magnitude_sq > (uint32_t)(stickDeadzoneActual * stickDeadzoneActual)) {
pad->stick_x = leftx / 0x100;
int stick_y = -lefty / 0x100;
pad->stick_y = stick_y == 128 ? 127 : stick_y;

View File

@ -5,6 +5,11 @@
#include <stdbool.h>
#include <assert.h>
#ifdef EXTERNAL_TEXTURES
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#endif
#ifndef _LANGUAGE_C
#define _LANGUAGE_C
#endif
@ -18,6 +23,7 @@
#include "gfx_rendering_api.h"
#include "gfx_screen_config.h"
#include "../platform.h"
#include "../configfile.h"
#define SUPPORT_CHECK(x) assert(x)
@ -40,6 +46,17 @@
#define MAX_LIGHTS 2
#define MAX_VERTICES 64
#ifdef EXTERNAL_TEXTURES
# define MAX_CACHED_TEXTURES 4096 // for preloading purposes
# define HASH_SHIFT 0
#else
# define MAX_CACHED_TEXTURES 512
# define HASH_SHIFT 5
#endif
#define HASHMAP_LEN (MAX_CACHED_TEXTURES * 2)
#define HASH_MASK (HASHMAP_LEN - 1)
struct RGBA {
uint8_t r, g, b, a;
};
@ -66,8 +83,8 @@ struct TextureHashmapNode {
bool linear_filter;
};
static struct {
struct TextureHashmapNode *hashmap[1024];
struct TextureHashmapNode pool[512];
struct TextureHashmapNode *hashmap[HASHMAP_LEN];
struct TextureHashmapNode pool[MAX_CACHED_TEXTURES];
uint32_t pool_pos;
} gfx_texture_cache;
@ -155,41 +172,17 @@ static size_t buf_vbo_num_tris;
static struct GfxWindowManagerAPI *gfx_wapi;
static struct GfxRenderingAPI *gfx_rapi;
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && !defined(__APPLE__)
// old mingw
# include <_mingw.h>
# define NO_CLOCK_GETTIME
#ifdef EXTERNAL_TEXTURES
static inline size_t string_hash(const uint8_t *str) {
size_t h = 0;
for (const uint8_t *p = str; *p; p++)
h = 31 * h + *p;
return h;
}
#endif
#ifdef NO_CLOCK_GETTIME
#if defined(_WIN32)
#include <windows.h>
#define CLOCK_MONOTONIC 0
// https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows
struct timespec { long tv_sec; long tv_nsec; };
int clock_gettime(int arg, struct timespec *spec) {
__int64 wintime;
GetSystemTimeAsFileTime((FILETIME*)&wintime);
wintime -= 116444736000000000LL; //1jan1601 to 1jan1970
spec->tv_sec = wintime / 10000000LL; //seconds
spec->tv_nsec = wintime % 10000000LL*100; //nano-seconds
return 0;
}
#else // _WIN32
#error "Add a clock_gettime() impl for your platform!"
#endif // _WIN32
#else // NO_CLOCK_GETTIME
#include <time.h>
#endif // NO_CLOCK_GETTIME
static unsigned long get_time(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (unsigned long)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
return 0;
}
static void gfx_flush(void) {
@ -281,11 +274,19 @@ static struct ColorCombiner *gfx_lookup_or_create_color_combiner(uint32_t cc_id)
}
static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, const uint8_t *orig_addr, uint32_t fmt, uint32_t siz) {
#ifdef EXTERNAL_TEXTURES // hash and compare the data (i.e. the texture name) itself
size_t hash = string_hash(orig_addr);
#define CMPADDR(x, y) (x && !sys_strcasecmp(x, y))
#else // hash and compare the address
size_t hash = (uintptr_t)orig_addr;
hash = (hash >> 5) & 0x3ff;
#define CMPADDR(x, y) x == y
#endif
hash = (hash >> HASH_SHIFT) & HASH_MASK;
struct TextureHashmapNode **node = &gfx_texture_cache.hashmap[hash];
while (*node != NULL && *node - gfx_texture_cache.pool < gfx_texture_cache.pool_pos) {
if ((*node)->texture_addr == orig_addr && (*node)->fmt == fmt && (*node)->siz == siz) {
if (CMPADDR((*node)->texture_addr, orig_addr) && (*node)->fmt == fmt && (*node)->siz == siz) {
gfx_rapi->select_texture(tile, (*node)->texture_id);
*n = *node;
return true;
@ -296,7 +297,7 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
// Pool is full. We just invalidate everything and start over.
gfx_texture_cache.pool_pos = 0;
node = &gfx_texture_cache.hashmap[hash];
//puts("Clearing texture cache");
// puts("Clearing texture cache");
}
*node = &gfx_texture_cache.pool[gfx_texture_cache.pool_pos++];
if ((*node)->texture_addr == NULL) {
@ -313,8 +314,11 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
(*node)->siz = siz;
*n = *node;
return false;
#undef CMPADDR
}
#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;
@ -487,6 +491,90 @@ static void import_texture_ci8(int tile) {
gfx_rapi->upload_texture(rgba32_buf, width, height);
}
#else // EXTERNAL_TEXTURES
// this is taken straight from n64graphics
static bool texname_to_texformat(const char *name, u8 *fmt, u8 *siz) {
static const struct {
const char *name;
const u8 format;
const u8 size;
} fmt_table[] = {
{ "rgba16", G_IM_FMT_RGBA, G_IM_SIZ_16b },
{ "rgba32", G_IM_FMT_RGBA, G_IM_SIZ_32b },
{ "ia1", G_IM_FMT_IA, G_IM_SIZ_8b }, // uhh
{ "ia4", G_IM_FMT_IA, G_IM_SIZ_4b },
{ "ia8", G_IM_FMT_IA, G_IM_SIZ_8b },
{ "ia16", G_IM_FMT_IA, G_IM_SIZ_16b },
{ "i4", G_IM_FMT_I, G_IM_SIZ_4b },
{ "i8", G_IM_FMT_I, G_IM_SIZ_8b },
{ "ci8", G_IM_FMT_I, G_IM_SIZ_8b },
{ "ci16", G_IM_FMT_I, G_IM_SIZ_16b },
};
char *fstr = strrchr(name, '.');
if (!fstr) return false; // no format string?
fstr++;
for (unsigned i = 0; i < sizeof(fmt_table) / sizeof(fmt_table[0]); ++i) {
if (!sys_strcasecmp(fstr, fmt_table[i].name)) {
*fmt = fmt_table[i].format;
*siz = fmt_table[i].size;
return true;
}
}
return false;
}
// calls import_texture() on every texture in the res folder
// we can get the format and size from the texture files
// and then cache them using gfx_texture_cache_lookup
static bool preload_texture(const char *path) {
// strip off the extension
char texname[SYS_MAX_PATH];
strncpy(texname, path, sizeof(texname));
texname[sizeof(texname)-1] = 0;
char *dot = strrchr(texname, '.');
if (dot) *dot = 0;
// get the format and size from filename
u8 fmt, siz;
if (!texname_to_texformat(texname, &fmt, &siz)) {
fprintf(stderr, "unknown texture format: `%s`, skipping\n", texname);
return true; // just skip it, might be a stray skybox or something
}
// strip off the data path
const char *datapath = sys_data_path();
const unsigned int datalen = strlen(datapath);
const char *actualname = (!strncmp(texname, datapath, datalen)) ?
texname + datalen + 1 : texname;
// skip any separators
while (*actualname == '/' || *actualname == '\\') ++actualname;
// this will be stored in the hashtable, so make a copy
actualname = sys_strdup(actualname);
assert(actualname);
struct TextureHashmapNode *n;
if (!gfx_texture_cache_lookup(0, &n, actualname, fmt, siz)) {
// new texture, load it
int w, h;
u8 *data = stbi_load(path, &w, &h, NULL, 4);
if (!data) {
fprintf(stderr, "could not load texture: `%s`\n", path);
return false;
}
// upload it
gfx_rapi->upload_texture(data, w, h);
stbi_image_free(data);
}
return true;
}
#endif // EXTERNAL_TEXTURES
static void import_texture(int tile) {
uint8_t fmt = rdp.texture_tile.fmt;
uint8_t siz = rdp.texture_tile.siz;
@ -495,6 +583,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[SYS_MAX_PATH];
int w, h;
const char *texname = (const char*)rdp.loaded_texture[tile].addr;
snprintf(fpath, sizeof(fpath), "%s/%s.png", sys_data_path(), texname);
u8 *data = stbi_load(fpath, &w, &h, NULL, 4);
if (!data) {
fprintf(stderr, "could not load texture: `%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 +640,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]) {
@ -1638,6 +1743,13 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi) {
for (size_t i = 0; i < sizeof(precomp_shaders) / sizeof(uint32_t); i++) {
gfx_lookup_or_create_shader_program(precomp_shaders[i]);
}
#ifdef EXTERNAL_TEXTURES
// preload all textures if needed
if (configPrecacheRes) {
printf("Precaching textures from `%s`\n", sys_data_path());
sys_dir_walk(sys_data_path(), preload_texture, true);
}
#endif
}
void gfx_start_frame(void) {

View File

@ -100,7 +100,7 @@ void audio_shutdown(void) {
}
void game_deinit(void) {
configfile_save(gCLIOpts.ConfigFile);;
configfile_save(configfile_name());
controller_shutdown();
audio_shutdown();
gfx_shutdown();
@ -153,7 +153,7 @@ void main_func(void) {
main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0]));
gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT);
configfile_load(gCLIOpts.ConfigFile);
configfile_load(configfile_name());
wm_api = &gfx_sdl;
rendering_api = &gfx_opengl_api;

228
src/pc/platform.c Normal file
View File

@ -0,0 +1,228 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <ctype.h>
#ifdef _WIN32
#include <direct.h>
#endif
#include "cliopts.h"
/* these are not available on some platforms, so might as well */
char *sys_strlwr(char *src) {
for (unsigned char *p = (unsigned char *)src; *p; p++)
*p = tolower(*p);
return src;
}
char *sys_strdup(const char *src) {
const unsigned len = strlen(src) + 1;
char *newstr = malloc(len);
if (newstr) memcpy(newstr, src, len);
return newstr;
}
int sys_strcasecmp(const char *s1, const char *s2) {
const unsigned char *p1 = (const unsigned char *) s1;
const unsigned char *p2 = (const unsigned char *) s2;
int result;
if (p1 == p2)
return 0;
while ((result = tolower(*p1) - tolower(*p2++)) == 0)
if (*p1++ == '\0')
break;
return result;
}
/* file system stuff */
bool sys_file_exists(const char *name) {
struct stat st;
return (stat(name, &st) == 0 && S_ISREG(st.st_mode));
}
bool sys_dir_exists(const char *name) {
struct stat st;
return (stat(name, &st) == 0 && S_ISDIR(st.st_mode));
}
bool sys_dir_walk(const char *base, walk_fn_t walk, const bool recur) {
char fullpath[SYS_MAX_PATH];
DIR *dir;
struct dirent *ent;
if (!(dir = opendir(base))) {
fprintf(stderr, "sys_dir_walk(): could not open `%s`\n", base);
return false;
}
bool ret = true;
while ((ent = readdir(dir)) != NULL) {
if (ent->d_name[0] == 0 || ent->d_name[0] == '.') continue; // skip ./.. and hidden files
snprintf(fullpath, sizeof(fullpath), "%s/%s", base, ent->d_name);
if (sys_dir_exists(fullpath)) {
if (recur) {
if (!sys_dir_walk(fullpath, walk, recur)) {
ret = false;
break;
}
}
} else {
if (!walk(fullpath)) {
ret = false;
break;
}
}
}
closedir(dir);
return ret;
}
bool sys_mkdir(const char *name) {
#ifdef _WIN32
return _mkdir(name) == 0;
#else
return mkdir(name, 0777) == 0;
#endif
}
#if USE_SDL
// we can just ask SDL for most of this shit if we have it
#include <SDL2/SDL.h>
const char *sys_data_path(void) {
static char path[SYS_MAX_PATH] = { 0 };
if (!path[0]) {
// prefer the override, if it is set
// "!" expands to executable path
if (gCLIOpts.DataPath[0]) {
if (gCLIOpts.DataPath[0] == '!')
snprintf(path, sizeof(path), "%s%s", sys_exe_path(), gCLIOpts.DataPath + 1);
else
snprintf(path, sizeof(path), "%s", gCLIOpts.DataPath);
if (sys_dir_exists(path)) return path;
printf("Warning: Specified data path ('%s') doesn't exist\n", path);
}
// then the executable directory
snprintf(path, sizeof(path), "%s/" DATADIR, sys_exe_path());
if (sys_dir_exists(path)) return path;
// then the save path
snprintf(path, sizeof(path), "%s/" DATADIR, sys_save_path());
if (sys_dir_exists(path)) return path;
#if defined(__linux__) || defined(__unix__)
// on Linux/BSD try some common paths for read-only data
const char *try[] = {
"/usr/local/share/sm64pc/" DATADIR,
"/usr/share/sm64pc/" DATADIR,
"/opt/sm64pc/" DATADIR,
};
for (unsigned i = 0; i < sizeof(try) / sizeof(try[0]); ++i) {
if (sys_dir_exists(try[i])) {
strcpy(path, try[i]);
return path;
}
}
#endif
// hope for the best
strcpy(path, "./" DATADIR);
}
return path;
}
const char *sys_save_path(void) {
static char path[SYS_MAX_PATH] = { 0 };
if (!path[0]) {
// if the override is set, use that
// "!" expands to executable path
if (gCLIOpts.SavePath[0]) {
if (gCLIOpts.SavePath[0] == '!')
snprintf(path, sizeof(path), "%s%s", sys_exe_path(), gCLIOpts.SavePath + 1);
else
snprintf(path, sizeof(path), "%s", gCLIOpts.SavePath);
if (!sys_dir_exists(path) && !sys_mkdir(path)) {
printf("Warning: Specified save path ('%s') doesn't exist and can't be created\n", path);
path[0] = 0; // doesn't exist and no write access
}
}
// didn't work? get it from SDL
if (!path[0]) {
char *sdlpath = SDL_GetPrefPath("", "sm64pc");
if (sdlpath) {
const unsigned int len = strlen(sdlpath);
strncpy(path, sdlpath, sizeof(path));
path[sizeof(path)-1] = 0;
SDL_free(sdlpath);
if (path[len-1] == '/' || path[len-1] == '\\')
path[len-1] = 0; // strip the trailing separator
if (!sys_dir_exists(path) && !sys_mkdir(path))
path[0] = 0;
}
}
// if all else fails, just store near the EXE
if (!path[0])
strcpy(path, sys_exe_path());
printf("Save path set to '%s'\n", path);
}
return path;
}
const char *sys_exe_path(void) {
static char path[SYS_MAX_PATH] = { 0 };
if (!path[0]) {
char *sdlpath = SDL_GetBasePath();
if (sdlpath) {
// use the SDL path if it exists
const unsigned int len = strlen(sdlpath);
strncpy(path, sdlpath, sizeof(path));
path[sizeof(path)-1] = 0;
SDL_free(sdlpath);
if (path[len-1] == '/' || path[len-1] == '\\')
path[len-1] = 0; // strip the trailing separator
} else {
// hope for the best
strcpy(path, ".");
}
printf("Executable path set to '%s'\n", path);
}
return path;
}
#else
#warning "You might want to implement these functions for your platform"
const char *sys_data_path(void) {
return ".";
}
const char *sys_save_path(void) {
return ".";
}
const char *sys_exe_path(void) {
return ".";
}
#endif // platform switch

34
src/pc/platform.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _SM64_PLATFORM_H_
#define _SM64_PLATFORM_H_
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/* Platform-specific functions and whatnot */
#define DATADIR "res"
#define SYS_MAX_PATH 1024 // FIXME: define this on different platforms
// crossplatform impls of misc stuff
char *sys_strdup(const char *src);
char *sys_strlwr(char *src);
int sys_strcasecmp(const char *s1, const char *s2);
// filesystem stuff
bool sys_mkdir(const char *name); // creates with 0777 by default
bool sys_file_exists(const char *name);
bool sys_dir_exists(const char *name);
// receives the full path
// should return `true` if traversal should continue
typedef bool (*walk_fn_t)(const char *);
// returns `true` if the directory was successfully opened and walk() didn't ever return false
bool sys_dir_walk(const char *base, walk_fn_t walk, const bool recur);
// path stuff
const char *sys_data_path(void);
const char *sys_save_path(void);
const char *sys_exe_path(void);
#endif // _SM64_PLATFORM_H_

View File

@ -2,6 +2,7 @@
#include <string.h>
#include "lib/src/libultra_internal.h"
#include "macros.h"
#include "platform.h"
#ifdef TARGET_WEB
#include <emscripten.h>
@ -119,7 +120,9 @@ s32 osEepromLongRead(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes)
ret = 0;
}
#else
FILE *fp = fopen("sm64_save_file.bin", "rb");
char save_path[SYS_MAX_PATH] = { 0 };
snprintf(save_path, sizeof(save_path), "%s/sm64_save_file.bin", sys_save_path());
FILE *fp = fopen(save_path, "rb");
if (fp == NULL) {
return -1;
}
@ -149,7 +152,9 @@ s32 osEepromLongWrite(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes
}, content);
s32 ret = 0;
#else
FILE* fp = fopen("sm64_save_file.bin", "wb");
char save_path[SYS_MAX_PATH] = { 0 };
snprintf(save_path, sizeof(save_path), "%s/sm64_save_file.bin", sys_save_path());
FILE *fp = fopen(save_path, "wb");
if (fp == NULL) {
return -1;
}

View File

@ -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 -Iinclude -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

42
tools/cleancrcmap.py Normal file
View File

@ -0,0 +1,42 @@
#!/usr/bin/env python3
import sys
import os
import glob
if len(sys.argv) < 4:
print("usage: cleancrcmap <in_map> <out_map> <searchdir>")
sys.exit(1)
# load and check the old map
searchpath = sys.argv[3]
inmap = list()
with open(sys.argv[1], 'r') as f:
for line in f:
line = line.strip()
if line == '' or line[0] == '#':
continue
tok = line.split(',')
crcstr = tok[0].strip()
if crcstr.startswith('0x'):
crc = int(crcstr[2:], 16)
else:
crc = int(crcstr)
tok[1] = tok[1].strip()
[fname, fext] = os.path.splitext(tok[1])
[fname, ffmt] = os.path.splitext(fname)
fname = fname + ffmt[:-1] + '*'
matches = glob.glob(os.path.join(searchpath, fname))
if len(matches) == 0:
print("warning: texture '{0}' does not match anything in '{1}'".format(fname, searchpath))
else:
for s in matches:
tup = (crc, os.path.relpath(s, searchpath))
if not (tup in inmap):
inmap.append(tup)
# save cleaned up version to the new one
with open(sys.argv[2], 'w') as f:
for (crc, fpath) in inmap:
f.write("0x{0:08x}, {1}\n".format(crc, fpath))

1237
tools/default_crcmap.txt Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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];
@ -216,7 +217,6 @@ static void assign_tile_positions() {
void write_tiles() {
const ImageProps props = IMAGE_PROPERTIES[type][true];
char buffer[PATH_MAX];
char skyboxName[PATH_MAX];
if (realpath(writeDir, buffer) == NULL) {
fprintf(stderr, "err: Could not find find img dir %s", writeDir);
@ -292,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);
}
}
}
@ -335,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);
}
@ -474,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
@ -530,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;

71
tools/texrename.py Normal file
View File

@ -0,0 +1,71 @@
#!/usr/bin/env python3
import sys
import os
import shutil
if len(sys.argv) < 3:
print("usage: texrename <in_dir> <out_dir> [<crcmap_file>]")
sys.exit(1)
inpath = sys.argv[1]
outpath = sys.argv[2]
mapfname = "crcmap.txt"
if len(sys.argv) > 3:
mapfname = sys.argv[3]
# catalog the original texture pack
texmap = dict()
imgexts = frozenset(['.png', '.bmp', '.jpg', '.tga', '.gif'])
try:
for root, dirs, files in os.walk(inpath):
for f in files:
ffull = os.path.join(root, f)
[fpath, fname] = os.path.split(f)
ext = os.path.splitext(fname)[1].lower()
if fname[0] == '.' or not (ext in imgexts):
continue
crc = 0
try:
if '#' in fname: # rice pack format: "GAME NAME#hash#whatever"
crc = int(fname.split('#')[1], 16)
else: # just the crc probably
crc = int(os.path.splitext(fname)[0], 16)
except ValueError:
print('unknown filename format: {0}'.format(ffull))
continue
texmap[crc] = ffull
except OSError as e:
print('error opening {0}: {1}'.format(inpath, e))
sys.exit(2)
# load the CRC map
crcmap = list()
try:
with open(mapfname, 'r') as f:
for line in f:
line = line.strip()
if line == '' or line[0] == '#':
continue
tok = line.split(',')
crcstr = tok[0].strip()
if crcstr.startswith('0x'):
crc = int(crcstr[2:], 16)
else:
crc = int(crcstr)
crcmap.append((crc, os.path.join(outpath, tok[1].strip())))
except OSError as e:
print('could not open {0}: {1}'.format(mapfname, e))
except ValueError as e:
print('invalid integer in {0}: {1}'.format(mapfname, e))
sys.exit(3)
# copy the files to the correct locations
for (crc, path) in crcmap:
if not (crc in texmap):
print('unmatched CRC: {0} ({1})'.format(crc, path))
else:
[fpath, fname] = os.path.split(path)
if not os.path.exists(fpath):
os.makedirs(fpath)
shutil.copy2(texmap[crc], path)

6
tools/zeroterm.py Normal file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env python3
import sys
if len(sys.argv) < 2:
print("usage: zeroterm <string>")
else:
sys.stdout.buffer.write(bytes(sys.argv[1], 'ascii') + b'\x00')