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

This commit is contained in:
Zerocker 2020-05-30 21:00:11 +09:00
commit 82163b706a
36 changed files with 2210 additions and 242 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
@ -123,6 +125,14 @@ endif
endif
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)
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)\""
endif
# Microcode
ifeq ($(GRUCODE),f3dex) # Fast3DEX
@ -481,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
@ -490,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
@ -544,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)
@ -589,6 +607,7 @@ EMU_FLAGS = --noosd
LOADER = loader64
LOADER_FLAGS = -vwf
SHA1SUM = sha1sum
ZEROTERM = $(PYTHON) $(TOOLS_DIR)/zeroterm.py
###################### Dependency Check #####################
@ -598,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)
@ -630,6 +662,9 @@ $(BUILD_DIR)/include/text_strings.h: include/text_strings.h.in
$(BUILD_DIR)/include/text_menu_strings.h: include/text_menu_strings.h.in
$(TEXTCONV) charmap_menu.txt $< $@
$(BUILD_DIR)/include/text_options_strings.h: include/text_options_strings.h.in
$(TEXTCONV) charmap.txt $< $@
ifeq ($(VERSION),eu)
TEXT_DIRS := text/de text/us text/fr
@ -669,6 +704,7 @@ ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS) $(GOD
DUMMY != mkdir -p $(ALL_DIRS)
$(BUILD_DIR)/include/text_strings.h: $(BUILD_DIR)/include/text_menu_strings.h
$(BUILD_DIR)/include/text_strings.h: $(BUILD_DIR)/include/text_options_strings.h
ifeq ($(VERSION),eu)
$(BUILD_DIR)/src/menu/file_select.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o
@ -688,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
@ -702,6 +744,7 @@ $(BUILD_DIR)/%.ci8: %.ci8.png
# Color Index CI4
$(BUILD_DIR)/%.ci4: %.ci4.png
$(N64GRAPHICS_CI) -i $@ -g $< -f ci4
endif
################################################################
@ -845,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

@ -51,4 +51,19 @@
#define PHYSICAL_TO_VIRTUAL(addr) ((uintptr_t)(addr))
#define VIRTUAL_TO_PHYSICAL2(addr) ((void *)(addr))
// Byteswap macros
#define BSWAP16(x) (((x) & 0xFF) << 8 | (((x) >> 8) & 0xFF))
#define BSWAP32(x) \
( (((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \
(((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000) )
// Convenience macros for endian conversions
#if IS_BIG_ENDIAN
#define BE_TO_HOST16(x) (x)
#define BE_TO_HOST32(x) (x)
#else
#define BE_TO_HOST16(x) BSWAP16(x)
#define BE_TO_HOST32(x) BSWAP32(x)
#endif
#endif

View file

@ -0,0 +1,140 @@
#ifndef TEXT_OPTIONS_STRINGS_H
#define TEXT_OPTIONS_STRINGS_H
/* Extended options menu text */
// Menu title strings
#define TEXT_OPT_OPTIONS _("OPTIONS")
#define TEXT_OPT_CAMERA _("CAMERA")
#define TEXT_OPT_CONTROLS _("CONTROLS")
#define TEXT_OPT_VIDEO _("DISPLAY")
#define TEXT_OPT_AUDIO _("SOUND")
#define TEXT_OPT_CHEATS _("CHEATS")
// Markers
#define TEXT_OPT_HIGHLIGHT _("O")
#define TEXT_OPT_UNBOUND _("NONE")
// Language specific strings
#if defined(VERSION_JP) || defined(VERSION_SH)
// TODO: Actually translate this to JP
// No . in JP
#define TEXT_OPT_PRESSKEY _("・・・")
// Option strings
#define TEXT_OPT_BUTTON1 _(" OPTIONS")
#define TEXT_OPT_BUTTON2 _(" RETURN")
#define TEXT_OPT_ENABLED _("ENABLED")
#define TEXT_OPT_DISABLED _("DISABLED")
#define TEXT_OPT_CAMX _("CAMERA X SENSITIVITY")
#define TEXT_OPT_CAMY _("CAMERA Y SENSITIVITY")
#define TEXT_OPT_INVERTX _("INVERT X AXIS")
#define TEXT_OPT_INVERTY _("INVERT Y AXIS")
#define TEXT_OPT_CAMC _("CAMERA CENTRE AGGRESSION")
#define TEXT_OPT_CAMP _("CAMERA PAN LEVEL")
#define TEXT_OPT_CAMD _("CAMERA DECELERATION")
#define TEXT_OPT_ANALOGUE _("ANALOGUE CAMERA")
#define TEXT_OPT_MOUSE _("MOUSE LOOK")
#define TEXT_OPT_TEXFILTER _("TEXTURE FILTERING")
#define TEXT_OPT_FSCREEN _("FULLSCREEN")
#define TEXT_OPT_NEAREST _("NEAREST")
#define TEXT_OPT_LINEAR _("LINEAR")
#define TEXT_OPT_MVOLUME _("MASTER VOLUME")
#define TEXT_OPT_VSYNC _("VERTICAL SYNC")
#define TEXT_OPT_DOUBLE _("DOUBLE")
#define TEXT_RESET_WINDOW _("RESET WINDOW")
#define TEXT_OPT_HUD _("HUD")
#define TEXT_BIND_A _("A BUTTON")
#define TEXT_BIND_B _("B BUTTON")
#define TEXT_BIND_START _("START BUTTON")
#define TEXT_BIND_L _("L TRIGGER")
#define TEXT_BIND_R _("R TRIGGER")
#define TEXT_BIND_Z _("Z TRIGGER")
#define TEXT_BIND_C_UP _("C-UP")
#define TEXT_BIND_C_DOWN _("C-DOWN")
#define TEXT_BIND_C_LEFT _("C-LEFT")
#define TEXT_BIND_C_RIGHT _("C-RIGHT")
#define TEXT_BIND_UP _("STICK UP")
#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)")
#define TEXT_OPT_CHEAT3 _("INVINCIBLE MARIO")
#define TEXT_OPT_CHEAT4 _("INFINITE LIVES")
#define TEXT_OPT_CHEAT5 _("SUPER SPEED")
#define TEXT_OPT_CHEAT6 _("SUPER RESPONSIVE CONTROLS")
#define TEXT_OPT_CHEAT7 _("EXIT COURSE AT ANY TIME")
#define TEXT_OPT_CHEAT8 _("HUGE MARIO")
#define TEXT_OPT_CHEAT9 _("TINY MARIO")
#else // VERSION
// Markers
#define TEXT_OPT_PRESSKEY _("...")
// Option strings
#define TEXT_OPT_BUTTON1 _("[R] Options")
#define TEXT_OPT_BUTTON2 _("[R] Return")
#define TEXT_OPT_ENABLED _("Enabled")
#define TEXT_OPT_DISABLED _("Disabled")
#define TEXT_OPT_CAMX _("Camera X Sensitivity")
#define TEXT_OPT_CAMY _("Camera Y Sensitivity")
#define TEXT_OPT_INVERTX _("Invert X Axis")
#define TEXT_OPT_INVERTY _("Invert Y Axis")
#define TEXT_OPT_CAMC _("Camera Centre Aggression")
#define TEXT_OPT_CAMP _("Camera Pan Level")
#define TEXT_OPT_CAMD _("Camera Deceleration")
#define TEXT_OPT_ANALOGUE _("Analogue Camera")
#define TEXT_OPT_MOUSE _("Mouse Look")
#define TEXT_OPT_TEXFILTER _("Texture Filtering")
#define TEXT_OPT_FSCREEN _("Fullscreen")
#define TEXT_OPT_NEAREST _("Nearest")
#define TEXT_OPT_LINEAR _("Linear")
#define TEXT_OPT_MVOLUME _("Master Volume")
#define TEXT_OPT_VSYNC _("Vertical Sync")
#define TEXT_OPT_DOUBLE _("Double")
#define TEXT_RESET_WINDOW _("Reset Window")
#define TEXT_OPT_HUD _("HUD")
#define TEXT_BIND_A _("A Button")
#define TEXT_BIND_B _("B Button")
#define TEXT_BIND_START _("Start Button")
#define TEXT_BIND_L _("L Trigger")
#define TEXT_BIND_R _("R Trigger")
#define TEXT_BIND_Z _("Z Trigger")
#define TEXT_BIND_C_UP _("C-Up")
#define TEXT_BIND_C_DOWN _("C-Down")
#define TEXT_BIND_C_LEFT _("C-Left")
#define TEXT_BIND_C_RIGHT _("C-Right")
#define TEXT_BIND_UP _("Stick Up")
#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)")
#define TEXT_OPT_CHEAT3 _("Invincible Mario")
#define TEXT_OPT_CHEAT4 _("Infinite lives")
#define TEXT_OPT_CHEAT5 _("Super speed")
#define TEXT_OPT_CHEAT6 _("Super responsive controls")
#define TEXT_OPT_CHEAT7 _("Exit course at any time")
#define TEXT_OPT_CHEAT8 _("Huge Mario")
#define TEXT_OPT_CHEAT9 _("Tiny Mario")
#endif // VERSION
#endif // TEXT_OPTIONS_STRINGS_H

View file

@ -1,64 +1,12 @@
#ifndef TEXT_STRINGS_H
#ifndef TEXT_STRINGS_H
#define TEXT_STRINGS_H
#include "text_menu_strings.h"
#define TEXT_OPT_CAMX _("Camera X Sensitivity")
#define TEXT_OPT_CAMY _("Camera Y Sensitivity")
#define TEXT_OPT_INVERTX _("Invert X Axis")
#define TEXT_OPT_INVERTY _("Invert Y Axis")
#define TEXT_OPT_CAMC _("Camera Centre Aggression")
#define TEXT_OPT_CAMP _("Camera Pan Level")
#define TEXT_OPT_CAMD _("Camera Deceleration")
#define TEXT_OPT_ENABLED _("Enabled")
#define TEXT_OPT_DISABLED _("Disabled")
#define TEXT_OPT_BUTTON1 _("[R]: Options")
#define TEXT_OPT_BUTTON2 _("[R]: Return")
#define TEXT_OPT_OPTIONS _("OPTIONS")
#define TEXT_OPT_CAMERA _("CAMERA")
#define TEXT_OPT_CONTROLS _("CONTROLS")
#define TEXT_OPT_VIDEO _("DISPLAY")
#define TEXT_OPT_AUDIO _("SOUND")
#define TEXT_OPT_HIGHLIGHT _("O")
#define TEXT_OPT_ANALOGUE _("Analogue Camera")
#define TEXT_OPT_MOUSE _("Mouse Look")
#define TEXT_OPT_TEXFILTER _("Texture Filtering")
#define TEXT_OPT_FSCREEN _("Fullscreen")
#define TEXT_OPT_NEAREST _("Nearest")
#define TEXT_OPT_LINEAR _("Linear")
#define TEXT_OPT_MVOLUME _("Master Volume")
#define TEXT_OPT_VSYNC _("Vertical Sync")
#define TEXT_OPT_DOUBLE _("Double")
#define TEXT_RESET_WINDOW _("Reset Window")
#define TEXT_OPT_HUD _("HUD")
#ifdef EXT_OPTIONS_MENU
#include "text_options_strings.h"
#endif
#define TEXT_OPT_UNBOUND _("NONE")
#define TEXT_OPT_PRESSKEY _("...")
#define TEXT_BIND_A _("A Button")
#define TEXT_BIND_B _("B Button")
#define TEXT_BIND_START _("Start Button")
#define TEXT_BIND_L _("L Trigger")
#define TEXT_BIND_R _("R Trigger")
#define TEXT_BIND_Z _("Z Trigger")
#define TEXT_BIND_C_UP _("C-Up")
#define TEXT_BIND_C_DOWN _("C-Down")
#define TEXT_BIND_C_LEFT _("C-Left")
#define TEXT_BIND_C_RIGHT _("C-Right")
#define TEXT_BIND_UP _("Stick Up")
#define TEXT_BIND_DOWN _("Stick Down")
#define TEXT_BIND_LEFT _("Stick Left")
#define TEXT_BIND_RIGHT _("Stick Right")
#define TEXT_OPT_CHEATS _("CHEATS")
#define TEXT_OPT_CHEAT1 _("Enable cheats")
#define TEXT_OPT_CHEAT2 _("Moonjump (Press L)")
#define TEXT_OPT_CHEAT3 _("Invincible Mario")
#define TEXT_OPT_CHEAT4 _("Infinite lives")
#define TEXT_OPT_CHEAT5 _("Super speed")
#define TEXT_OPT_CHEAT6 _("Super responsive controls")
#define TEXT_OPT_CHEAT7 _("Exit course at any time")
#define TEXT_OPT_CHEAT8 _("Huge Mario")
#define TEXT_OPT_CHEAT9 _("Tiny Mario")
/**
* Global Symbols
*/
@ -146,7 +94,7 @@
#define TEXT_COURSE _("コース")
#define TEXT_MYSCORE _("マイスコア")
#define TEXT_CONTINUE _("つづけて マリオする?")
#define TEXT_EXIT_GAME _("ゲームをしゅうりょうする")
#define TEXT_EXIT_GAME _("ゲームをしゅうりょうする")
#define TEXT_EXIT_COURSE _("コースからでる?")
#define TEXT_CAMERA_ANGLE_R _("Rボタンのカメラきりかえ")

View file

@ -175,9 +175,9 @@ s8 gVibratoCurve[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104,
#endif
struct AdsrEnvelope gDefaultEnvelope[] = {
{ BSWAP16(4), BSWAP16(32000) }, // go from 0 to 32000 over the course of 16ms
{ BSWAP16(1000), BSWAP16(32000) }, // stay there for 4.16 seconds
{ BSWAP16(ADSR_HANG), 0 } // then continue staying there
{ BE_TO_HOST16(4), BE_TO_HOST16(32000) }, // go from 0 to 32000 over the course of 16ms
{ BE_TO_HOST16(1000), BE_TO_HOST16(32000) }, // stay there for 4.16 seconds
{ BE_TO_HOST16(ADSR_HANG), 0 } // then continue staying there
};
#ifdef VERSION_EU

View file

@ -391,7 +391,7 @@ s32 adsr_update(struct AdsrState *adsr) {
// fallthrough
case ADSR_STATE_LOOP:
adsr->delay = BSWAP16(adsr->envelope[adsr->envIndex].delay);
adsr->delay = BE_TO_HOST16(adsr->envelope[adsr->envIndex].delay);
switch (adsr->delay) {
case ADSR_DISABLE:
adsr->state = ADSR_STATE_DISABLED;
@ -400,7 +400,7 @@ s32 adsr_update(struct AdsrState *adsr) {
adsr->state = ADSR_STATE_HANG;
break;
case ADSR_GOTO:
adsr->envIndex = BSWAP16(adsr->envelope[adsr->envIndex].arg);
adsr->envIndex = BE_TO_HOST16(adsr->envelope[adsr->envIndex].arg);
break;
case ADSR_RESTART:
adsr->state = ADSR_STATE_INITIAL;
@ -411,11 +411,11 @@ s32 adsr_update(struct AdsrState *adsr) {
if (adsr->delay >= 4) {
adsr->delay = adsr->delay * gAudioBufferParameters.updatesPerFrame / 4;
}
adsr->target = (f32) BSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0;
adsr->target = (f32) BE_TO_HOST16(adsr->envelope[adsr->envIndex].arg) / 32767.0;
adsr->target = adsr->target * adsr->target;
adsr->velocity = (adsr->target - adsr->current) / adsr->delay;
#else
adsr->target = BSWAP16(adsr->envelope[adsr->envIndex].arg);
adsr->target = BE_TO_HOST16(adsr->envelope[adsr->envIndex].arg);
adsr->velocity = ((adsr->target - adsr->current) << 0x10) / adsr->delay;
#endif
adsr->state = ADSR_STATE_FADE;

View file

@ -3,6 +3,7 @@
#include "internal.h"
#include "platform_info.h"
#include "macros.h"
#define ADSR_STATE_DISABLED 0
#define ADSR_STATE_INITIAL 1
@ -24,12 +25,9 @@
#define ADSR_RESTART -3
// Envelopes are always stored as big endian, to match sequence files which are
// byte blobs and can embed envelopes. Hence this byteswapping macro.
#if IS_BIG_ENDIAN
#define BSWAP16(x) (x)
#else
#define BSWAP16(x) (((x) & 0xff) << 8 | (((x) >> 8) & 0xff))
#endif
// byte blobs and can embed envelopes.
// BSWAP16() definition has been moved to macros.h. Use BE_TO_HOST16() for the
// same effect in the future.
void sequence_player_process_sound(struct SequencePlayer *seqPlayer);
void note_vibrato_update(struct Note *note);

View file

@ -74,9 +74,9 @@ struct newcam_hardpos newcam_fixedcam[] =
#endif // noaccel
s16 newcam_yaw; //Z axis rotation
f32 newcam_yaw_acc;
s16 newcam_yaw_acc;
s16 newcam_tilt = 1500; //Y axis rotation
f32 newcam_tilt_acc;
s16 newcam_tilt_acc;
u16 newcam_distance = 750; //The distance the camera stays from the player
u16 newcam_distance_target = 750; //The distance the player camera tries to reach.
f32 newcam_pos_target[3]; //The position the camera is basing calculations off. *usually* Mario.
@ -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;
@ -187,7 +187,7 @@ void newcam_diagnostics(void)
print_text_fmt_int(32,32,"DISTANCE %d",newcam_distance);
}
static s16 newcam_adjust_value(s16 var, s16 val, s8 max)
static s16 newcam_adjust_value(s16 var, s16 val, s16 max)
{
if (val > 0)
{

View file

@ -19,6 +19,7 @@
#include "print.h"
#include "engine/math_util.h"
#include "course_table.h"
#include "macros.h"
#include "pc/cheats.h"
#ifdef BETTERCAMERA
#include "bettercamera.h"
@ -127,6 +128,16 @@ u8 gMenuHoldKeyIndex = 0;
u8 gMenuHoldKeyTimer = 0;
s32 gDialogResponse = 0;
#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
#define CHCACHE_BUFLEN (8 * 16) // JP only converts 8x16 or 16x8 characters
#endif
// stores char data unpacked from ia1 to ia8 or ia4
// so that it won't be reconverted every time a character is rendered
static struct CachedChar { u8 used; u8 data[CHCACHE_BUFLEN]; } charCache[256];
#endif // VERSION
void create_dl_identity_matrix(void) {
Mtx *matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
@ -206,23 +217,19 @@ void create_dl_ortho_matrix(void) {
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_PROJECTION | G_MTX_MUL | G_MTX_NOPUSH)
}
static u8 *alloc_ia8_text_from_i1(u16 *in, s16 width, s16 height) {
#if defined(VERSION_JP) || defined(VERSION_SH)
static inline void alloc_ia8_text_from_i1(u8 *out, u16 *in, s16 width, s16 height) {
s32 inPos;
u16 bitMask;
u8 *out;
u16 inWord;
s16 outPos = 0;
out = alloc_display_list((u32) width * (u32) height);
if (out == NULL) {
return NULL;
}
for (inPos = 0; inPos < (width * height) / 16; inPos++) {
inWord = BE_TO_HOST16(in[inPos]);
bitMask = 0x8000;
while (bitMask != 0) {
if (in[inPos] & bitMask) {
if (inWord & bitMask) {
out[outPos] = 0xFF;
} else {
out[outPos] = 0x00;
@ -232,10 +239,22 @@ static u8 *alloc_ia8_text_from_i1(u16 *in, s16 width, s16 height) {
outPos++;
}
}
return out;
}
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 (!tex) return NULL;
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
void render_generic_char(u8 c) {
void **fontLUT;
void *packedTexture;
@ -247,7 +266,7 @@ void render_generic_char(u8 c) {
packedTexture = segmented_to_virtual(fontLUT[c]);
#if defined(VERSION_JP) || defined(VERSION_SH)
unpackedTexture = alloc_ia8_text_from_i1(packedTexture, 8, 16);
unpackedTexture = convert_ia8_char(c, packedTexture, 8, 16);
gDPPipeSync(gDisplayListHead++);
gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_IA, G_IM_SIZ_8b, 1, VIRTUAL_TO_PHYSICAL(unpackedTexture));
@ -265,20 +284,12 @@ void render_generic_char(u8 c) {
}
#ifdef VERSION_EU
u8 *alloc_ia4_tex_from_i1(u8 *in, s16 width, s16 height) {
static void alloc_ia4_tex_from_i1(u8 *out, u8 *in, s16 width, s16 height) {
u32 size = (u32) width * (u32) height;
u8 *out;
s32 inPos;
s16 outPos;
s16 outPos = 0;
u8 bitMask;
outPos = 0;
out = (u8 *) alloc_display_list(size);
if (out == NULL) {
return NULL;
}
for (inPos = 0; inPos < (width * height) / 4; inPos++) {
bitMask = 0x80;
while (bitMask != 0) {
@ -289,8 +300,19 @@ u8 *alloc_ia4_tex_from_i1(u8 *in, s16 width, s16 height) {
outPos++;
}
}
}
return out;
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 (!tex) return NULL;
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) {
@ -300,7 +322,7 @@ void render_generic_char_at_pos(s16 xPos, s16 yPos, u8 c) {
fontLUT = segmented_to_virtual(main_font_lut);
packedTexture = segmented_to_virtual(fontLUT[c]);
unpackedTexture = alloc_ia4_tex_from_i1(packedTexture, 8, 8);
unpackedTexture = convert_ia4_char(c, packedTexture, 8, 8);
gDPPipeSync(gDisplayListHead++);
gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, VIRTUAL_TO_PHYSICAL(unpackedTexture));
@ -1025,7 +1047,7 @@ void render_generic_dialog_char_at_pos(struct DialogEntry *dialog, s16 x, s16 y,
fontLUT = segmented_to_virtual(main_font_lut);
packedTexture = segmented_to_virtual(fontLUT[c]);
unpackedTexture = alloc_ia4_tex_from_i1(packedTexture, 8, 8);
unpackedTexture = convert_ia4_char(c, packedTexture, 8, 8);
gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, VIRTUAL_TO_PHYSICAL(unpackedTexture));
gSPDisplayList(gDisplayListHead++, dl_ia_text_tex_settings);

View file

@ -115,6 +115,7 @@ static const u8 bindStr[][32] = {
{ TEXT_BIND_DOWN },
{ TEXT_BIND_LEFT },
{ TEXT_BIND_RIGHT },
{ TEXT_OPT_DEADZONE },
};
static const u8 *filterChoices[] = {
@ -233,6 +234,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[] = {
@ -462,7 +466,7 @@ void optmenu_draw(void) {
//This has been separated for interesting reasons. Don't question it.
void optmenu_draw_prompt(void) {
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
optmenu_draw_text(278, 212, menuStr[1 + optmenu_open], 0);
optmenu_draw_text(264, 212, menuStr[1 + optmenu_open], 0);
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
}
@ -496,7 +500,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

@ -10,16 +10,12 @@
#include "level_table.h"
#include "course_table.h"
#include "thread6.h"
#include "macros.h"
#include "pc/ini.h"
#define MENU_DATA_MAGIC 0x4849
#define SAVE_FILE_MAGIC 0x4441
#define BSWAP16(x) \
( (((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00) )
#define BSWAP32(x) \
( (((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \
(((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000) )
STATIC_ASSERT(sizeof(struct SaveBuffer) == EEPROM_SIZE, "eeprom buffer size must match");
extern struct SaveBuffer gSaveBuffer;

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;
@ -210,7 +231,7 @@ void configfile_load(const char *filename) {
// Go through each line in the file
while ((line = read_file_line(file)) != NULL) {
char *p = line;
char *tokens[2];
char *tokens[1 + MAX_BINDS];
int numTokens;
while (isspace(*p))
@ -219,7 +240,7 @@ void configfile_load(const char *filename) {
if (!*p || *p == '#') // comment or empty line
continue;
numTokens = tokenize_string(p, 2, tokens);
numTokens = tokenize_string(p, sizeof(tokens) / sizeof(tokens[0]), tokens);
if (numTokens != 0) {
if (numTokens >= 2) {
const struct ConfigOption *option = NULL;
@ -253,7 +274,9 @@ void configfile_load(const char *filename) {
default:
assert(0); // bad type
}
printf("option: '%s', value: '%s'\n", tokens[0], tokens[1]);
printf("option: '%s', value:", tokens[0]);
for (int i = 1; i < numTokens; ++i) printf(" '%s'", tokens[i]);
printf("\n");
}
} else
puts("error: expected value");

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

@ -1,6 +1,8 @@
#include "lib/src/libultra_internal.h"
#include "lib/src/osContInternal.h"
#include "../configfile.h"
#include "controller_recorded_tas.h"
#include "controller_keyboard.h"
@ -40,7 +42,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

@ -1,10 +1,16 @@
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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 +24,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 +47,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 +84,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 +173,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 +275,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 +298,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 +315,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,14 +492,131 @@ 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;
}
static inline void load_texture(const char *name) {
static char fpath[SYS_MAX_PATH];
int w, h;
const char *texname = name;
if (!texname[0]) {
fprintf(stderr, "empty texture name at %p\n", texname);
return;
}
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);
return;
}
gfx_rapi->upload_texture(data, w, h);
stbi_image_free(data); // don't need this anymore
}
#endif // EXTERNAL_TEXTURES
static void import_texture(int tile) {
uint8_t fmt = rdp.texture_tile.fmt;
uint8_t siz = rdp.texture_tile.siz;
if (!rdp.loaded_texture[tile].addr) {
fprintf(stderr, "NULL texture: tile %d, format %d/%d, size %d\n",
tile, (int)fmt, (int)siz, (int)rdp.loaded_texture[tile].size_bytes);
return;
}
if (gfx_texture_cache_lookup(tile, &rendering_state.textures[tile], rdp.loaded_texture[tile].addr, fmt, siz)) {
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
load_texture((const char*)rdp.loaded_texture[tile].addr);
#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 +658,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 +1761,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

@ -156,13 +156,17 @@ static void gfx_sdl_init(void) {
else if (gCLIOpts.FullScreen == 2)
configWindow.fullscreen = false;
const char* window_title =
char window_title[96] =
#ifndef USE_GLES
"Super Mario 64 PC port (OpenGL)";
#else
"Super Mario 64 PC port (OpenGL_ES2)";
#endif
#ifdef NIGHTLY
strcat(window_title, " nightly " GIT_HASH);
#endif
wnd = SDL_CreateWindow(
window_title,
configWindow.x, configWindow.y, configWindow.w, configWindow.h,

View file

@ -92,7 +92,7 @@ void audio_shutdown(void) {
}
void game_deinit(void) {
configfile_save(gCLIOpts.ConfigFile);;
configfile_save(configfile_name());
controller_shutdown();
audio_shutdown();
gfx_shutdown();
@ -145,7 +145,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')