mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-21 19:45:10 +00:00
Prevent the game from caching downloaded WIP mods (#69)
* don't tmp or cache wip mods * update
This commit is contained in:
parent
69cb215219
commit
c4214ed2da
10 changed files with 351 additions and 56 deletions
|
@ -9,6 +9,7 @@ extern "C" {
|
||||||
#include "engine/math_util.h"
|
#include "engine/math_util.h"
|
||||||
#include "game/moving_texture.h"
|
#include "game/moving_texture.h"
|
||||||
#include "pc/djui/djui_console.h"
|
#include "pc/djui/djui_console.h"
|
||||||
|
#include "pc/fs/fmem.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FUNCTION_CODE (u32) 0x434E5546
|
#define FUNCTION_CODE (u32) 0x434E5546
|
||||||
|
@ -95,16 +96,16 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BinFile *OpenR(const char *aFilename) {
|
static BinFile *OpenR(const char *aFilename) {
|
||||||
FILE *f = fopen(aFilename, "rb");
|
FILE *f = f_open_r(aFilename);
|
||||||
if (f) {
|
if (f) {
|
||||||
fseek(f, 0, SEEK_END);
|
f_seek(f, 0, SEEK_END);
|
||||||
BinFile *_BinFile = (BinFile *) calloc(1, sizeof(BinFile));
|
BinFile *_BinFile = (BinFile *) calloc(1, sizeof(BinFile));
|
||||||
_BinFile->mFilename = (const char *) memcpy(calloc(strlen(aFilename) + 1, 1), aFilename, strlen(aFilename));
|
_BinFile->mFilename = (const char *) memcpy(calloc(strlen(aFilename) + 1, 1), aFilename, strlen(aFilename));
|
||||||
_BinFile->mReadOnly = true;
|
_BinFile->mReadOnly = true;
|
||||||
_BinFile->Grow(ftell(f));
|
_BinFile->Grow(f_tell(f));
|
||||||
rewind(f);
|
f_rewind(f);
|
||||||
fread(_BinFile->mData, 1, _BinFile->mSize, f);
|
f_read(_BinFile->mData, 1, _BinFile->mSize, f);
|
||||||
fclose(f);
|
f_close(f);
|
||||||
return _BinFile;
|
return _BinFile;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -17,7 +17,7 @@ static inline void DynOS_Bin_Compress_Init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void DynOS_Bin_Compress_Close() {
|
static inline void DynOS_Bin_Compress_Close() {
|
||||||
if (sFile) fclose(sFile);
|
if (sFile) f_close(sFile);
|
||||||
sFile = NULL;
|
sFile = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,14 +159,14 @@ BinFile *DynOS_Bin_Decompress(const SysPath &aFilename) {
|
||||||
|
|
||||||
// Open input file
|
// Open input file
|
||||||
if (!DynOS_Bin_Compress_Check(
|
if (!DynOS_Bin_Compress_Check(
|
||||||
(sFile = fopen(aFilename.c_str(), "rb")) != NULL,
|
(sFile = f_open_r(aFilename.c_str())) != NULL,
|
||||||
__FUNCTION__, aFilename.c_str(), "Cannot open file"
|
__FUNCTION__, aFilename.c_str(), "Cannot open file"
|
||||||
)) return NULL;
|
)) return NULL;
|
||||||
|
|
||||||
// Read magic
|
// Read magic
|
||||||
u64 _Magic = 0;
|
u64 _Magic = 0;
|
||||||
if (!DynOS_Bin_Compress_Check(
|
if (!DynOS_Bin_Compress_Check(
|
||||||
fread(&_Magic, sizeof(u64), 1, sFile) == 1,
|
f_read(&_Magic, sizeof(u64), 1, sFile) == 1,
|
||||||
__FUNCTION__, aFilename.c_str(), "Cannot read magic"
|
__FUNCTION__, aFilename.c_str(), "Cannot read magic"
|
||||||
)) return NULL;
|
)) return NULL;
|
||||||
|
|
||||||
|
@ -180,20 +180,20 @@ BinFile *DynOS_Bin_Decompress(const SysPath &aFilename) {
|
||||||
|
|
||||||
// Read expected uncompressed file size
|
// Read expected uncompressed file size
|
||||||
if (!DynOS_Bin_Compress_Check(
|
if (!DynOS_Bin_Compress_Check(
|
||||||
fread(&sLengthUncompressed, sizeof(u64), 1, sFile) == 1,
|
f_read(&sLengthUncompressed, sizeof(u64), 1, sFile) == 1,
|
||||||
__FUNCTION__, aFilename.c_str(), "Cannot read uncompressed file size"
|
__FUNCTION__, aFilename.c_str(), "Cannot read uncompressed file size"
|
||||||
)) return NULL;
|
)) return NULL;
|
||||||
|
|
||||||
// Retrieve file length
|
// Retrieve file length
|
||||||
if (!DynOS_Bin_Compress_Check(
|
if (!DynOS_Bin_Compress_Check(
|
||||||
fseek(sFile, 0, SEEK_END) == 0,
|
f_seek(sFile, 0, SEEK_END) == 0,
|
||||||
__FUNCTION__, aFilename.c_str(), "Cannot retrieve file length"
|
__FUNCTION__, aFilename.c_str(), "Cannot retrieve file length"
|
||||||
)) return NULL;
|
)) return NULL;
|
||||||
|
|
||||||
// Check file length
|
// Check file length
|
||||||
u64 _LengthHeader = (u64) (sizeof(u64) + sizeof(u64));
|
u64 _LengthHeader = (u64) (sizeof(u64) + sizeof(u64));
|
||||||
if (!DynOS_Bin_Compress_Check(
|
if (!DynOS_Bin_Compress_Check(
|
||||||
(sLengthCompressed = (u64) ftell(sFile)) >= _LengthHeader,
|
(sLengthCompressed = (u64) f_tell(sFile)) >= _LengthHeader,
|
||||||
__FUNCTION__, aFilename.c_str(), "Empty file"
|
__FUNCTION__, aFilename.c_str(), "Empty file"
|
||||||
)) return NULL;
|
)) return NULL;
|
||||||
|
|
||||||
|
@ -201,11 +201,11 @@ BinFile *DynOS_Bin_Decompress(const SysPath &aFilename) {
|
||||||
if (!DynOS_Bin_Compress_Check(
|
if (!DynOS_Bin_Compress_Check(
|
||||||
(sBufferCompressed = (u8 *) calloc(sLengthCompressed - _LengthHeader, sizeof(u8))) != NULL,
|
(sBufferCompressed = (u8 *) calloc(sLengthCompressed - _LengthHeader, sizeof(u8))) != NULL,
|
||||||
__FUNCTION__, aFilename.c_str(), "Cannot allocate memory for decompression"
|
__FUNCTION__, aFilename.c_str(), "Cannot allocate memory for decompression"
|
||||||
)) return NULL; else fseek(sFile, _LengthHeader, SEEK_SET);
|
)) return NULL; else f_seek(sFile, _LengthHeader, SEEK_SET);
|
||||||
|
|
||||||
// Read input data
|
// Read input data
|
||||||
if (!DynOS_Bin_Compress_Check(
|
if (!DynOS_Bin_Compress_Check(
|
||||||
fread(sBufferCompressed, sizeof(u8), sLengthCompressed - _LengthHeader, sFile) == sLengthCompressed - _LengthHeader,
|
f_read(sBufferCompressed, sizeof(u8), sLengthCompressed - _LengthHeader, sFile) == sLengthCompressed - _LengthHeader,
|
||||||
__FUNCTION__, aFilename.c_str(), "Cannot read compressed data"
|
__FUNCTION__, aFilename.c_str(), "Cannot read compressed data"
|
||||||
)) return NULL; else DynOS_Bin_Compress_Close();
|
)) return NULL; else DynOS_Bin_Compress_Close();
|
||||||
|
|
||||||
|
|
164
src/pc/fs/fmem.c
Normal file
164
src/pc/fs/fmem.c
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
#include "fmem.h"
|
||||||
|
#include "pc/platform.h"
|
||||||
|
#include "engine/math_util.h"
|
||||||
|
|
||||||
|
typedef struct file_t {
|
||||||
|
char filename[SYS_MAX_PATH];
|
||||||
|
void *data;
|
||||||
|
size_t size;
|
||||||
|
size_t pos;
|
||||||
|
bool readonly;
|
||||||
|
} file_t;
|
||||||
|
|
||||||
|
typedef struct file_node_t {
|
||||||
|
file_t file;
|
||||||
|
struct file_node_t *prev;
|
||||||
|
struct file_node_t *next;
|
||||||
|
} file_node_t;
|
||||||
|
|
||||||
|
static file_node_t *sMemoryFiles = NULL;
|
||||||
|
|
||||||
|
static file_t *f_get_file_from_handle(FILE *f) {
|
||||||
|
for (file_node_t *node = sMemoryFiles; node; node = node->prev) {
|
||||||
|
if (node == (void *) f) {
|
||||||
|
return &node->file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static file_t *f_get_file_from_name(const char *filename) {
|
||||||
|
for (file_node_t *node = sMemoryFiles; node; node = node->prev) {
|
||||||
|
if (strcmp(node->file.filename, filename) == 0) {
|
||||||
|
return &node->file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static file_t *f_create_file(const char *filename) {
|
||||||
|
file_node_t *node = calloc(1, sizeof(file_node_t));
|
||||||
|
if (sMemoryFiles) {
|
||||||
|
sMemoryFiles->next = node;
|
||||||
|
node->prev = sMemoryFiles;
|
||||||
|
}
|
||||||
|
sMemoryFiles = node;
|
||||||
|
strncpy(node->file.filename, filename, sizeof(node->file.filename) - 1);
|
||||||
|
return &node->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f_remove_file(file_t *file) {
|
||||||
|
file_node_t *node = (file_node_t *) file;
|
||||||
|
if (node->prev) {
|
||||||
|
node->prev->next = node->next;
|
||||||
|
}
|
||||||
|
if (node->next) {
|
||||||
|
node->next->prev = node->prev;
|
||||||
|
}
|
||||||
|
if (node == sMemoryFiles) {
|
||||||
|
sMemoryFiles = node->prev;
|
||||||
|
}
|
||||||
|
if (file->data) {
|
||||||
|
free(file->data);
|
||||||
|
}
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f_open_r(const char *filename) {
|
||||||
|
file_t *file = f_get_file_from_name(filename);
|
||||||
|
if (!file) return fopen(filename, "rb");
|
||||||
|
file->pos = 0;
|
||||||
|
file->readonly = true;
|
||||||
|
return (FILE *) file;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f_open_w(const char *filename) {
|
||||||
|
file_t *file = f_create_file(filename);
|
||||||
|
return (FILE *) file;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f_close(FILE *f) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void f_delete(FILE *f) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return;
|
||||||
|
f_remove_file(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t f_read(void *dst, size_t size, size_t count, FILE *f) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return fread(dst, size, count, f);
|
||||||
|
if (file->pos >= file->size) return 0;
|
||||||
|
count = min(count, ((file->size - file->pos) / size));
|
||||||
|
memcpy(dst, file->data + file->pos, count * size);
|
||||||
|
file->pos += count * size;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t f_write(const void *str, size_t size, size_t count, FILE *f) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return fwrite(str, size, count, f);
|
||||||
|
if (file->readonly) return 0;
|
||||||
|
size_t newsize = file->pos + size * count;
|
||||||
|
if (newsize > file->size) {
|
||||||
|
void *buffer = malloc(newsize);
|
||||||
|
if (!buffer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (file->data) {
|
||||||
|
memcpy(buffer, file->data, file->size);
|
||||||
|
free(file->data);
|
||||||
|
}
|
||||||
|
file->data = buffer;
|
||||||
|
file->size = newsize;
|
||||||
|
}
|
||||||
|
memcpy(file->data + file->pos, str, size * count);
|
||||||
|
file->pos += size * count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f_seek(FILE *f, long offset, int origin) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return fseek(f, offset, origin);
|
||||||
|
switch (origin) {
|
||||||
|
case SEEK_SET: file->pos = offset; break;
|
||||||
|
case SEEK_CUR: file->pos += offset; break;
|
||||||
|
case SEEK_END: file->pos = file->size + offset; break;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long f_tell(FILE *f) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return ftell(f);
|
||||||
|
return file->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void f_rewind(FILE *f) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return rewind(f);
|
||||||
|
file->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f_flush(FILE *f) {
|
||||||
|
file_t *file = f_get_file_from_handle(f);
|
||||||
|
if (!file) return fflush(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void f_shutdown() {
|
||||||
|
for (file_node_t *node = sMemoryFiles; node;) {
|
||||||
|
if (node->file.data) {
|
||||||
|
free(node->file.data);
|
||||||
|
}
|
||||||
|
file_node_t *prev = node->prev;
|
||||||
|
free(node);
|
||||||
|
node = prev;
|
||||||
|
}
|
||||||
|
sMemoryFiles = NULL;
|
||||||
|
}
|
18
src/pc/fs/fmem.h
Normal file
18
src/pc/fs/fmem.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef FMEM_H
|
||||||
|
#define FMEM_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
FILE *f_open_r (const char *filename);
|
||||||
|
FILE *f_open_w (const char *filename);
|
||||||
|
int f_close (FILE *f);
|
||||||
|
void f_delete (FILE *f);
|
||||||
|
size_t f_read (void *dst, size_t size, size_t count, FILE *f);
|
||||||
|
size_t f_write (const void *str, size_t size, size_t count, FILE *f);
|
||||||
|
int f_seek (FILE *f, long offset, int origin);
|
||||||
|
long f_tell (FILE *f);
|
||||||
|
void f_rewind (FILE *f);
|
||||||
|
int f_flush (FILE *f);
|
||||||
|
void f_shutdown ();
|
||||||
|
|
||||||
|
#endif
|
|
@ -9,6 +9,7 @@
|
||||||
#include "pc/lua/utils/smlua_level_utils.h"
|
#include "pc/lua/utils/smlua_level_utils.h"
|
||||||
#include "pc/lua/utils/smlua_anim_utils.h"
|
#include "pc/lua/utils/smlua_anim_utils.h"
|
||||||
#include "pc/djui/djui.h"
|
#include "pc/djui/djui.h"
|
||||||
|
#include "pc/fs/fmem.h"
|
||||||
|
|
||||||
lua_State* gLuaState = NULL;
|
lua_State* gLuaState = NULL;
|
||||||
u8 gLuaInitializingScript = 0;
|
u8 gLuaInitializingScript = 0;
|
||||||
|
@ -81,28 +82,30 @@ void smlua_exec_str(const char* str) {
|
||||||
#define LUA_BOM_19 0x4077280000000000llu
|
#define LUA_BOM_19 0x4077280000000000llu
|
||||||
|
|
||||||
static bool smlua_check_binary_header(struct ModFile *file) {
|
static bool smlua_check_binary_header(struct ModFile *file) {
|
||||||
FILE *f = fopen(file->cachedPath, "rb");
|
FILE *f = f_open_r(file->cachedPath);
|
||||||
if (f) {
|
if (f) {
|
||||||
|
|
||||||
// Read signature
|
// Read signature
|
||||||
char signature[sizeof(LUA_SIGNATURE)] = { 0 };
|
char signature[sizeof(LUA_SIGNATURE)] = { 0 };
|
||||||
if (fread(signature, 1, sizeof(LUA_SIGNATURE) - 1, f) != sizeof(LUA_SIGNATURE) - 1) {
|
if (f_read(signature, 1, sizeof(LUA_SIGNATURE) - 1, f) != sizeof(LUA_SIGNATURE) - 1) {
|
||||||
LOG_LUA("Failed to load lua script '%s': File too short.", file->cachedPath);
|
LOG_LUA("Failed to load lua script '%s': File too short.", file->cachedPath);
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check signature
|
// Check signature
|
||||||
if (strcmp(signature, LUA_SIGNATURE) != 0) {
|
if (strcmp(signature, LUA_SIGNATURE) != 0) {
|
||||||
fclose(f);
|
f_close(f);
|
||||||
return true; // Not a binary lua
|
return true; // Not a binary lua
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read version number
|
// Read version number
|
||||||
u8 version;
|
u8 version;
|
||||||
if (fread(&version, 1, 1, f) != 1) {
|
if (f_read(&version, 1, 1, f) != 1) {
|
||||||
LOG_LUA("Failed to load lua script '%s': File too short.", file->cachedPath);
|
LOG_LUA("Failed to load lua script '%s': File too short.", file->cachedPath);
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,15 +113,17 @@ static bool smlua_check_binary_header(struct ModFile *file) {
|
||||||
u8 expectedVersion = strtoul(LUA_VERSION_MAJOR LUA_VERSION_MINOR, NULL, 16);
|
u8 expectedVersion = strtoul(LUA_VERSION_MAJOR LUA_VERSION_MINOR, NULL, 16);
|
||||||
if (version != expectedVersion) {
|
if (version != expectedVersion) {
|
||||||
LOG_LUA("Failed to load lua script '%s': Lua versions don't match (%X, expected %X).", file->cachedPath, version, expectedVersion);
|
LOG_LUA("Failed to load lua script '%s': Lua versions don't match (%X, expected %X).", file->cachedPath, version, expectedVersion);
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the rest of the header
|
// Read the rest of the header
|
||||||
u8 header[28];
|
u8 header[28];
|
||||||
if (fread(header, 1, 28, f) != 28) {
|
if (f_read(header, 1, 28, f) != 28) {
|
||||||
LOG_LUA("Failed to load lua script '%s': File too short.", file->cachedPath);
|
LOG_LUA("Failed to load lua script '%s': File too short.", file->cachedPath);
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,12 +134,14 @@ static bool smlua_check_binary_header(struct ModFile *file) {
|
||||||
u64 bom19 = *((u64 *) (header + 20));
|
u64 bom19 = *((u64 *) (header + 20));
|
||||||
if (bom11 != LUA_BOM_11) {
|
if (bom11 != LUA_BOM_11) {
|
||||||
LOG_ERROR("Failed to load lua script '%s': BOM at offset 0x11 don't match (%016llX, expected %016llX).", file->cachedPath, bom11, LUA_BOM_11);
|
LOG_ERROR("Failed to load lua script '%s': BOM at offset 0x11 don't match (%016llX, expected %016llX).", file->cachedPath, bom11, LUA_BOM_11);
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (bom19 != LUA_BOM_19) {
|
if (bom19 != LUA_BOM_19) {
|
||||||
LOG_ERROR("Failed to load lua script '%s': BOM at offset 0x19 don't match (%016llX, expected %016llX).", file->cachedPath, bom19, LUA_BOM_19);
|
LOG_ERROR("Failed to load lua script '%s': BOM at offset 0x19 don't match (%016llX, expected %016llX).", file->cachedPath, bom19, LUA_BOM_19);
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,33 +153,37 @@ static bool smlua_check_binary_header(struct ModFile *file) {
|
||||||
u8 sizeOfLuaNumber = header[11];
|
u8 sizeOfLuaNumber = header[11];
|
||||||
if (sizeOfCInteger != sizeof(int)) {
|
if (sizeOfCInteger != sizeof(int)) {
|
||||||
LOG_ERROR("Failed to load lua script '%s': sizes of C Integer don't match (%d, expected %llu).", file->cachedPath, sizeOfCInteger, (long long unsigned)sizeof(int));
|
LOG_ERROR("Failed to load lua script '%s': sizes of C Integer don't match (%d, expected %llu).", file->cachedPath, sizeOfCInteger, (long long unsigned)sizeof(int));
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (sizeOfCPointer != sizeof(void *)) { // 4 for 32-bit architectures, 8 for 64-bit
|
if (sizeOfCPointer != sizeof(void *)) { // 4 for 32-bit architectures, 8 for 64-bit
|
||||||
LOG_ERROR("Failed to load lua script '%s': sizes of C Pointer don't match (%d, expected %llu).", file->cachedPath, sizeOfCPointer, (long long unsigned)sizeof(void *));
|
LOG_ERROR("Failed to load lua script '%s': sizes of C Pointer don't match (%d, expected %llu).", file->cachedPath, sizeOfCPointer, (long long unsigned)sizeof(void *));
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (sizeOfCFloat != sizeof(float)) {
|
if (sizeOfCFloat != sizeof(float)) {
|
||||||
LOG_ERROR("Failed to load lua script '%s': sizes of C Float don't match (%d, expected %llu).", file->cachedPath, sizeOfCFloat, (long long unsigned)sizeof(float));
|
LOG_ERROR("Failed to load lua script '%s': sizes of C Float don't match (%d, expected %llu).", file->cachedPath, sizeOfCFloat, (long long unsigned)sizeof(float));
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (sizeOfLuaInteger != sizeof(LUA_INTEGER)) {
|
if (sizeOfLuaInteger != sizeof(LUA_INTEGER)) {
|
||||||
LOG_ERROR("Failed to load lua script '%s': sizes of Lua Integer don't match (%d, expected %llu).", file->cachedPath, sizeOfLuaInteger, (long long unsigned)sizeof(LUA_INTEGER));
|
LOG_ERROR("Failed to load lua script '%s': sizes of Lua Integer don't match (%d, expected %llu).", file->cachedPath, sizeOfLuaInteger, (long long unsigned)sizeof(LUA_INTEGER));
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (sizeOfLuaNumber != sizeof(LUA_NUMBER)) {
|
if (sizeOfLuaNumber != sizeof(LUA_NUMBER)) {
|
||||||
LOG_ERROR("Failed to load lua script '%s': sizes of Lua Number don't match (%d, expected %llu).", file->cachedPath, sizeOfLuaNumber, (long long unsigned)sizeof(LUA_NUMBER));
|
LOG_ERROR("Failed to load lua script '%s': sizes of Lua Number don't match (%d, expected %llu).", file->cachedPath, sizeOfLuaNumber, (long long unsigned)sizeof(LUA_NUMBER));
|
||||||
fclose(f);
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All's good
|
// All's good
|
||||||
LOG_INFO("Loading lua script '%s'", file->cachedPath);
|
f_close(f);
|
||||||
fclose(f);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOG_LUA("Failed to load lua script '%s': File not found.", file->cachedPath);
|
LOG_LUA("Failed to load lua script '%s': File not found.", file->cachedPath);
|
||||||
|
@ -190,13 +201,40 @@ static void smlua_load_script(struct Mod* mod, struct ModFile* file, u16 remoteI
|
||||||
gLuaInitializingScript = 1;
|
gLuaInitializingScript = 1;
|
||||||
LOG_INFO("Loading lua script '%s'", file->cachedPath);
|
LOG_INFO("Loading lua script '%s'", file->cachedPath);
|
||||||
|
|
||||||
if (luaL_loadfile(L, file->cachedPath) != LUA_OK) { // only run on success
|
FILE *f = f_open_r(file->cachedPath);
|
||||||
LOG_LUA("Failed to load lua script '%s'.", file->cachedPath);
|
if (!f) {
|
||||||
LOG_LUA("%s", smlua_to_string(L, lua_gettop(L)));
|
LOG_LUA("Failed to load lua script '%s': File not found.", file->cachedPath);
|
||||||
gLuaInitializingScript = 0;
|
gLuaInitializingScript = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f_seek(f, 0, SEEK_END);
|
||||||
|
size_t length = f_tell(f);
|
||||||
|
char *buffer = calloc(length + 1, 1);
|
||||||
|
if (!buffer) {
|
||||||
|
LOG_LUA("Failed to load lua script '%s': Cannot allocate buffer.", file->cachedPath);
|
||||||
|
gLuaInitializingScript = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_rewind(f);
|
||||||
|
if (f_read(buffer, 1, length, f) < length) {
|
||||||
|
LOG_LUA("Failed to load lua script '%s': Unexpected early end of file.", file->cachedPath);
|
||||||
|
gLuaInitializingScript = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
|
|
||||||
|
if (luaL_loadstring(L, buffer) != LUA_OK) { // only run on success
|
||||||
|
LOG_LUA("Failed to load lua script '%s'.", file->cachedPath);
|
||||||
|
LOG_LUA("%s", smlua_to_string(L, lua_gettop(L)));
|
||||||
|
gLuaInitializingScript = 0;
|
||||||
|
free(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
// check if this is the first time this mod has been loaded
|
// check if this is the first time this mod has been loaded
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath);
|
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath);
|
||||||
bool firstInit = (lua_type(L, -1) == LUA_TNIL);
|
bool firstInit = (lua_type(L, -1) == LUA_TNIL);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "pc/utils/misc.h"
|
#include "pc/utils/misc.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
#include "pc/pc_main.h"
|
#include "pc/pc_main.h"
|
||||||
|
#include "pc/fs/fmem.h"
|
||||||
#include "audio/external.h"
|
#include "audio/external.h"
|
||||||
|
|
||||||
struct AudioOverride {
|
struct AudioOverride {
|
||||||
|
@ -81,22 +82,24 @@ bool smlua_audio_utils_override(u8 sequenceId, s32* bankId, void** seqData) {
|
||||||
static u8* buffer = NULL;
|
static u8* buffer = NULL;
|
||||||
static long int length = 0;
|
static long int length = 0;
|
||||||
|
|
||||||
FILE* fp = fopen(override->filename, "rb");
|
FILE* fp = f_open_r(override->filename);
|
||||||
if (!fp) { return false; }
|
if (!fp) { return false; }
|
||||||
fseek(fp, 0L, SEEK_END);
|
f_seek(fp, 0L, SEEK_END);
|
||||||
length = ftell(fp);
|
length = f_tell(fp);
|
||||||
|
|
||||||
buffer = malloc(length+1);
|
buffer = malloc(length+1);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
LOG_ERROR("Failed to malloc m64 sound file");
|
LOG_ERROR("Failed to malloc m64 sound file");
|
||||||
fclose(fp);
|
f_close(fp);
|
||||||
|
f_delete(fp);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(fp, 0L, SEEK_SET);
|
f_seek(fp, 0L, SEEK_SET);
|
||||||
fread(buffer, length, 1, fp);
|
f_read(buffer, length, 1, fp);
|
||||||
|
|
||||||
fclose(fp);
|
f_close(fp);
|
||||||
|
f_delete(fp);
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
override->loaded = true;
|
override->loaded = true;
|
||||||
|
@ -251,12 +254,53 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) {
|
||||||
audio->file = modFile;
|
audio->file = modFile;
|
||||||
|
|
||||||
// load audio
|
// load audio
|
||||||
ma_result result = ma_sound_init_from_file(
|
FILE *f = f_open_r(modFile->cachedPath);
|
||||||
&gModAudioEngine, modFile->cachedPath,
|
if (!f) {
|
||||||
|
LOG_ERROR("failed to load audio file '%s': file not found", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_seek(f, 0, SEEK_END);
|
||||||
|
u32 size = f_tell(f);
|
||||||
|
f_rewind(f);
|
||||||
|
void *buffer = calloc(size, 1);
|
||||||
|
if (!buffer) {
|
||||||
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
|
LOG_ERROR("failed to load audio file '%s': cannot allocate buffer of size: %d", filename, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the audio buffer
|
||||||
|
if (f_read(buffer, 1, size, f) < size) {
|
||||||
|
free(buffer);
|
||||||
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
|
LOG_ERROR("failed to load audio file '%s': cannot read audio buffer of size: %d", filename, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
f_close(f);
|
||||||
|
f_delete(f);
|
||||||
|
|
||||||
|
// decode the audio buffer
|
||||||
|
// note: buffer and decoder are not freed after a successful call, because ma_decoder_init_memory() does not make copies of them
|
||||||
|
ma_decoder *decoder = calloc(1, sizeof(ma_decoder));
|
||||||
|
ma_result result = ma_decoder_init_memory(buffer, size, NULL, decoder);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
free(decoder);
|
||||||
|
free(buffer);
|
||||||
|
LOG_ERROR("failed to load audio file '%s': failed to decode raw audio: %d", filename, result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ma_sound_init_from_data_source(
|
||||||
|
&gModAudioEngine, decoder,
|
||||||
isStream ? MA_SOUND_STREAM_FLAGS : MA_SOUND_SAMPLE_FLAGS,
|
isStream ? MA_SOUND_STREAM_FLAGS : MA_SOUND_SAMPLE_FLAGS,
|
||||||
NULL, NULL, &audio->sound
|
NULL, &audio->sound
|
||||||
);
|
);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
|
free(decoder);
|
||||||
|
free(buffer);
|
||||||
LOG_ERROR("failed to load audio file '%s': %d", filename, result);
|
LOG_ERROR("failed to load audio file '%s': %d", filename, result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "pc/utils/misc.h"
|
#include "pc/utils/misc.h"
|
||||||
#include "pc/utils/md5.h"
|
#include "pc/utils/md5.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
|
#include "pc/fs/fmem.h"
|
||||||
|
|
||||||
size_t mod_get_lua_size(struct Mod* mod) {
|
size_t mod_get_lua_size(struct Mod* mod) {
|
||||||
if (!mod) { return 0; }
|
if (!mod) { return 0; }
|
||||||
|
@ -171,7 +172,8 @@ void mod_clear(struct Mod* mod) {
|
||||||
for (int j = 0; j < mod->fileCount; j++) {
|
for (int j = 0; j < mod->fileCount; j++) {
|
||||||
struct ModFile* file = &mod->files[j];
|
struct ModFile* file = &mod->files[j];
|
||||||
if (file->fp != NULL) {
|
if (file->fp != NULL) {
|
||||||
fclose(file->fp);
|
f_close(file->fp);
|
||||||
|
f_delete(file->fp);
|
||||||
file->fp = NULL;
|
file->fp = NULL;
|
||||||
}
|
}
|
||||||
if (file->cachedPath != NULL) {
|
if (file->cachedPath != NULL) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "data/dynos.c.h"
|
#include "data/dynos.c.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
#include "pc/loading.h"
|
#include "pc/loading.h"
|
||||||
|
#include "pc/fs/fmem.h"
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -322,7 +323,8 @@ void mods_clear(struct Mods* mods) {
|
||||||
for (int j = 0; j < mod->fileCount; j++) {
|
for (int j = 0; j < mod->fileCount; j++) {
|
||||||
struct ModFile* file = &mod->files[j];
|
struct ModFile* file = &mod->files[j];
|
||||||
if (file->fp != NULL) {
|
if (file->fp != NULL) {
|
||||||
fclose(file->fp);
|
f_close(file->fp);
|
||||||
|
f_delete(file->fp);
|
||||||
file->fp = NULL;
|
file->fp = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
#include "pc/pc_main.h"
|
#include "pc/pc_main.h"
|
||||||
#include "pc/gfx/gfx_pc.h"
|
#include "pc/gfx/gfx_pc.h"
|
||||||
|
#include "pc/fs/fmem.h"
|
||||||
#include "game/camera.h"
|
#include "game/camera.h"
|
||||||
#include "game/skybox.h"
|
#include "game/skybox.h"
|
||||||
#include "game/object_list_processor.h"
|
#include "game/object_list_processor.h"
|
||||||
|
@ -726,6 +727,7 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup, bool reconnect
|
||||||
save_file_load_all(TRUE);
|
save_file_load_all(TRUE);
|
||||||
extern void save_file_set_using_backup_slot(bool usingBackupSlot);
|
extern void save_file_set_using_backup_slot(bool usingBackupSlot);
|
||||||
save_file_set_using_backup_slot(false);
|
save_file_set_using_backup_slot(false);
|
||||||
|
f_shutdown();
|
||||||
|
|
||||||
extern s16 gMenuMode;
|
extern s16 gMenuMode;
|
||||||
gMenuMode = -1;
|
gMenuMode = -1;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "pc/djui/djui_panel_join_message.h"
|
#include "pc/djui/djui_panel_join_message.h"
|
||||||
//#define DISABLE_MODULE_LOG 1
|
//#define DISABLE_MODULE_LOG 1
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
|
#include "pc/fs/fmem.h"
|
||||||
|
|
||||||
#define CHUNK_SIZE 800
|
#define CHUNK_SIZE 800
|
||||||
#define OFFSET_COUNT 50
|
#define OFFSET_COUNT 50
|
||||||
|
@ -191,8 +192,8 @@ static void network_update_offset_groups(void) {
|
||||||
for (u64 fileIndex = 0; fileIndex < mod->fileCount; fileIndex++) {
|
for (u64 fileIndex = 0; fileIndex < mod->fileCount; fileIndex++) {
|
||||||
struct ModFile* modFile = &mod->files[fileIndex];
|
struct ModFile* modFile = &mod->files[fileIndex];
|
||||||
if (modFile->fp == NULL) { continue; }
|
if (modFile->fp == NULL) { continue; }
|
||||||
fflush(modFile->fp);
|
f_flush(modFile->fp);
|
||||||
fclose(modFile->fp);
|
f_close(modFile->fp);
|
||||||
modFile->fp = NULL;
|
modFile->fp = NULL;
|
||||||
}
|
}
|
||||||
mod->enabled = true;
|
mod->enabled = true;
|
||||||
|
@ -315,6 +316,18 @@ after_filled:;
|
||||||
//LOG_INFO("Sent chunk: offset %llu, length %llu", requestOffset, chunkFill);
|
//LOG_INFO("Sent chunk: offset %llu, length %llu", requestOffset, chunkFill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache any mod that doesn't have "(wip)" or "[wip]" in its name (case-insensitive)
|
||||||
|
static bool should_cache_mod(struct Mod *mod) {
|
||||||
|
char *modName = sys_strdup(mod->name);
|
||||||
|
sys_strlwr(modName);
|
||||||
|
bool shouldCache = (
|
||||||
|
!strstr(modName, "(wip)") &&
|
||||||
|
!strstr(modName, "[wip]")
|
||||||
|
);
|
||||||
|
free(modName);
|
||||||
|
return shouldCache;
|
||||||
|
}
|
||||||
|
|
||||||
static void open_mod_file(struct Mod* mod, struct ModFile* file) {
|
static void open_mod_file(struct Mod* mod, struct ModFile* file) {
|
||||||
if (file->fp != NULL) {
|
if (file->fp != NULL) {
|
||||||
return;
|
return;
|
||||||
|
@ -326,10 +339,13 @@ static void open_mod_file(struct Mod* mod, struct ModFile* file) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_file_create_directories(mod, file);
|
|
||||||
|
|
||||||
file->wroteBytes = 0;
|
file->wroteBytes = 0;
|
||||||
file->fp = fopen(fullPath, "wb");
|
if (should_cache_mod(mod)) {
|
||||||
|
mod_file_create_directories(mod, file);
|
||||||
|
file->fp = fopen(fullPath, "wb");
|
||||||
|
} else {
|
||||||
|
file->fp = f_open_w(fullPath);
|
||||||
|
}
|
||||||
if (file->fp == NULL) {
|
if (file->fp == NULL) {
|
||||||
LOG_ERROR("unable to open for write: '%s' - '%s'", fullPath, strerror(errno));
|
LOG_ERROR("unable to open for write: '%s' - '%s'", fullPath, strerror(errno));
|
||||||
return;
|
return;
|
||||||
|
@ -430,14 +446,22 @@ after_group:;
|
||||||
LOG_ERROR("Failed to open file for download write: %s", modFile->cachedPath);
|
LOG_ERROR("Failed to open file for download write: %s", modFile->cachedPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fseek(modFile->fp, fileWriteOffset, SEEK_SET);
|
f_seek(modFile->fp, fileWriteOffset, SEEK_SET);
|
||||||
fwrite(&chunk[chunkPour], sizeof(u8), fileWriteLength, modFile->fp);
|
f_write(&chunk[chunkPour], sizeof(u8), fileWriteLength, modFile->fp);
|
||||||
modFile->wroteBytes += fileWriteLength;
|
modFile->wroteBytes += fileWriteLength;
|
||||||
|
|
||||||
if (modFile->wroteBytes >= modFile->size) {
|
if (modFile->wroteBytes >= modFile->size) {
|
||||||
fflush(modFile->fp);
|
f_flush(modFile->fp);
|
||||||
fclose(modFile->fp);
|
f_close(modFile->fp);
|
||||||
modFile->fp = NULL;
|
modFile->fp = NULL;
|
||||||
|
|
||||||
|
// Write cachedPath here so the file doesn't end up in mod.cache
|
||||||
|
if (!should_cache_mod(mod)) {
|
||||||
|
char modFilePath[SYS_MAX_PATH] = { 0 };
|
||||||
|
concat_path(modFilePath, mod->basePath, modFile->relativePath);
|
||||||
|
normalize_path(modFilePath);
|
||||||
|
modFile->cachedPath = strdup(modFilePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wroteBytes += fileWriteLength;
|
wroteBytes += fileWriteLength;
|
||||||
|
|
Loading…
Reference in a new issue