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

This commit is contained in:
Zerocker 2020-06-04 19:13:41 +09:00
commit 77217baf13
16 changed files with 292 additions and 83 deletions

View File

@ -42,8 +42,8 @@ TEXTURE_FIX ?= 0
EXT_OPTIONS_MENU ?= 1 EXT_OPTIONS_MENU ?= 1
# Disable text-based save-files by default # Disable text-based save-files by default
TEXTSAVES ?= 0 TEXTSAVES ?= 0
# Load textures from external PNG files # Load resources from external files
EXTERNAL_TEXTURES ?= 0 EXTERNAL_DATA ?= 0
# Various workarounds for weird toolchains # Various workarounds for weird toolchains
@ -60,8 +60,20 @@ NON_MATCHING := 1
GRUCODE := f3dex2e GRUCODE := f3dex2e
WINDOWS_BUILD ?= 0 WINDOWS_BUILD ?= 0
ifeq ($(TARGET_WEB),0) # Attempt to detect OS
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
HOST_OS ?= Windows
else
HOST_OS ?= $(shell uname -s 2>/dev/null || echo Unknown)
# some weird MINGW/Cygwin env that doesn't define $OS
ifneq (,$(findstring MINGW,HOST_OS))
HOST_OS := Windows
endif
endif
ifeq ($(TARGET_WEB),0)
ifeq ($(HOST_OS),Windows)
WINDOWS_BUILD := 1 WINDOWS_BUILD := 1
endif endif
endif endif
@ -274,7 +286,7 @@ else
ifeq ($(VERSION),sh) ifeq ($(VERSION),sh)
OPT_FLAGS := -O2 OPT_FLAGS := -O2
else else
OPT_FLAGS := -g OPT_FLAGS := -O2
endif endif
endif endif
@ -555,9 +567,9 @@ ifeq ($(LEGACY_GL),1)
endif endif
# Load external textures # Load external textures
ifeq ($(EXTERNAL_TEXTURES),1) ifeq ($(EXTERNAL_DATA),1)
CC_CHECK += -DEXTERNAL_TEXTURES CC_CHECK += -DEXTERNAL_DATA
CFLAGS += -DEXTERNAL_TEXTURES CFLAGS += -DEXTERNAL_DATA
# tell skyconv to write names instead of actual texture data and save the split tiles so we can use them later # 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" SKYCONV_ARGS := --store-names --write-tiles "$(BUILD_DIR)/textures/skybox_tiles"
endif endif
@ -617,17 +629,30 @@ ZEROTERM = $(PYTHON) $(TOOLS_DIR)/zeroterm.py
all: $(EXE) all: $(EXE)
ifeq ($(EXTERNAL_TEXTURES),1) ifeq ($(EXTERNAL_DATA),1)
# thank you apple very cool
ifeq ($(HOST_OS),Darwin)
CP := gcp
else
CP := cp
endif
# depend on resources as well # depend on resources as well
all: res all: res
# prepares the resource folder for external data # prepares the resource folder for external data
res: $(EXE) res: $(EXE)
@mkdir -p $(BUILD_DIR)/res @mkdir -p $(BUILD_DIR)/res/sound
@cp -r -f textures/ $(BUILD_DIR)/res/ @$(CP) -r -f textures/ $(BUILD_DIR)/res/
@cp -r -f $(BUILD_DIR)/textures/skybox_tiles/ $(BUILD_DIR)/res/textures/ @$(CP) -r -f $(BUILD_DIR)/textures/skybox_tiles/ $(BUILD_DIR)/res/textures/
@find actors -name \*.png -exec cp --parents {} $(BUILD_DIR)/res/ \; @$(CP) -f $(SOUND_BIN_DIR)/sound_data.ctl $(BUILD_DIR)/res/sound/
@find levels -name \*.png -exec cp --parents {} $(BUILD_DIR)/res/ \; @$(CP) -f $(SOUND_BIN_DIR)/sound_data.tbl $(BUILD_DIR)/res/sound/
@$(CP) -f $(SOUND_BIN_DIR)/sequences.bin $(BUILD_DIR)/res/sound/
@$(CP) -f $(SOUND_BIN_DIR)/bank_sets $(BUILD_DIR)/res/sound/
@find actors -name \*.png -exec $(CP) --parents {} $(BUILD_DIR)/res/ \;
@find levels -name \*.png -exec $(CP) --parents {} $(BUILD_DIR)/res/ \;
endif endif
clean: clean:
@ -724,7 +749,7 @@ endif
################################################################ ################################################################
# RGBA32, RGBA16, IA16, IA8, IA4, IA1, I8, I4 # RGBA32, RGBA16, IA16, IA8, IA4, IA1, I8, I4
ifeq ($(EXTERNAL_TEXTURES),1) ifeq ($(EXTERNAL_DATA),1)
$(BUILD_DIR)/%: %.png $(BUILD_DIR)/%: %.png
$(ZEROTERM) "$(patsubst %.png,%,$^)" > $@ $(ZEROTERM) "$(patsubst %.png,%,$^)" > $@
else else
@ -736,7 +761,7 @@ $(BUILD_DIR)/%.inc.c: $(BUILD_DIR)/% %.png
hexdump -v -e '1/1 "0x%X,"' $< > $@ hexdump -v -e '1/1 "0x%X,"' $< > $@
echo >> $@ echo >> $@
ifeq ($(EXTERNAL_TEXTURES),0) ifeq ($(EXTERNAL_DATA),0)
# Color Index CI8 # Color Index CI8
$(BUILD_DIR)/%.ci8: %.ci8.png $(BUILD_DIR)/%.ci8: %.ci8.png
$(N64GRAPHICS_CI) -i $@ -g $< -f ci8 $(N64GRAPHICS_CI) -i $@ -g $< -f ci8
@ -787,6 +812,18 @@ $(SOUND_BIN_DIR)/%.m64: $(SOUND_BIN_DIR)/%.o
$(SOUND_BIN_DIR)/%.o: $(SOUND_BIN_DIR)/%.s $(SOUND_BIN_DIR)/%.o: $(SOUND_BIN_DIR)/%.s
$(AS) $(ASFLAGS) -o $@ $< $(AS) $(ASFLAGS) -o $@ $<
ifeq ($(EXTERNAL_DATA),1)
$(SOUND_BIN_DIR)/sound_data.ctl.c: $(SOUND_BIN_DIR)/sound_data.ctl
echo "unsigned char gSoundDataADSR[] = \"sound/sound_data.ctl\";" > $@
$(SOUND_BIN_DIR)/sound_data.tbl.c: $(SOUND_BIN_DIR)/sound_data.tbl
echo "unsigned char gSoundDataRaw[] = \"sound/sound_data.tbl\";" > $@
$(SOUND_BIN_DIR)/sequences.bin.c: $(SOUND_BIN_DIR)/sequences.bin
echo "unsigned char gMusicData[] = \"sound/sequences.bin\";" > $@
$(SOUND_BIN_DIR)/bank_sets.c: $(SOUND_BIN_DIR)/bank_sets
echo "unsigned char gBankSetsData[] = \"sound/bank_sets\";" > $@
else
$(SOUND_BIN_DIR)/sound_data.ctl.c: $(SOUND_BIN_DIR)/sound_data.ctl $(SOUND_BIN_DIR)/sound_data.ctl.c: $(SOUND_BIN_DIR)/sound_data.ctl
echo "unsigned char gSoundDataADSR[] = {" > $@ echo "unsigned char gSoundDataADSR[] = {" > $@
@ -808,6 +845,8 @@ $(SOUND_BIN_DIR)/bank_sets.c: $(SOUND_BIN_DIR)/bank_sets
hexdump -v -e '1/1 "0x%X,"' $< >> $@ hexdump -v -e '1/1 "0x%X,"' $< >> $@
echo "};" >> $@ echo "};" >> $@
endif
$(BUILD_DIR)/levels/scripts.o: $(BUILD_DIR)/include/level_headers.h $(BUILD_DIR)/levels/scripts.o: $(BUILD_DIR)/include/level_headers.h
$(BUILD_DIR)/include/level_headers.h: levels/level_headers.h.in $(BUILD_DIR)/include/level_headers.h: levels/level_headers.h.in

