diff --git a/CMakeLists.txt b/CMakeLists.txt index 55eecb8..d1962f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if (ANDROID) target_sources(system3 PRIVATE src/android/nact_android.cpp - src/android/mako.cpp + src/generic/mako.cpp ) target_link_libraries(system3 PRIVATE SDL2 SDL2_ttf SDL2_mixer ymfm) @@ -133,8 +133,8 @@ else() # NOT (ANDROID OR EMSCRIPTEN) else() pkg_check_modules(SDL2MIXER REQUIRED IMPORTED_TARGET SDL2_mixer) target_sources(system3 PRIVATE - src/linux/nact_linux.cpp - src/linux/mako.cpp + src/generic/nact_generic.cpp + src/generic/mako.cpp ) target_link_libraries(system3 PRIVATE PkgConfig::SDL2MIXER) set(RESOURCE_PATH ${CMAKE_INSTALL_PREFIX}/share/system3/) diff --git a/src/android/mako.cpp b/src/android/mako.cpp deleted file mode 100644 index ced741e..0000000 --- a/src/android/mako.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include -#include -#include -#include - -#include "../config.h" -#include "jnihelper.h" -#include "dri.h" -#include "mako.h" -#include "fm/mako_ymfm.h" - -namespace { - -const int SAMPLE_RATE = 44100; - -Mix_Music *mix_music; -Mix_Chunk *mix_chunk; -SDL_mutex* fm_mutex; -std::unique_ptr fm; - -void FMHook(void*, Uint8* stream, int len) { - SDL_LockMutex(fm_mutex); - fm->Process(reinterpret_cast(stream), len / 4); - SDL_UnlockMutex(fm_mutex); -} - -} // namespace - -MAKO::MAKO(NACT* parent, const Config& config) : - use_fm(config.use_fm), - current_music(0), - next_loop(0), - nact(parent) -{ - load_playlist(config.playlist.c_str()); - - strcpy(amus, "AMUS.DAT"); - strcpy(amse, "AMSE.DAT"); // unused - for (int i = 1; i <= 99; i++) - cd_track[i] = 0; - - const int mix_init_flags = MIX_INIT_MP3 | MIX_INIT_OGG; - if (Mix_Init(mix_init_flags) != mix_init_flags) - WARNING("Mix_Init(0x%x) failed", mix_init_flags); - if (Mix_OpenAudio(SAMPLE_RATE, AUDIO_S16LSB, 2, 4096) < 0) - WARNING("Mix_OpenAudio failed: %s", Mix_GetError()); -} - -MAKO::~MAKO() -{ - stop_pcm(); - Mix_CloseAudio(); - Mix_Quit(); -} - -bool MAKO::load_playlist(const char* path) -{ - FILE* fp = fopen(path, "r"); - if (!fp) { - WARNING("Cannot open %s", path); - return false; - } - char buf[256]; - while (fgets(buf, sizeof(buf) - 1, fp)) { - for (char *p = buf; *p; p++) { - if (*p == '\\') - *p = '/'; - else if (*p == '\r' || *p == '\n') - *p = '\0'; - } - playlist.push_back(buf[0] ? strdup(buf) : NULL); - } - fclose(fp); - return true; -} - -void MAKO::play_music(int page) -{ - if (current_music == page) - return; - - stop_music(); - - int track = page < 100 ? cd_track[page] : 0; - if (track) { - if (track < playlist.size() && playlist[track]) { - // Mix_LoadMUS uses SDL_RWFromFile which requires absolute path on Android - char path[PATH_MAX]; - if (!realpath(playlist[track], path)) - return; - mix_music = Mix_LoadMUS(path); - if (!mix_music) { - WARNING("Mix_LoadMUS failed: %s: %s", playlist[track], Mix_GetError()); - return; - } - if (Mix_PlayMusic(mix_music, next_loop ? next_loop : -1) != 0) { - WARNING("Mix_PlayMusic failed: %s", Mix_GetError()); - Mix_FreeMusic(mix_music); - return; - } - } - } else { - DRI dri; - int size; - uint8* data = dri.load(amus, page, &size); - if (!data) - return; - if (!fm_mutex) - fm_mutex = SDL_CreateMutex(); - - SDL_LockMutex(fm_mutex); - fm = std::make_unique(SAMPLE_RATE, data, true); - SDL_UnlockMutex(fm_mutex); - Mix_HookMusic(&FMHook, this); - } - - current_music = page; - next_loop = 0; -} - -void MAKO::stop_music() -{ - if (!current_music) - return; - - if (mix_music) { - Mix_FreeMusic(mix_music); - mix_music = NULL; - } - - if (fm) { - Mix_HookMusic(NULL, NULL); - SDL_LockMutex(fm_mutex); - fm = nullptr; - SDL_UnlockMutex(fm_mutex); - } - current_music = 0; -} - -bool MAKO::check_music() -{ - if (!current_music) - return false; - if (mix_music) - return Mix_PlayingMusic(); - if (fm) { - int mark, loop; - SDL_LockMutex(fm_mutex); - fm->get_mark(&mark, &loop); - SDL_UnlockMutex(fm_mutex); - return !loop; - } - - return false; -} - -void MAKO::get_mark(int* mark, int* loop) -{ - if (fm) { - SDL_LockMutex(fm_mutex); - fm->get_mark(mark, loop); - SDL_UnlockMutex(fm_mutex); - } else { - *mark = 0; - *loop = 0; - } -} - -void MAKO::play_pcm(int page, bool loop) -{ - static char header[44] = { - 'R' , 'I' , 'F' , 'F' , 0x00, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' , - 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, - 0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x00, 0x00, 0x00, 0x00 - }; - - stop_pcm(); - - uint8* buffer = NULL; - int size; - DRI* dri = new DRI(); - - if((buffer = dri->load("AWAV.DAT", page, &size)) != NULL) { - // WAV形式 (Only You) - mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(buffer, size), 1 /* freesrc */); - free(buffer); - Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); - } else if((buffer = dri->load("AMSE.DAT", page, &size)) != NULL) { - // AMSE形式 (乙女戦記) - int total = (size - 12) * 2 + 0x24; - int samples = (size - 12) * 2; - - uint8* wav = (uint8*)malloc(total + 8); - memcpy(wav, header, 44); - wav[ 4] = (total >> 0) & 0xff; - wav[ 5] = (total >> 8) & 0xff; - wav[ 6] = (total >> 16) & 0xff; - wav[ 7] = (total >> 24) & 0xff; - wav[40] = (samples >> 0) & 0xff; - wav[41] = (samples >> 8) & 0xff; - wav[42] = (samples >> 16) & 0xff; - wav[43] = (samples >> 24) & 0xff; - for(int i = 12, p = 44; i < size; i++) { - wav[p++] = buffer[i] & 0xf0; - wav[p++] = (buffer[i] & 0x0f) << 4; - } - free(buffer); - - mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(wav, total + 8), 1 /* freesrc */); - free(wav); - Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); - } -} - -void MAKO::stop_pcm() -{ - Mix_HaltChannel(-1); - if (mix_chunk) { - Mix_FreeChunk(mix_chunk); - mix_chunk = NULL; - } -} - -bool MAKO::check_pcm() -{ - return Mix_Playing(-1) != 0; -} diff --git a/src/linux/mako.cpp b/src/generic/mako.cpp similarity index 95% rename from src/linux/mako.cpp rename to src/generic/mako.cpp index 572bcf3..ac9f4ce 100644 --- a/src/linux/mako.cpp +++ b/src/generic/mako.cpp @@ -97,7 +97,15 @@ void MAKO::play_music(int page) int track = page < 100 ? cd_track[page] : 0; if (track) { if (track < playlist.size() && playlist[track]) { +#ifdef __ANDROID__ + // Mix_LoadMUS uses SDL_RWFromFile which requires absolute path on Android + char path[PATH_MAX]; + if (!realpath(playlist[track], path)) + return; + mix_music = Mix_LoadMUS(path); +#else mix_music = Mix_LoadMUS(playlist[track]); +#endif if (!mix_music) { WARNING("Mix_LoadMUS failed: %s: %s", playlist[track], Mix_GetError()); return; @@ -132,6 +140,9 @@ void MAKO::play_music(int page) void MAKO::stop_music() { + if (!current_music) + return; + if (mix_music) { Mix_FreeMusic(mix_music); mix_music = NULL; diff --git a/src/linux/nact_linux.cpp b/src/generic/nact_generic.cpp similarity index 100% rename from src/linux/nact_linux.cpp rename to src/generic/nact_generic.cpp