mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-05 05:17:59 +03:00
Use abstract archive interface for ALD files
In preparation for AFA support in libsystem4.
This commit is contained in:
+4
-47
@@ -24,23 +24,13 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "system4/archive.h"
|
||||
|
||||
#define ALD_FILEMAX 255
|
||||
#define ALD_DATAMAX 65535
|
||||
|
||||
enum ald_error {
|
||||
ALD_SUCCESS,
|
||||
ALD_FILE_ERROR,
|
||||
ALD_BAD_ARCHIVE_ERROR,
|
||||
ALD_MAX_ERROR
|
||||
};
|
||||
|
||||
enum {
|
||||
ALD_MMAP = 1
|
||||
};
|
||||
|
||||
struct ald_archive {
|
||||
bool mmapped;
|
||||
struct archive ar;
|
||||
int nr_files;
|
||||
struct {
|
||||
uint8_t *data;
|
||||
@@ -57,14 +47,6 @@ struct ald_archive {
|
||||
int *fileptr[ALD_FILEMAX];
|
||||
};
|
||||
|
||||
struct archive_data {
|
||||
size_t size;
|
||||
uint8_t *data;
|
||||
uint8_t *data_raw;
|
||||
char *name;
|
||||
struct ald_archive *archive;
|
||||
};
|
||||
|
||||
enum {
|
||||
ALDFILE_BGM,
|
||||
ALDFILE_CG,
|
||||
@@ -72,36 +54,11 @@ enum {
|
||||
ALDFILETYPE_MAX
|
||||
};
|
||||
|
||||
struct ald_archive *ald[ALDFILETYPE_MAX];
|
||||
|
||||
/*
|
||||
* Returns a human readable description of an error.
|
||||
*/
|
||||
const char *ald_strerror(int error);
|
||||
struct archive *ald[ALDFILETYPE_MAX];
|
||||
|
||||
/*
|
||||
* Open an ALD archive.
|
||||
*/
|
||||
struct ald_archive *ald_open(char **files, int count, int flags, int *error);
|
||||
|
||||
/*
|
||||
* Check if data exists in an ALD archive.
|
||||
*/
|
||||
bool ald_data_exists(struct ald_archive *ar, int no);
|
||||
|
||||
/*
|
||||
* Retrieve a piece of data from an ALD archive.
|
||||
*/
|
||||
struct archive_data *ald_get(struct ald_archive *archive, int no);
|
||||
|
||||
/*
|
||||
* Free an ald_data structure returned by `ald_get`.
|
||||
*/
|
||||
void ald_free_data(struct archive_data *data);
|
||||
|
||||
/*
|
||||
* Free an ald_archive structure returned by `ald_open`.
|
||||
*/
|
||||
void ald_free_archive(struct ald_archive *ar);
|
||||
struct archive *ald_open(char **files, int count, int flags, int *error);
|
||||
|
||||
#endif /* SYSTEM4_ALD_H */
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM4_ARCHIVE_H
|
||||
#define SYSTEM4_ARCHIVE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum ald_error {
|
||||
ARCHIVE_SUCCESS,
|
||||
ARCHIVE_FILE_ERROR,
|
||||
ARCHIVE_BAD_ARCHIVE_ERROR,
|
||||
ARCHIVE_MAX_ERROR
|
||||
};
|
||||
|
||||
enum {
|
||||
ARCHIVE_MMAP = 1
|
||||
};
|
||||
|
||||
struct archive {
|
||||
bool mmapped;
|
||||
struct archive_ops *ops;
|
||||
};
|
||||
|
||||
struct archive_ops {
|
||||
bool (*exists)(struct archive *ar, int no);
|
||||
struct archive_data *(*get)(struct archive *ar, int no);
|
||||
void (*free_data)(struct archive_data *data);
|
||||
void (*free)(struct archive *ar);
|
||||
};
|
||||
|
||||
struct archive_data {
|
||||
size_t size;
|
||||
uint8_t *data;
|
||||
uint8_t *data_raw;
|
||||
char *name;
|
||||
struct archive *archive;
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns a human readable description of an error.
|
||||
*/
|
||||
const char *archive_strerror(int error);
|
||||
|
||||
/*
|
||||
* Check if data exists in an archive.
|
||||
*/
|
||||
static inline bool archive_exists(struct archive *ar, int no)
|
||||
{
|
||||
return ar->ops->exists(ar, no);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a piece of data from an ALD archive.
|
||||
*/
|
||||
static inline struct archive_data *archive_get(struct archive *ar, int no)
|
||||
{
|
||||
return ar->ops->get(ar, no);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an archive_data structure returned by `archive_get`.
|
||||
*/
|
||||
static inline void archive_free_data(struct archive_data *data)
|
||||
{
|
||||
data->archive->ops->free_data(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an ald_archive structure returned by `ald_open`.
|
||||
*/
|
||||
static inline void archive_free(struct archive *ar)
|
||||
{
|
||||
ar->ops->free(ar);
|
||||
}
|
||||
|
||||
#endif /* SYSTEM4_ARCHIVE_H */
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct ald_archive;
|
||||
struct archive;
|
||||
|
||||
/*
|
||||
* Available CG formats
|
||||
@@ -53,8 +53,8 @@ struct cg {
|
||||
void *pixels;
|
||||
};
|
||||
|
||||
bool cg_get_metrics(struct ald_archive *ar, int no, struct cg_metrics *dst);
|
||||
struct cg *cg_load(struct ald_archive *ar, int no);
|
||||
bool cg_get_metrics(struct archive *ar, int no, struct cg_metrics *dst);
|
||||
struct cg *cg_load(struct archive *ar, int no);
|
||||
void cg_free(struct cg *cg);
|
||||
|
||||
#endif /* SYSTEM4_CG_H */
|
||||
|
||||
@@ -36,19 +36,17 @@
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
static const char *errtab[ALD_MAX_ERROR] = {
|
||||
[ALD_SUCCESS] = "Success",
|
||||
[ALD_FILE_ERROR] = "Error opening ALD file",
|
||||
[ALD_BAD_ARCHIVE_ERROR] = "Invalid ALD file"
|
||||
};
|
||||
static bool ald_exists(struct archive *ar, int no);
|
||||
static struct archive_data *ald_get(struct archive *ar, int no);
|
||||
static void ald_free_data(struct archive_data *data);
|
||||
static void ald_free(struct archive *ar);
|
||||
|
||||
/* Get a message describing an error. */
|
||||
const char *ald_strerror(int error)
|
||||
{
|
||||
if (error < ALD_MAX_ERROR)
|
||||
return errtab[error];
|
||||
return "Invalid error number";
|
||||
}
|
||||
struct archive_ops ald_archive_ops = {
|
||||
.exists = ald_exists,
|
||||
.get = ald_get,
|
||||
.free_data = ald_free_data,
|
||||
.free = ald_free,
|
||||
};
|
||||
|
||||
/* Get the size of a file in bytes. */
|
||||
static long get_file_size(FILE *fp)
|
||||
@@ -188,25 +186,26 @@ static int _ald_get(struct ald_archive *ar, int no, int *disk_out, int *dataptr_
|
||||
return dataptr2 - dataptr;
|
||||
}
|
||||
|
||||
bool ald_data_exists(struct ald_archive *ar, int no)
|
||||
static bool ald_exists(struct archive *ar, int no)
|
||||
{
|
||||
int disk, dataptr;
|
||||
return ar && !!_ald_get(ar, no, &disk, &dataptr);
|
||||
return ar && !!_ald_get((struct ald_archive*)ar, no, &disk, &dataptr);
|
||||
}
|
||||
|
||||
/* Get a piece of data from an ALD archive. */
|
||||
struct archive_data *ald_get(struct ald_archive *ar, int no)
|
||||
struct archive_data *ald_get(struct archive *_ar, int no)
|
||||
{
|
||||
if (!ar)
|
||||
if (!_ar)
|
||||
return NULL;
|
||||
|
||||
uint8_t *data;
|
||||
struct archive_data *dfile;
|
||||
int disk, dataptr, ptr, size;
|
||||
struct ald_archive *ar = (struct ald_archive*)_ar;
|
||||
int readsize = _ald_get(ar, no, &disk, &dataptr);
|
||||
|
||||
// get data top
|
||||
if (ar->mmapped) {
|
||||
if (ar->ar.mmapped) {
|
||||
data = ar->files[disk].data + dataptr;
|
||||
} else {
|
||||
//int readsize = dataptr2 - dataptr;
|
||||
@@ -228,28 +227,31 @@ struct archive_data *ald_get(struct ald_archive *ar, int no)
|
||||
dfile->data = data + ptr;
|
||||
dfile->size = size;
|
||||
dfile->name = strdup((char*)data + 16);
|
||||
dfile->archive = ar;
|
||||
dfile->archive = &ar->ar;
|
||||
return dfile;
|
||||
}
|
||||
|
||||
/* Free an ald_data strcture returned by `ald_get`. */
|
||||
void ald_free_data(struct archive_data *data)
|
||||
static void ald_free_data(struct archive_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
if (!((struct ald_archive*)data->archive)->mmapped)
|
||||
if (!data->archive->mmapped)
|
||||
free(data->data);
|
||||
free(data->name);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* Free an ald_archive structure returned by `ald_open`. */
|
||||
void ald_free_archive(struct ald_archive *ar)
|
||||
static void ald_free(struct archive *_ar)
|
||||
{
|
||||
if (!ar)
|
||||
if (!_ar)
|
||||
return;
|
||||
|
||||
struct ald_archive *ar = (struct ald_archive*)_ar;
|
||||
|
||||
// unmap mmap files
|
||||
if (ar->mmapped) {
|
||||
if (ar->ar.mmapped) {
|
||||
for (int i = 0; i < ALD_FILEMAX; i++) {
|
||||
if (ar->files[i].data)
|
||||
munmap(ar->files[i].data, ar->files[i].size);
|
||||
@@ -259,7 +261,7 @@ void ald_free_archive(struct ald_archive *ar)
|
||||
}
|
||||
|
||||
/* Open an ALD archive, optionally memory-mapping it. */
|
||||
struct ald_archive *ald_open(char **files, int count, int flags, int *error)
|
||||
struct archive *ald_open(char **files, int count, int flags, int *error)
|
||||
{
|
||||
FILE *fp;
|
||||
long filesize;
|
||||
@@ -267,7 +269,7 @@ struct ald_archive *ald_open(char **files, int count, int flags, int *error)
|
||||
bool gotmap = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
flags &= ~ALD_MMAP;
|
||||
flags &= ~ARCHIVE_MMAP;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -275,12 +277,12 @@ struct ald_archive *ald_open(char **files, int count, int flags, int *error)
|
||||
if (!files[i])
|
||||
continue;
|
||||
if (!(fp = fopen(files[i], "r"))) {
|
||||
*error = ALD_FILE_ERROR;
|
||||
*error = ARCHIVE_FILE_ERROR;
|
||||
goto exit_err;
|
||||
}
|
||||
// check if it's a valid archive
|
||||
if (!file_check(fp)) {
|
||||
*error = ALD_BAD_ARCHIVE_ERROR;
|
||||
*error = ARCHIVE_BAD_ARCHIVE_ERROR;
|
||||
fclose(fp);
|
||||
goto exit_err;
|
||||
}
|
||||
@@ -297,16 +299,16 @@ struct ald_archive *ald_open(char **files, int count, int flags, int *error)
|
||||
ar->files[i].name = strdup(files[i]);
|
||||
// close
|
||||
fclose(fp);
|
||||
if (flags & ALD_MMAP) {
|
||||
if (flags & ARCHIVE_MMAP) {
|
||||
int fd;
|
||||
if (0 > (fd = open(files[i], O_RDONLY))) {
|
||||
*error = ALD_FILE_ERROR;
|
||||
*error = ARCHIVE_FILE_ERROR;
|
||||
goto exit_err;
|
||||
}
|
||||
ar->files[i].data = mmap(0, filesize, PROT_READ, MAP_SHARED, fd, 0);
|
||||
close(fd);
|
||||
if (ar->files[i].data == MAP_FAILED) {
|
||||
*error = ALD_FILE_ERROR;
|
||||
*error = ARCHIVE_FILE_ERROR;
|
||||
goto exit_err;
|
||||
}
|
||||
ar->files[i].size = filesize;
|
||||
@@ -318,10 +320,12 @@ struct ald_archive *ald_open(char **files, int count, int flags, int *error)
|
||||
continue;
|
||||
c++;
|
||||
}
|
||||
ar->mmapped = flags & ALD_MMAP;
|
||||
ar->ar.mmapped = flags & ARCHIVE_MMAP;
|
||||
ar->nr_files = count;
|
||||
return ar;
|
||||
ar->ar.ops = &ald_archive_ops;
|
||||
return &ar->ar;
|
||||
exit_err:
|
||||
free(ar);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "system4.h"
|
||||
#include "system4/ald.h"
|
||||
|
||||
static const char *errtab[ARCHIVE_MAX_ERROR] = {
|
||||
[ARCHIVE_SUCCESS] = "Success",
|
||||
[ARCHIVE_FILE_ERROR] = "Error opening ALD file",
|
||||
[ARCHIVE_BAD_ARCHIVE_ERROR] = "Invalid ALD file"
|
||||
};
|
||||
|
||||
/* Get a message describing an error. */
|
||||
const char *archive_strerror(int error)
|
||||
{
|
||||
if (error < ARCHIVE_MAX_ERROR)
|
||||
return errtab[error];
|
||||
return "Invalid error number";
|
||||
}
|
||||
+3
-3
@@ -101,7 +101,7 @@ static int audio_type_to_archive_type(enum audio_type type)
|
||||
bool audio_exists(enum audio_type type, int no)
|
||||
{
|
||||
int archive = audio_type_to_archive_type(type);
|
||||
return ald[archive] && ald_data_exists(ald[archive], no);
|
||||
return ald[archive] && archive_exists(ald[archive], no);
|
||||
}
|
||||
|
||||
static Mix_Chunk *load_chunk(enum audio_type type, int no)
|
||||
@@ -109,13 +109,13 @@ static Mix_Chunk *load_chunk(enum audio_type type, int no)
|
||||
struct archive_data *dfile;
|
||||
int archive = audio_type_to_archive_type(type);
|
||||
|
||||
if (!(dfile = ald_get(ald[archive], no))) {
|
||||
if (!(dfile = archive_get(ald[archive], no))) {
|
||||
WARNING("Failed to load %s %d", archive == ALDFILE_BGM ? "BGM" : "WAV", no);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Mix_Chunk *chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(dfile->data, dfile->size), 1);
|
||||
ald_free_data(dfile);
|
||||
archive_free_data(dfile);
|
||||
|
||||
if (!chunk) {
|
||||
WARNING("%s %d: not a valid audio file", archive == ALDFILE_BGM ? "BGM" : "WAV", no);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "system4.h"
|
||||
#include "system4/ald.h"
|
||||
#include "system4/archive.h"
|
||||
#include "system4/cg.h"
|
||||
#include "system4/qnt.h"
|
||||
|
||||
@@ -35,11 +35,11 @@ static enum cg_type check_cgformat(uint8_t *data)
|
||||
return ALCG_UNKNOWN;
|
||||
}
|
||||
|
||||
bool cg_get_metrics(struct ald_archive *ar, int no, struct cg_metrics *dst)
|
||||
bool cg_get_metrics(struct archive *ar, int no, struct cg_metrics *dst)
|
||||
{
|
||||
struct archive_data *dfile;
|
||||
|
||||
if (!(dfile = ald_get(ar, no)))
|
||||
if (!(dfile = archive_get(ar, no)))
|
||||
return false;
|
||||
|
||||
switch (check_cgformat(dfile->data)) {
|
||||
@@ -48,10 +48,10 @@ bool cg_get_metrics(struct ald_archive *ar, int no, struct cg_metrics *dst)
|
||||
break;
|
||||
default:
|
||||
WARNING("Unknown CG type (CG %d)", no);
|
||||
ald_free_data(dfile);
|
||||
archive_free_data(dfile);
|
||||
return false;
|
||||
}
|
||||
ald_free_data(dfile);
|
||||
archive_free_data(dfile);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -72,13 +72,13 @@ void cg_free(struct cg *cg)
|
||||
* no: file no ( >= 0)
|
||||
* return: cg object(extracted)
|
||||
*/
|
||||
struct cg *cg_load(struct ald_archive *ar, int no)
|
||||
struct cg *cg_load(struct archive *ar, int no)
|
||||
{
|
||||
struct cg *cg;
|
||||
struct archive_data *dfile;
|
||||
int type;
|
||||
|
||||
if (!(dfile = ald_get(ar, no))) {
|
||||
if (!(dfile = archive_get(ar, no))) {
|
||||
WARNING("Failed to load CG %d", no);
|
||||
return NULL;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ struct cg *cg_load(struct ald_archive *ar, int no)
|
||||
}
|
||||
|
||||
// ok to free
|
||||
ald_free_data(dfile);
|
||||
archive_free_data(dfile);
|
||||
|
||||
if (cg->pixels)
|
||||
return cg;
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ int sact_Key_IsDown(int keycode)
|
||||
|
||||
int sact_CG_IsExist(int cg_no)
|
||||
{
|
||||
return ald[ALDFILE_CG] && ald_data_exists(ald[ALDFILE_CG], cg_no - 1);
|
||||
return ald[ALDFILE_CG] && archive_exists(ald[ALDFILE_CG], cg_no - 1);
|
||||
}
|
||||
|
||||
int sact_Music_IsExist(int n)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# sources for libsys4.a
|
||||
system4 = ['ain.c',
|
||||
'ald.c',
|
||||
'archive.c',
|
||||
'buffer.c',
|
||||
'cg.c',
|
||||
'ex.c',
|
||||
|
||||
+3
-3
@@ -75,10 +75,10 @@ static int ald_count[ALDFILETYPE_MAX];
|
||||
|
||||
void ald_init(int type, char **files, int count)
|
||||
{
|
||||
int error = ALD_SUCCESS;
|
||||
ald[type] = ald_open(files, count, ALD_MMAP, &error);
|
||||
int error = ARCHIVE_SUCCESS;
|
||||
ald[type] = ald_open(files, count, ARCHIVE_MMAP, &error);
|
||||
if (error)
|
||||
ERROR("Failed to open ALD file: %s\n", ald_strerror(error));
|
||||
ERROR("Failed to open ALD file: %s\n", archive_strerror(error));
|
||||
}
|
||||
|
||||
static void init_gamedata_dir(const char *path)
|
||||
|
||||
Reference in New Issue
Block a user