View File

@ -34,14 +34,14 @@ This section contains two flags for menu.
| Flag | Value | Description | | Flag | Value | Description |
|---|---|---| |---|---|---|
| coin_score_age | ?? | Each save file has a 2 bit "age" for each course. The higher this value, the older the high score is. This is used for tie-breaking when displaying on the high score screen | coin_score_age | 0, 1, 2, 3 | Each save file has a 2 bit "age" for each course. The higher this value, the older the high score is. This is used for tie-breaking when displaying on the high score screen
| sound_mode | ?? | Sound mode for the game: stereo, mono, or headset | sound_mode | stereo, mono, headset | Sound mode for the game
Example: Example:
``` ```
[menu] [menu]
coin_score_age = ?? coin_score_age = 0
sound_mode = ?? sound_mode = stereo
``` ```
___ ___
## Flags Section - [flags] ## Flags Section - [flags]
@ -145,14 +145,14 @@ ___
This section contains information about where Mario lost his cap and who take it. This section contains information about where Mario lost his cap and who take it.
| Flag | Value | Description | | Flag | Value | Description |
|---|---|---| |---|---|---|
| type | ground, klepto, ukiki, mrblizzard | The one who or what took the cap from Mario. | type | ground, klepto, ukiki, mrblizzard | The one who or what took the cap from Mario. Default flag is **"ground"**
| level | ?? | Specifies the course where the cap is located. | level | ssl, sl, ttm, none | Specifies the course where the cap is located. Default flag is **"none"**.
| area | ?? | Specifies the area in the course. | area | 1, 2 | Specifies the area in the course.
Example: Example:
``` ```
[cap] [cap]
type = onground type = ground
level = 5 level = ssl
area = 0 area = 1
``` ```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 417 B

View File

