fix xm and add resource

This commit is contained in:
NishiOwO 2025-04-21 13:48:51 +09:00
parent 85cc050bbb
commit ea81776b1b
No known key found for this signature in database
GPG Key ID: 27EF69B208EB9343
11 changed files with 459 additions and 11 deletions

View File

@ -1355,15 +1355,18 @@ mulong jar_mod_current_samples(jar_mod_context_t* modctx) {
/* Works, however it is very slow, this data should be cached to ensure it is run only once per file */
mulong jar_mod_max_samples(jar_mod_context_t* ctx) {
mulong len;
mulong lastcount = ctx->loopcount;
mulong lastcount = ctx->loopcount;
mulong samplenb = ctx->samplenb;
muint tablepos = ctx->tablepos;
muint patternpos = ctx->patternpos;
while(ctx->loopcount <= lastcount) jar_mod_fillbuffer(ctx, NULL, 1, 0);
len = ctx->samplenb;
jar_mod_seek_start(ctx);
ctx->samplenb = 0;
ctx->tablepos = 0;
ctx->patternpos = 0;
ctx->samplenb = samplenb;
ctx->tablepos = tablepos;
ctx->patternpos = patternpos;
return len;
}

View File

@ -2454,8 +2454,11 @@ void jar_xm_generate_samples(jar_xm_context_t* ctx, float* output, size_t numsam
}
gf_uint64_t jar_xm_get_remaining_samples(jar_xm_context_t* ctx) {
gf_uint64_t total = 0;
gf_uint8_t currentLoopCount = jar_xm_get_loop_count(ctx);
gf_uint64_t total = 0;
gf_uint8_t currentLoopCount = jar_xm_get_loop_count(ctx);
gf_uint8_t current_tick = ctx->current_tick;
gf_uint8_t current_row = ctx->current_row;
gf_uint8_t current_table_index = ctx->current_table_index;
jar_xm_set_max_loop_count(ctx, 0);
while(jar_xm_get_loop_count(ctx) == currentLoopCount) {
@ -2464,7 +2467,10 @@ gf_uint64_t jar_xm_get_remaining_samples(jar_xm_context_t* ctx) {
jar_xm_tick(ctx);
}
ctx->loop_count = currentLoopCount;
ctx->loop_count = currentLoopCount;
ctx->current_tick = current_tick;
ctx->current_row = current_row;
ctx->current_table_index = current_table_index;
return total;
}

View File

@ -129,6 +129,14 @@
#define GF_EXPOSE_AUDIO
#endif
#ifndef GF_EXPOSE_RESOURCE
/**
* @~english
* @brief Expose resource properties
*/
#define GF_EXPOSE_RESOURCE
#endif
#ifndef GF_EXPOSE_GRAPHIC
/**
* @~english

View File

@ -0,0 +1,49 @@
/**
* @file gf_resource.h
* @~english
* @brief Resource
*/
#ifndef __GF_RESOURCE_H__
#define __GF_RESOURCE_H__
#include <gf_pre.h>
#include <gf_macro.h>
/* Type */
#include <gf_type/resource.h>
/* Engine */
#include <gf_type/core.h>
/* Standard */
#include <stddef.h>
/**
* @~english
* @brief Create resource
* @param engine Engine instance
* @param path Path
* @return Resource
*/
GF_EXPORT gf_resource_t* gf_resource_create(gf_engine_t* engine, const char* path);
/**
* @~english
* @brief Destroy resource
* @param resource Resource
*/
GF_EXPORT void gf_resource_destroy(gf_resource_t* resource);
/**
* @~english
* @brief Get data from resource
* @param resource Resource
* @param name Entry name
* @param data Pointer to data result
* @param size Pointer to size result
* @return `0` if successful, otherwise `-1`
*/
GF_EXPORT int gf_resource_get(gf_resource_t* resource, const char* name, void** data, size_t* size);
#endif

View File

@ -0,0 +1,71 @@
/**
* @file gf_type/resource.h
* @~english
* @brief Type definitions related to resource
*/
#ifndef __GF_TYPE_RESOURCE_H__
#define __GF_TYPE_RESOURCE_H__
#include <gf_pre.h>
#include <gf_macro.h>
#ifdef GF_EXPOSE_RESOURCE
typedef struct gf_resource_t gf_resource_t;
/* External library */
/* Engine */
#include <gf_type/core.h>
/* Standard */
#include <stdio.h>
/**
* @struct gf_resource_entry_t
* @~english
* @brief Resource entry
*
* @var gf_resource_entry_t::key
* @brief Entry name
*
* @var gf_resource_entry_t::address
* @brief Location in file
*
* @var gf_resource_entry_t::address
* @brief Location in file
*
* @var gf_resource_entry_t::size
* @brief Size
*/
GF_DECLARE_TYPE(resource_entry, {
char* key;
unsigned int address;
unsigned int size;
});
/**
* @struct gf_resource_t
* @~english
* @brief Resource
*
* @var gf_resource_t::engine
* @brief Engine instance
*
* @var gf_resource_t::entries
* @brief Resource entries
*
* @var gf_resource_t::data
* @brief Data
*/
GF_DECLARE_TYPE(resource, {
gf_engine_t* engine;
gf_resource_entry_t* entries;
unsigned char* data;
});
#else
typedef void gf_resource_entry_t;
typedef void gf_resource_t;
#endif
#endif

189
engine/src/gf_resource.c Normal file
View File

@ -0,0 +1,189 @@
#define GF_EXPOSE_RESOURCE
#include <gf_pre.h>
/* External library */
#include <stb_ds.h>
#include <zlib.h>
/* Interface */
#include <gf_resource.h>
/* Engine */
#include <gf_core.h>
#include <gf_log.h>
/* Standard */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#pragma pack(1)
struct tar_header {
char filename[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag[1];
char linkname[100];
char ustar[6];
char ustarv[2];
char username[32];
char grpname[32];
char devmajor[8];
char devminor[8];
char prefix[155];
};
#pragma pack()
unsigned int tar_getsize(const char* input) {
int i;
unsigned int r = 0;
for(i = 0; i < 11; i++) {
r = r << 3;
r = r | (input[i] - '0');
}
return r;
}
gf_resource_t* gf_resource_create(gf_engine_t* engine, const char* path) {
struct tar_header* th;
int i;
unsigned int cmpsize = 0;
unsigned int cursize = 0;
unsigned int curseek = 0;
z_stream stream;
int ret;
FILE* f;
gf_resource_t* resource = malloc(sizeof(*resource));
memset(resource, 0, sizeof(*resource));
resource->engine = engine;
resource->entries = NULL;
resource->data = NULL;
sh_new_strdup(resource->entries);
if(path == NULL) {
gf_log_function(engine, "Created empty resource", "");
return resource;
}
f = fopen(path, "rb");
if(f == NULL) {
gf_log_function(engine, "Failed to create resource", "");
gf_resource_destroy(resource);
return NULL;
}
fseek(f, 0, SEEK_END);
cmpsize = ftell(f);
fseek(f, 0, SEEK_SET);
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = 0;
stream.next_in = Z_NULL;
if(inflateInit(&stream) != Z_OK) {
gf_log_function(engine, "Failed to initialize zlib", "");
gf_resource_destroy(resource);
return NULL;
}
gf_log_function(engine, "Created resource", "");
do {
unsigned char in[32767];
unsigned char out[32767];
stream.avail_in = fread(in, 1, sizeof(in), f);
if(stream.avail_in == 0) break;
stream.next_in = in;
do {
int have;
stream.avail_out = sizeof(out);
stream.next_out = out;
ret = inflate(&stream, Z_NO_FLUSH);
if(ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
inflateEnd(&stream);
gf_log_function(engine, "Failed to decompress", "");
gf_resource_destroy(resource);
return NULL;
}
have = sizeof(out) - stream.avail_out;
if(resource->data == NULL) {
resource->data = malloc(have);
memcpy(resource->data, out, have);
} else {
unsigned char* old = resource->data;
resource->data = malloc(cursize + have);
memcpy(resource->data, old, cursize);
memcpy(resource->data + cursize, out, have);
free(old);
}
cursize += have;
} while(stream.avail_out == 0);
} while(ret != Z_STREAM_END);
inflateEnd(&stream);
fclose(f);
gf_log_function(engine, "Compression made the file size %.2f%%", (double)cmpsize / cursize * 100);
for(i = 0;; i++) {
unsigned int sz;
gf_resource_entry_t entry;
th = (struct tar_header*)(resource->data + curseek);
if(th->filename[0] == 0) break;
curseek += 512;
if(memcmp(th->ustar, "ustar", 6) != 0) {
gf_log_function(engine, "Not USTAR", "");
gf_resource_destroy(resource);
resource = NULL;
break;
}
sz = tar_getsize(&th->size[0]);
gf_log_function(engine, "%s: %u bytes", th->filename, sz);
entry.key = th->filename;
entry.address = curseek;
entry.size = sz;
shputs(resource->entries, entry);
if(sz != 0) curseek += ((sz / 512) + 1) * 512;
}
return resource;
}
int gf_resource_get(gf_resource_t* resource, const char* name, void** data, size_t* size) {
if(resource->entries != NULL && shgeti(resource->entries, name) != -1) {
gf_resource_entry_t e = shgets(resource->entries, name);
*size = e.size;
*data = malloc(e.size);
memcpy(*data, resource->data + e.address, e.size);
return 0;
}
return -1;
}
void gf_resource_destroy(gf_resource_t* resource) {
if(resource->entries != NULL) {
shfree(resource->entries);
}
if(resource->data != NULL) {
free(resource->data);
}
gf_log_function(resource->engine, "Destroyed resource", "");
free(resource);
}

2
engine/src/gf_stb_ds.c Normal file
View File

@ -0,0 +1,2 @@
#define STB_DS_IMPLEMENTATION
#include <stb_ds.h>

View File

@ -1,8 +1,117 @@
/* Engine */
#include <gf_version.h>
#include <gf_resource.h>
/* External library */
/* Standard */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <windows.h>
#define gf_stat _stat
#else
#include <dirent.h>
#define gf_stat stat
#endif
int main(int argc, char** argv) { return 0; }
char* out = NULL;
char* base = ".";
int add_all(gf_resource_t* resource, char* path) {
#ifdef _WIN32
#else
DIR* dir;
struct dirent* d;
#endif
int st = 0;
char* op = malloc(strlen(base) + 1 + strlen(path) + 1);
op[0] = 0;
strcat(op, base);
strcat(op, "/");
strcat(op, path);
#ifdef _WIN32
st = -1;
#else
dir = opendir(op);
if(dir == NULL) {
free(op);
fprintf(stderr, "Could not open directory\n");
return -1;
}
while((d = readdir(dir)) != NULL) {
if(strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
char* p = malloc(strlen(base) + 1 + strlen(path) + strlen(d->d_name) + 1);
char* np = malloc(strlen(path) + strlen(d->d_name) + 1 + 1);
struct gf_stat s;
p[0] = 0;
strcat(p, base);
strcat(p, "/");
strcat(p, path);
strcat(p, d->d_name);
np[0] = 0;
strcat(np, path);
strcat(np, d->d_name);
printf("%s\n", np);
gf_stat(p, &s);
if(S_ISDIR(s.st_mode)) {
strcat(np, "/");
if((st = add_all(resource, np)) != 0) {
free(np);
break;
}
} else {
}
free(np);
free(p);
}
}
closedir(dir);
#endif
free(op);
return st;
}
int main(int argc, char** argv) {
gf_version_t version;
gf_resource_t* resource;
int i;
int st = 0;
gf_version_get(&version);
printf("GoldFish Engine Resource Packer %s\n", version.full);
for(i = 1; i < argc; i++) {
if(argv[i][0] == '-') {
if(strcmp(argv[i], "-d") == 0) {
base = argv[++i];
} else {
fprintf(stderr, "Invalid flag: %s\n", argv[i]);
return 1;
}
} else {
out = argv[i];
}
}
if(out == NULL || base == NULL) {
fprintf(stderr, "Usage: %s [-d basedir] output\n", argv[0]);
return 1;
}
resource = gf_resource_create(NULL, NULL);
if(resource != NULL) {
if(add_all(resource, "") != 0) {
st = 1;
}
gf_resource_destroy(resource);
}
return st;
}

View File

@ -1,14 +1,18 @@
project("Pack")
kind("ConsoleApp")
filter({})
language("C")
targetdir("../bin/%{cfg.buildcfg}/%{cfg.platform}")
objdir("../obj")
targetname("pack")
includedirs({
"../include"
})
files({
"pack/*.c"
})
-- Call this if you are gonna use my engine...
links({
"GoldFish"
})
gf_link_stuffs("options:engine=static")
filter("system:windows")
files({
@ -56,7 +60,6 @@ project("EngineInfo")
links({
"GoldFish"
})
-- Call this if you are gonna use my engine...
gf_link_stuffs("options:engine=static")
filter("system:windows")
files({

8
tool/respack.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
old="`pwd`"
rm -rf /tmp/respack
mkdir -p /tmp/respack
cp -rf music /tmp/respack/music
exec ./engine/bin/*/*/pack -d /tmp/respack resource.pak