diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e586818..7eb9bdf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,7 @@ target_sources(xsystem35 PRIVATE ags.c ald_manager.c alpha_plane.c - bgi.c + audio_meta.c bmp.c cache.c cali.c diff --git a/src/bgi.c b/src/audio_meta.c similarity index 57% rename from src/bgi.c rename to src/audio_meta.c index f9a9f9d..95c8670 100644 --- a/src/bgi.c +++ b/src/audio_meta.c @@ -1,5 +1,5 @@ /* - * bgi.c: BGI (BGM information) parser + * audio_meta.c: BGI (BGM information) / WAI (wave information) parser * * Copyright (C) 1997-1998 Masaki Chikama (Wren) * 1998- @@ -23,10 +23,12 @@ #include "config.h" #include +#include #include "portab.h" #include "system.h" -#include "bgi.h" +#include "audio_meta.h" +#include "LittleEndian.h" #define BGI_MAX 100 @@ -82,3 +84,77 @@ bgi_t *bgi_find(int no) { } return NULL; } + +static int *wai_channels; +static int wai_count; + +static void wai_unload(void) { + free(wai_channels); + wai_channels = NULL; + wai_count = 0; +} + +bool wai_load(const char *path) { + wai_unload(); + if (!path) + return false; + + FILE *fp = fopen(path, "rb"); + if (!fp) + return false; + + uint8_t header[24]; + if (fread(header, 1, sizeof(header), fp) != sizeof(header) || + header[0] != 'X' || header[1] != 'I' || header[2] != '2' || header[3] != '\0') + { + WARNING("not WAI file"); + fclose(fp); + return false; + } + + int count = LittleEndian_getDW(header, 8); + if (count <= 0) { + WARNING("invalid WAI record count: %d", count); + fclose(fp); + return false; + } + + int version = LittleEndian_getDW(header, 12); + if (version != 3) { + WARNING("unsupported WAI version: %d", version); + fclose(fp); + return false; + } + + int *channels = calloc(count, sizeof(*channels)); + if (!channels) { + fclose(fp); + return false; + } + + uint8_t record[12]; + for (int i = 0; i < count; i++) { + if (fread(record, 1, sizeof(record), fp) != sizeof(record)) { + WARNING("truncated WAI file"); + free(channels); + fclose(fp); + return false; + } + channels[i] = LittleEndian_getDW(record, 8); + } + + fclose(fp); + wai_channels = channels; + wai_count = count; + return true; +} + +bool wai_loaded(void) { + return wai_channels != NULL; +} + +int wai_mixch(int no) { + if (!wai_channels || no < 0 || no >= wai_count) + return -1; + return wai_channels[no]; +} diff --git a/src/bgi.h b/src/audio_meta.h similarity index 89% rename from src/bgi.h rename to src/audio_meta.h index 0ede362..cefce41 100644 --- a/src/bgi.h +++ b/src/audio_meta.h @@ -1,5 +1,5 @@ /* - * bgi.c: BGI (BGM information) parser + * audio_meta.h: BGI (BGM information) / WAI (wave information) parser * * Copyright (C) 1997-1998 Masaki Chikama (Wren) * 1998- @@ -35,4 +35,8 @@ typedef struct { extern bool bgi_read(const char *path); extern bgi_t *bgi_find(int no); +bool wai_load(const char *path); +bool wai_loaded(void); +int wai_mixch(int no); + #endif /* _BGI_H__ */ diff --git a/src/bgm.emscripten.c b/src/bgm.emscripten.c index fa37d16..44580d0 100644 --- a/src/bgm.emscripten.c +++ b/src/bgm.emscripten.c @@ -23,7 +23,7 @@ #include "portab.h" #include "nact.h" #include "bgm.h" -#include "bgi.h" +#include "audio_meta.h" #include "system.h" bool musbgm_init(DRIFILETYPE type, int base_no) { diff --git a/src/bgm.sdlmixer.c b/src/bgm.sdlmixer.c index 99c7a54..35b39aa 100644 --- a/src/bgm.sdlmixer.c +++ b/src/bgm.sdlmixer.c @@ -32,7 +32,7 @@ #include "system.h" #include "nact.h" #include "bgm.h" -#include "bgi.h" +#include "audio_meta.h" #include "music_private.h" #include "ald_manager.h" diff --git a/src/pcm.sdlmixer.c b/src/pcm.sdlmixer.c index 2349005..3f2cc14 100644 --- a/src/pcm.sdlmixer.c +++ b/src/pcm.sdlmixer.c @@ -35,8 +35,7 @@ #include "music_pcm.h" #include "music_private.h" #include "nact.h" -#include "LittleEndian.h" -#include "mmap.h" +#include "audio_meta.h" #define SAMPLE_RATE 44100 #define BYTES_PER_SAMPLE 4 @@ -51,12 +50,6 @@ static struct { uint32_t start_time; } slots[PCM_SLOTS]; -static bool load_wai(); -static mmap_t *wai_map; - -// Volume mixer channel -#define WAIMIXCH(no) LittleEndian_getDW(wai_map->addr, 36 + (no -1) * 4 * 3 + 8) - // Apply the slot's volume valancer level via its chunk volume. static void apply_valance(int slot) { if (!slots[slot].chunk) @@ -152,7 +145,7 @@ bool muspcm_init(int audio_buffer_size) { if (Mix_OpenAudio(SAMPLE_RATE, AUDIO_S16LSB, 2, audio_buffer_size) < 0) return false; Mix_AllocateChannels(PCM_SLOTS); - load_wai(); + wai_load(nact->files.wai); return true; } @@ -177,8 +170,8 @@ bool muspcm_load_no(int slot, int no) { } // if has .wai file - if (wai_map) { - int ch = WAIMIXCH(no); + if (wai_loaded()) { + int ch = wai_mixch(no); prv.vol_pcm_sub[slot] = ch < 0 ? 0: ch; } else { prv.vol_pcm_sub[slot] = SE_VOLVAL_CH; @@ -333,24 +326,3 @@ void muspcm_reapply_valance(void) { for (int slot = 0; slot < PCM_SLOTS; slot++) apply_valance(slot); } - -static bool load_wai() { - if (wai_map) { - unmap_file(wai_map); - wai_map = NULL; - } - if (nact->files.wai == NULL) - return false; - wai_map = map_file(nact->files.wai); - if (!wai_map) - return false; - - char *adr = wai_map->addr; - if (*adr != 'X' || *(adr+1) != 'I' || *(adr+2) != '2') { - WARNING("not WAI file"); - unmap_file(wai_map); - wai_map = NULL; - return false; - } - return true; -}