@ -6,6 +6,8 @@
#include "data.h" #include "data.h"
#include "seqplayer.h" #include "seqplayer.h"
#include "../pc/platform.h"
#define ALIGN16(val) (((val) + 0xF) & ~0xF) #define ALIGN16(val) (((val) + 0xF) & ~0xF)
struct SharedDma { struct SharedDma {
@ -868,6 +870,24 @@ void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) {
seqPlayer->scriptState.pc = sequenceData; seqPlayer->scriptState.pc = sequenceData;
} }
#ifdef EXTERNAL_DATA
# define LOAD_DATA(x) load_sound_res((const char *)x)
# include <stdio.h>
# include <stdlib.h>
static inline void *load_sound_res(const char *path) {
void *data = sys_load_res(path);
if (!data) {
fprintf(stderr, "could not load sound data from '%s'\n", path);
abort();
}
// FIXME: figure out where it is safe to free this shit
// can't free it immediately after in audio_init()
return data;
}
#else
# define LOAD_DATA(x) x
#endif
void audio_init() { void audio_init() {
#ifdef VERSION_EU #ifdef VERSION_EU
UNUSED s8 pad[16]; UNUSED s8 pad[16];
@ -966,7 +986,7 @@ void audio_init() {
// Load header for sequence data (assets/music_data.sbk.s) // Load header for sequence data (assets/music_data.sbk.s)
gSeqFileHeader = (ALSeqFile *) buf; gSeqFileHeader = (ALSeqFile *) buf;
data = gMusicData; data = LOAD_DATA(gMusicData);
audio_dma_copy_immediate((uintptr_t) data, gSeqFileHeader, 0x10); audio_dma_copy_immediate((uintptr_t) data, gSeqFileHeader, 0x10);
gSequenceCount = gSeqFileHeader->seqCount; gSequenceCount = gSeqFileHeader->seqCount;
#ifdef VERSION_EU #ifdef VERSION_EU
@ -981,7 +1001,7 @@ void audio_init() {
// Load header for CTL (assets/sound_data.ctl.s, i.e. ADSR) // Load header for CTL (assets/sound_data.ctl.s, i.e. ADSR)
gAlCtlHeader = (ALSeqFile *) buf; gAlCtlHeader = (ALSeqFile *) buf;
data = gSoundDataADSR; data = LOAD_DATA(gSoundDataADSR);
audio_dma_copy_immediate((uintptr_t) data, gAlCtlHeader, 0x10); audio_dma_copy_immediate((uintptr_t) data, gAlCtlHeader, 0x10);
size = gAlCtlHeader->seqCount * sizeof(ALSeqData) + 4; size = gAlCtlHeader->seqCount * sizeof(ALSeqData) + 4;
size = ALIGN16(size); size = ALIGN16(size);
@ -996,14 +1016,16 @@ void audio_init() {
size = gAlTbl->seqCount * sizeof(ALSeqData) + 4; size = gAlTbl->seqCount * sizeof(ALSeqData) + 4;
size = ALIGN16(size); size = ALIGN16(size);
gAlTbl = soundAlloc(&gAudioInitPool, size); gAlTbl = soundAlloc(&gAudioInitPool, size);
audio_dma_copy_immediate((uintptr_t) gSoundDataRaw, gAlTbl, size);
alSeqFileNew(gAlTbl, gSoundDataRaw); data = LOAD_DATA(gSoundDataRaw);
audio_dma_copy_immediate((uintptr_t) data, gAlTbl, size);
alSeqFileNew(gAlTbl, data);
// Load bank sets for each sequence (assets/bank_sets.s) // Load bank sets for each sequence (assets/bank_sets.s)
data = LOAD_DATA(gBankSetsData);
gAlBankSets = soundAlloc(&gAudioInitPool, 0x100); gAlBankSets = soundAlloc(&gAudioInitPool, 0x100);
audio_dma_copy_immediate((uintptr_t) gBankSetsData, gAlBankSets, 0x100); audio_dma_copy_immediate((uintptr_t) data, gAlBankSets, 0x100);
init_sequence_players(); init_sequence_players();
gAudioLoadLock = AUDIO_LOCK_NOT_LOADING; gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
} }

View File

@ -62,11 +62,13 @@ void fish_act_spawn(void) {
* Y coordinate is greater than 2000.0f then spawn another fish. * Y coordinate is greater than 2000.0f then spawn another fish.
*/ */
void fish_act_respawn(void) { void fish_act_respawn(void) {
#ifndef NODRAWINGDISTANCE
if (gCurrLevelNum != LEVEL_SA) { if (gCurrLevelNum != LEVEL_SA) {
if (gMarioObject->oPosY - o->oPosY > 2000.0f) { if (gMarioObject->oPosY - o->oPosY > 2000.0f) {
o->oAction = FISH_ACT_RESPAWN; o->oAction = FISH_ACT_RESPAWN;
} }
} }
#endif
} }
/** /**

View File

@ -128,7 +128,7 @@ u8 gMenuHoldKeyIndex = 0;
u8 gMenuHoldKeyTimer = 0; u8 gMenuHoldKeyTimer = 0;
s32 gDialogResponse = 0; s32 gDialogResponse = 0;
#if !defined(EXTERNAL_TEXTURES) && (defined(VERSION_JP) || defined(VERSION_SH) || defined(VERSION_EU)) #if !defined(EXTERNAL_DATA) && (defined(VERSION_JP) || defined(VERSION_SH) || defined(VERSION_EU))
#ifdef VERSION_EU #ifdef VERSION_EU
#define CHCACHE_BUFLEN (8 * 8) // EU only converts 8x8 #define CHCACHE_BUFLEN (8 * 8) // EU only converts 8x8
#else #else
@ -242,7 +242,7 @@ 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) { static inline u8 *convert_ia8_char(u8 c, u16 *tex, s16 w, s16 h) {
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
return (u8 *)tex; // the data's just a name return (u8 *)tex; // the data's just a name
#else #else
if (!tex) return NULL; if (!tex) return NULL;
@ -303,7 +303,7 @@ 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) { static u8 *convert_ia4_char(u8 c, u8 *tex, s16 w, s16 h) {
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
return tex; // the data's just a name return tex; // the data's just a name
#else #else
if (!tex) return NULL; if (!tex) return NULL;

View File

@ -1,5 +1,4 @@
#include <ultra64.h> #include <ultra64.h>
#include <stdio.h>
#include "sm64.h" #include "sm64.h"
#include "game_init.h" #include "game_init.h"
#include "main.h" #include "main.h"

View File

@ -1,4 +1,8 @@
#include <string.h> #include <string.h>
#include <stdio.h>
#include <time.h>
#include "course_table.h"
#include "pc/ini.h"
#define FILENAME_FORMAT "save_file_%d.sav" #define FILENAME_FORMAT "save_file_%d.sav"
#define NUM_COURSES 15 #define NUM_COURSES 15
@ -6,7 +10,7 @@
#define NUM_FLAGS 21 #define NUM_FLAGS 21
#define NUM_CAP_ON 4 #define NUM_CAP_ON 4
/* Flag key */ /* Flag keys */
const char *sav_flags[NUM_FLAGS] = { const char *sav_flags[NUM_FLAGS] = {
"file_exists", "wing_cap", "metal_cap", "vanish_cap", "key_1", "key_2", "file_exists", "wing_cap", "metal_cap", "vanish_cap", "key_1", "key_2",
"basement_door", "upstairs_door", "ddd_moved_back", "moat_drained", "basement_door", "upstairs_door", "ddd_moved_back", "moat_drained",
@ -31,6 +35,11 @@ const char *cap_on_types[NUM_CAP_ON] = {
"ground", "klepto", "ukiki", "mrblizzard" "ground", "klepto", "ukiki", "mrblizzard"
}; };
/* Sound modes */
const char *sound_modes[3] = {
"stereo", "mono", "headset"
};
/* Get current timestamp */ /* Get current timestamp */
static void get_timestamp(char* buffer) { static void get_timestamp(char* buffer) {
time_t timer; time_t timer;
@ -75,7 +84,7 @@ static s32 write_text_save(s32 fileIndex) {
struct MainMenuSaveData *menudata; struct MainMenuSaveData *menudata;
char filename[32] = { 0 }; char filename[32] = { 0 };
char value[32] = { 0 }; char value[32] = { 0 };
u32 i, flags, coins, stars, starFlags; u32 i, bit, flags, coins, stars, starFlags;
/* Define savefile's name */ /* Define savefile's name */
if (sprintf(filename, FILENAME_FORMAT, fileIndex) < 0) if (sprintf(filename, FILENAME_FORMAT, fileIndex) < 0)
@ -84,6 +93,8 @@ static s32 write_text_save(s32 fileIndex) {
file = fopen(filename, "wt"); file = fopen(filename, "wt");
if (file == NULL) if (file == NULL)
return -1; return -1;
else
printf("Updating savefile in '%s'\n", filename);
/* Write header */ /* Write header */
fprintf(file, "# Super Mario 64 save file\n"); fprintf(file, "# Super Mario 64 save file\n");
@ -98,8 +109,22 @@ static s32 write_text_save(s32 fileIndex) {
menudata = &gSaveBuffer.menuData[0]; menudata = &gSaveBuffer.menuData[0];
fprintf(file, "\n[menu]\n"); fprintf(file, "\n[menu]\n");
fprintf(file, "coin_score_age = %d\n", menudata->coinScoreAges[fileIndex]); fprintf(file, "coin_score_age = %d\n", menudata->coinScoreAges[fileIndex]);
fprintf(file, "sound_mode = %u\n", menudata->soundMode);
/* Sound mode */
if (menudata->soundMode == 0) {
fprintf(file, "sound_mode = %s\n", sound_modes[0]); // stereo
}
else if (menudata->soundMode == 3) {
fprintf(file, "sound_mode = %s\n", sound_modes[1]); // mono
}
else if (menudata->soundMode == 1) {
fprintf(file, "sound_mode = %s\n", sound_modes[2]); // headset
}
else {
printf("Undefined sound mode!");
return -1;
}
/* Write all flags */ /* Write all flags */
fprintf(file, "\n[flags]\n"); fprintf(file, "\n[flags]\n");
for (i = 1; i < NUM_FLAGS; i++) { for (i = 1; i < NUM_FLAGS; i++) {
@ -139,7 +164,8 @@ static s32 write_text_save(s32 fileIndex) {
fprintf(file, "\n[cap]\n"); fprintf(file, "\n[cap]\n");
for (i = 0; i < NUM_CAP_ON; i++) { for (i = 0; i < NUM_CAP_ON; i++) {
flags = save_file_get_flags(); // Read all flags flags = save_file_get_flags(); // Read all flags
flags = (flags & (1 << (i+16))); // Get `cap` flags bit = (1 << (i+16)); // Determine current flag
flags = (flags & bit); // Get `cap` flag
flags = (flags) ? 1 : 0; // Determine if bit is set or not flags = (flags) ? 1 : 0; // Determine if bit is set or not
if (flags) { if (flags) {
fprintf(file, "type = %s\n", cap_on_types[i]); fprintf(file, "type = %s\n", cap_on_types[i]);
@ -149,7 +175,20 @@ static s32 write_text_save(s32 fileIndex) {
/* Write in what course and area Mario losted its cap, and cap's position */ /* Write in what course and area Mario losted its cap, and cap's position */
savedata = &gSaveBuffer.files[fileIndex][0]; savedata = &gSaveBuffer.files[fileIndex][0];
fprintf(file, "level = %d\n", savedata->capLevel); switch(savedata->capLevel) {
case COURSE_SSL:
fprintf(file, "level = %s\n", "ssl");
break;
case COURSE_SL:
fprintf(file, "level = %s\n", "sl");
break;
case COURSE_TTM:
fprintf(file, "level = %s\n", "ttm");
break;
default:
fprintf(file, "level = %s\n", "none");
break;
}
fprintf(file, "area = %d\n", savedata->capArea); fprintf(file, "area = %d\n", savedata->capArea);
fclose(file); fclose(file);
@ -166,8 +205,7 @@ static s32 read_text_save(s32 fileIndex) {
ini_t *savedata; ini_t *savedata;
u32 i, flag, coins, stars, starFlags; u32 i, flag, coins, stars, starFlags;
u32 capLevel, capArea; u32 capArea;
Vec3s capPos;
/* Define savefile's name */ /* Define savefile's name */
if (sprintf(filename, FILENAME_FORMAT, fileIndex) < 0) if (sprintf(filename, FILENAME_FORMAT, fileIndex) < 0)
@ -178,15 +216,30 @@ static s32 read_text_save(s32 fileIndex) {
if (savedata == NULL) { if (savedata == NULL) {
return -1; return -1;
} else { } else {
/* Good, file exists for gSaveBuffer */ printf("Loading savefile from '%s'\n", filename);
gSaveBuffer.files[fileIndex][0].flags |= SAVE_FLAG_FILE_EXISTS;
} }
/* Read coin score age for selected file and sound mode */ /* Read coin score age for selected file and sound mode */
ini_sget(savedata, "menu", "coin_score_age", "%d", ini_sget(savedata, "menu", "coin_score_age", "%d",
&gSaveBuffer.menuData[0].coinScoreAges[fileIndex]); &gSaveBuffer.menuData[0].coinScoreAges[fileIndex]);
ini_sget(savedata, "menu", "sound_mode", "%u",
&gSaveBuffer.menuData[0].soundMode); // Can override 4 times! value = ini_get(savedata, "menu", "sound_mode");
if (value) {
if (strcmp(value, sound_modes[0]) == 0) {
gSaveBuffer.menuData[0].soundMode = 0; // stereo
}
else if (strcmp(value, sound_modes[1]) == 0) {
gSaveBuffer.menuData[0].soundMode = 3; // mono
}
else if (strcmp(value, sound_modes[2]) == 0) {
gSaveBuffer.menuData[0].soundMode = 1; // headset
}
}
else {
printf("Invalid 'menu:sound_mode' flag!\n");
return -1;
}
/* Parse main flags */ /* Parse main flags */
for (i = 1; i < NUM_FLAGS; i++) { for (i = 1; i < NUM_FLAGS; i++) {
@ -245,14 +298,48 @@ static s32 read_text_save(s32 fileIndex) {
} }
} }
/* ... also it's position, area and level */ /* ... it's level ... */
sscanf(ini_get(savedata, "cap", "level"), "%d", &capLevel); value = ini_get(savedata, "cap", "level");
sscanf(ini_get(savedata, "cap", "area"), "%d", &capArea); if (value) {
if (strcmp(value, "ssl") == 0) {
gSaveBuffer.files[fileIndex][0].capLevel = 8; // ssl
}
else if (strcmp(value, "sl") == 0) {
gSaveBuffer.files[fileIndex][0].capLevel = 10; // sl
}
else if (strcmp(value, "ttm") == 0) {
gSaveBuffer.files[fileIndex][0].capLevel = 12; // ttm
}
else if (strcmp(value, "none") == 0) {
gSaveBuffer.files[fileIndex][0].capLevel = 0;
}
else {
printf("Invalid 'cap:level' flag!\n");
return -1;
}
}
gSaveBuffer.files[fileIndex][0].capLevel = capLevel; /* ... and it's area */
gSaveBuffer.files[fileIndex][0].capArea = capArea; value = ini_get(savedata, "cap", "area");
if (value) {
sscanf(value, "%d", &capArea);
if (capArea > 1 && capArea < 2) {
printf("Invalid 'cap:area' flag: %d!\n", capArea);
return -1;
}
else {
gSaveBuffer.files[fileIndex][0].capArea = capArea;
}
}
/* Good, file exists for gSaveBuffer */
gSaveBuffer.files[fileIndex][0].flags |= SAVE_FLAG_FILE_EXISTS;
/* Make a backup */
bcopy(&gSaveBuffer.files[fileIndex][0], &gSaveBuffer.files[fileIndex][1],
sizeof(gSaveBuffer.files[fileIndex][1]));
/* Cleaning up after ourselves */ /* Cleaning up after ourselves */
ini_free(savedata); ini_free(savedata);
return 1; return 0;
} }

View File

@ -68,8 +68,8 @@ unsigned int configKeyStickLeft[MAX_BINDS] = { 0x001E, VK_INVALID, VK_INVALID
unsigned int configKeyStickRight[MAX_BINDS] = { 0x0020, 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) unsigned int configStickDeadzone = 16; // 16*DEADZONE_STEP=4960 (the original default deadzone)
unsigned int configRumbleStrength = 50; unsigned int configRumbleStrength = 50;
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
bool configPrecacheRes = false; bool configPrecacheRes = true;
#endif #endif
#ifdef BETTERCAMERA #ifdef BETTERCAMERA
// BetterCamera settings // BetterCamera settings
@ -111,7 +111,7 @@ static const struct ConfigOption options[] = {
{.name = "key_stickright", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickRight}, {.name = "key_stickright", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickRight},
{.name = "stick_deadzone", .type = CONFIG_TYPE_UINT, .uintValue = &configStickDeadzone}, {.name = "stick_deadzone", .type = CONFIG_TYPE_UINT, .uintValue = &configStickDeadzone},
{.name = "rumble_strength", .type = CONFIG_TYPE_UINT, .uintValue = &configRumbleStrength}, {.name = "rumble_strength", .type = CONFIG_TYPE_UINT, .uintValue = &configRumbleStrength},
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
{.name = "precache", .type = CONFIG_TYPE_BOOL, .boolValue = &configPrecacheRes}, {.name = "precache", .type = CONFIG_TYPE_BOOL, .boolValue = &configPrecacheRes},
#endif #endif
#ifdef BETTERCAMERA #ifdef BETTERCAMERA

View File

@ -37,7 +37,7 @@ extern unsigned int configKeyStickLeft[];
extern unsigned int configKeyStickRight[]; extern unsigned int configKeyStickRight[];
extern unsigned int configStickDeadzone; extern unsigned int configStickDeadzone;
extern unsigned int configRumbleStrength; extern unsigned int configRumbleStrength;
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
extern bool configPrecacheRes; extern bool configPrecacheRes;
#endif #endif
#ifdef BETTERCAMERA #ifdef BETTERCAMERA

View File

@ -1,10 +1,18 @@
#ifndef CONTROLLER_API #ifndef CONTROLLER_API
#define CONTROLLER_API #define CONTROLLER_API
#define DEADZONE_STEP 310 // original deadzone is 4960 #define DEADZONE_STEP 310 // original deadzone is 4960
#define VK_INVALID 0xFFFF #define VK_INVALID 0xFFFF
#define VK_SIZE 0x1000 #define VK_SIZE 0x1000
// fake buttons for binding the stick directions
#define STICK_UP 0x80000
#define STICK_DOWN 0x40000
#define STICK_LEFT 0x10000
#define STICK_RIGHT 0x20000
#define STICK_XMASK 0x30000
#define STICK_YMASK 0xc0000
#include <ultra64.h> #include <ultra64.h>
struct ControllerAPI { struct ControllerAPI {

View File

@ -61,10 +61,10 @@ static void keyboard_bindkeys(void) {
bzero(keyboard_mapping, sizeof(keyboard_mapping)); bzero(keyboard_mapping, sizeof(keyboard_mapping));
num_keybinds = 0; num_keybinds = 0;
keyboard_add_binds(0x80000, configKeyStickUp); keyboard_add_binds(STICK_UP, configKeyStickUp);
keyboard_add_binds(0x10000, configKeyStickLeft); keyboard_add_binds(STICK_LEFT, configKeyStickLeft);
keyboard_add_binds(0x40000, configKeyStickDown); keyboard_add_binds(STICK_DOWN, configKeyStickDown);
keyboard_add_binds(0x20000, configKeyStickRight); keyboard_add_binds(STICK_RIGHT, configKeyStickRight);
keyboard_add_binds(A_BUTTON, configKeyA); keyboard_add_binds(A_BUTTON, configKeyA);
keyboard_add_binds(B_BUTTON, configKeyB); keyboard_add_binds(B_BUTTON, configKeyB);
keyboard_add_binds(Z_TRIG, configKeyZ); keyboard_add_binds(Z_TRIG, configKeyZ);
@ -87,18 +87,16 @@ static void keyboard_init(void) {
static void keyboard_read(OSContPad *pad) { static void keyboard_read(OSContPad *pad) {
pad->button |= keyboard_buttons_down; pad->button |= keyboard_buttons_down;
if ((keyboard_buttons_down & 0x30000) == 0x10000) { const u32 xstick = keyboard_buttons_down & STICK_XMASK;
const u32 ystick = keyboard_buttons_down & STICK_YMASK;
if (xstick == STICK_LEFT)
pad->stick_x = -128; pad->stick_x = -128;
} else if (xstick == STICK_RIGHT)
if ((keyboard_buttons_down & 0x30000) == 0x20000) {
pad->stick_x = 127; pad->stick_x = 127;
} if (ystick == STICK_DOWN)
if ((keyboard_buttons_down & 0xc0000) == 0x40000) {
pad->stick_y = -128; pad->stick_y = -128;
} else if (ystick == STICK_UP)
if ((keyboard_buttons_down & 0xc0000) == 0x80000) {
pad->stick_y = 127; pad->stick_y = 127;
}
} }
static u32 keyboard_rawkey(void) { static u32 keyboard_rawkey(void) {

View File

@ -13,6 +13,7 @@
#include "controller_api.h" #include "controller_api.h"
#include "controller_sdl.h" #include "controller_sdl.h"
#include "../configfile.h" #include "../configfile.h"
#include "../platform.h"
#include "game/level_update.h" #include "game/level_update.h"
@ -71,6 +72,10 @@ static void controller_sdl_bind(void) {
controller_add_binds(A_BUTTON, configKeyA); controller_add_binds(A_BUTTON, configKeyA);
controller_add_binds(B_BUTTON, configKeyB); controller_add_binds(B_BUTTON, configKeyB);
controller_add_binds(Z_TRIG, configKeyZ); controller_add_binds(Z_TRIG, configKeyZ);
controller_add_binds(STICK_UP, configKeyStickUp);
controller_add_binds(STICK_LEFT, configKeyStickLeft);
controller_add_binds(STICK_DOWN, configKeyStickDown);
controller_add_binds(STICK_RIGHT, configKeyStickRight);
controller_add_binds(U_CBUTTONS, configKeyCUp); controller_add_binds(U_CBUTTONS, configKeyCUp);
controller_add_binds(L_CBUTTONS, configKeyCLeft); controller_add_binds(L_CBUTTONS, configKeyCLeft);
controller_add_binds(D_CBUTTONS, configKeyCDown); controller_add_binds(D_CBUTTONS, configKeyCDown);
@ -86,6 +91,17 @@ static void controller_sdl_init(void) {
return; return;
} }
// try loading an external gamecontroller mapping file
char gcpath[SYS_MAX_PATH];
snprintf(gcpath, sizeof(gcpath), "%s/gamecontrollerdb.txt", sys_save_path());
int nummaps = SDL_GameControllerAddMappingsFromFile(gcpath);
if (nummaps < 0) {
snprintf(gcpath, sizeof(gcpath), "%s/gamecontrollerdb.txt", sys_data_path());
nummaps = SDL_GameControllerAddMappingsFromFile(gcpath);
}
if (nummaps >= 0)
printf("loaded %d controller mappings from '%s'\n", nummaps, gcpath);
#ifdef BETTERCAMERA #ifdef BETTERCAMERA
if (newcam_mouse == 1) if (newcam_mouse == 1)
SDL_SetRelativeMouseMode(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_TRUE);
@ -117,7 +133,6 @@ static void controller_sdl_read(OSContPad *pad) {
// remember buttons that changed from 0 to 1 // remember buttons that changed from 0 to 1
last_mouse = (mouse_buttons ^ mouse) & mouse; last_mouse = (mouse_buttons ^ mouse) & mouse;
mouse_buttons = mouse; mouse_buttons = mouse;
#endif #endif
SDL_GameControllerUpdate(); SDL_GameControllerUpdate();
@ -148,9 +163,23 @@ static void controller_sdl_read(OSContPad *pad) {
if (pressed) last_joybutton = i; if (pressed) last_joybutton = i;
} }
u32 buttons_down = 0;
for (u32 i = 0; i < num_joy_binds; ++i) for (u32 i = 0; i < num_joy_binds; ++i)
if (joy_buttons[joy_binds[i][0]]) if (joy_buttons[joy_binds[i][0]])
pad->button |= joy_binds[i][1]; buttons_down |= joy_binds[i][1];
pad->button |= buttons_down;
const u32 xstick = buttons_down & STICK_XMASK;
const u32 ystick = buttons_down & STICK_YMASK;
if (xstick == STICK_LEFT)
pad->stick_x = -128;
else if (xstick == STICK_RIGHT)
pad->stick_x = 127;
if (ystick == STICK_DOWN)
pad->stick_y = -128;
else if (ystick == STICK_UP)
pad->stick_y = 127;
int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX); int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX);
int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY); int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY);
@ -225,7 +254,7 @@ static void controller_sdl_shutdown(void) {
u32 controller_rumble_init(void) { u32 controller_rumble_init(void) {
if (SDL_HapticRumbleSupported(sdl_haptic) != SDL_TRUE) { if (SDL_HapticRumbleSupported(sdl_haptic) != SDL_TRUE) {
printf("Controller does not support haptics! %s\n", SDL_GetError()); // printf("Controller does not support haptics! %s\n", SDL_GetError());
return 1; return 1;
} }
if (SDL_HapticRumbleInit(sdl_haptic) != 0) { if (SDL_HapticRumbleInit(sdl_haptic) != 0) {
@ -235,6 +264,7 @@ u32 controller_rumble_init(void) {
return 0; return 0;
} }
s32 controller_rumble_play(f32 strength, u32 length) { s32 controller_rumble_play(f32 strength, u32 length) {
if (SDL_HapticRumblePlay(sdl_haptic, strength, length) != 0) { if (SDL_HapticRumblePlay(sdl_haptic, strength, length) != 0) {
printf("Unable to start rumble! %s\n", SDL_GetError()); printf("Unable to start rumble! %s\n", SDL_GetError());

View File

@ -6,7 +6,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h> #include <stb/stb_image.h>
#endif #endif
@ -47,7 +47,7 @@
#define MAX_LIGHTS 2 #define MAX_LIGHTS 2
#define MAX_VERTICES 64 #define MAX_VERTICES 64
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
# define MAX_CACHED_TEXTURES 4096 // for preloading purposes # define MAX_CACHED_TEXTURES 4096 // for preloading purposes
# define HASH_SHIFT 0 # define HASH_SHIFT 0
#else #else
@ -173,7 +173,7 @@ static size_t buf_vbo_num_tris;
static struct GfxWindowManagerAPI *gfx_wapi; static struct GfxWindowManagerAPI *gfx_wapi;
static struct GfxRenderingAPI *gfx_rapi; static struct GfxRenderingAPI *gfx_rapi;
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
static inline size_t string_hash(const uint8_t *str) { static inline size_t string_hash(const uint8_t *str) {
size_t h = 0; size_t h = 0;
for (const uint8_t *p = str; *p; p++) for (const uint8_t *p = str; *p; p++)
@ -275,9 +275,9 @@ 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) { 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 #ifdef EXTERNAL_DATA // hash and compare the data (i.e. the texture name) itself
size_t hash = string_hash(orig_addr); size_t hash = string_hash(orig_addr);
#define CMPADDR(x, y) (x && !sys_strcasecmp(x, y)) #define CMPADDR(x, y) (x && !sys_strcasecmp((const char *)x, (const char *)y))
#else // hash and compare the address #else // hash and compare the address
size_t hash = (uintptr_t)orig_addr; size_t hash = (uintptr_t)orig_addr;
#define CMPADDR(x, y) x == y #define CMPADDR(x, y) x == y
@ -318,7 +318,7 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
#undef CMPADDR #undef CMPADDR
} }
#ifndef EXTERNAL_TEXTURES #ifndef EXTERNAL_DATA
static void import_texture_rgba32(int tile) { static void import_texture_rgba32(int tile) {
uint32_t width = rdp.texture_tile.line_size_bytes / 2; uint32_t width = rdp.texture_tile.line_size_bytes / 2;
@ -492,7 +492,7 @@ static void import_texture_ci8(int tile) {
gfx_rapi->upload_texture(rgba32_buf, width, height); gfx_rapi->upload_texture(rgba32_buf, width, height);
} }
#else // EXTERNAL_TEXTURES #else // EXTERNAL_DATA
// this is taken straight from n64graphics // this is taken straight from n64graphics
static bool texname_to_texformat(const char *name, u8 *fmt, u8 *siz) { static bool texname_to_texformat(const char *name, u8 *fmt, u8 *siz) {
@ -595,7 +595,7 @@ static inline void load_texture(const char *name) {
stbi_image_free(data); // don't need this anymore stbi_image_free(data); // don't need this anymore
} }
#endif // EXTERNAL_TEXTURES #endif // EXTERNAL_DATA
static void import_texture(int tile) { static void import_texture(int tile) {
uint8_t fmt = rdp.texture_tile.fmt; uint8_t fmt = rdp.texture_tile.fmt;
@ -611,7 +611,7 @@ static void import_texture(int tile) {
return; return;
} }
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
// the "texture data" is actually a C string with the path to our texture in it // 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 it from an external image in our data path
load_texture((const char*)rdp.loaded_texture[tile].addr); load_texture((const char*)rdp.loaded_texture[tile].addr);
@ -1761,7 +1761,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi) {
for (size_t i = 0; i < sizeof(precomp_shaders) / sizeof(uint32_t); i++) { for (size_t i = 0; i < sizeof(precomp_shaders) / sizeof(uint32_t); i++) {
gfx_lookup_or_create_shader_program(precomp_shaders[i]); gfx_lookup_or_create_shader_program(precomp_shaders[i]);
} }
#ifdef EXTERNAL_TEXTURES #ifdef EXTERNAL_DATA
// preload all textures if needed // preload all textures if needed
if (configPrecacheRes) { if (configPrecacheRes) {
printf("Precaching textures from `%s`\n", sys_data_path()); printf("Precaching textures from `%s`\n", sys_data_path());

View File

@ -86,6 +86,29 @@ bool sys_dir_walk(const char *base, walk_fn_t walk, const bool recur) {
return ret; return ret;
} }
void *sys_load_res(const char *name) {
char path[SYS_MAX_PATH] = { 0 };
snprintf(path, sizeof(path), "%s/%s", sys_data_path(), name);
FILE *f = fopen(path, "rb");
if (!f) return NULL;
fseek(f, 0, SEEK_END);
size_t size = ftell(f);
fseek(f, 0, SEEK_SET);
void *buf = malloc(size);
if (!buf) {
fclose(f);
return NULL;
}
fread(buf, 1, size, f);
fclose(f);
return buf;
}
bool sys_mkdir(const char *name) { bool sys_mkdir(const char *name) {
#ifdef _WIN32 #ifdef _WIN32
return _mkdir(name) == 0; return _mkdir(name) == 0;

View File

@ -19,6 +19,7 @@ int sys_strcasecmp(const char *s1, const char *s2);
bool sys_mkdir(const char *name); // creates with 0777 by default bool sys_mkdir(const char *name); // creates with 0777 by default
bool sys_file_exists(const char *name); bool sys_file_exists(const char *name);
bool sys_dir_exists(const char *name); bool sys_dir_exists(const char *name);
void *sys_load_res(const char *name);
// receives the full path // receives the full path
// should return `true` if traversal should continue // should return `true` if traversal should continue