mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-10-01 19:28:00 +03:00
Implement S3xMusic HLL
Used in Ore no Shita de Agake. Since the musbgm_* interface does not allow multiple channels, this implementation uses musbgm_* for channel 0 and muspcm_* for channel 1.
This commit is contained in:
@@ -23,6 +23,7 @@ add_library(modules STATIC
|
||||
NIGHTDLL/nt_sound.c
|
||||
NightDemonDemo/NightDemonDemo.c
|
||||
RandMT/RandMT.c
|
||||
S3xMusic/S3xMusic.c
|
||||
SACT/SACT.c
|
||||
SACT/sactcg.c
|
||||
SACT/sactsound.c
|
||||
|
||||
@@ -51,7 +51,7 @@ static void ndd_run(int demonum) {
|
||||
|
||||
int mus = ndemo_mus[demonum];
|
||||
if (mus)
|
||||
musbgm_play(mus, 0, 100);
|
||||
musbgm_play(mus, 0, 100, 0);
|
||||
|
||||
uint32_t start = sdl_getTicks();
|
||||
while (!nact->is_quit) {
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (C) 2025 <KichikuouChrome@gmail.com>
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "modules.h"
|
||||
#include "nact.h"
|
||||
#include "bgm.h"
|
||||
#include "music.h"
|
||||
#include "music_pcm.h"
|
||||
|
||||
#define SLOT 128
|
||||
|
||||
static int current_no = 0;
|
||||
|
||||
static void Init(void) {
|
||||
int isys3x = getCaliValue();
|
||||
TRACE("S3xMusic.Init %d:", isys3x);
|
||||
}
|
||||
|
||||
static void CreateChannel(void) {
|
||||
int nr_channels = getCaliValue();
|
||||
if (nr_channels != 2)
|
||||
SYSERROR("Unsupported number of channels: %d", nr_channels);
|
||||
TRACE("S3xMusic.CreateChannel %d:", nr_channels);
|
||||
}
|
||||
|
||||
static void Prepare(void) {
|
||||
int ch = getCaliValue();
|
||||
int no = getCaliValue();
|
||||
int *result = getCaliVariable();
|
||||
|
||||
if (ch == 0) {
|
||||
current_no = no;
|
||||
*result = 1;
|
||||
} else {
|
||||
*result = muspcm_load_bgm(SLOT, no) == OK;
|
||||
}
|
||||
TRACE("S3xMusic.Prepare %d, %d => %d:", ch, no, *result);
|
||||
}
|
||||
|
||||
static void Unprepare(void) {
|
||||
int ch = getCaliValue();
|
||||
|
||||
if (ch == 0) {
|
||||
if (current_no) {
|
||||
musbgm_stop(current_no, 0);
|
||||
current_no = 0;
|
||||
}
|
||||
} else {
|
||||
muspcm_unload(SLOT);
|
||||
}
|
||||
TRACE("S3xMusic.Unprepare %d:", ch);
|
||||
}
|
||||
|
||||
static void Play(void) {
|
||||
int p1 = getCaliValue();
|
||||
int p2 = getCaliValue();
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.Play %d, %d:", p1, p2);
|
||||
}
|
||||
|
||||
static void FadePlay(void) {
|
||||
int ch = getCaliValue();
|
||||
int fadein_time = getCaliValue();
|
||||
int volume = getCaliValue();
|
||||
int loop_count = getCaliValue(); // 0 = infinite
|
||||
|
||||
if (ch == 0) {
|
||||
musbgm_play(current_no, fadein_time, volume, loop_count);
|
||||
} else {
|
||||
muspcm_start(SLOT, loop_count == 0 ? -1 : loop_count);
|
||||
}
|
||||
TRACE("S3xMusic.FadePlay %d, %d, %d, %d:", ch, fadein_time, volume, loop_count);
|
||||
}
|
||||
|
||||
static void PlayPosSample(void) {
|
||||
int p1 = getCaliValue();
|
||||
int p2 = getCaliValue();
|
||||
int p3 = getCaliValue();
|
||||
int p4 = getCaliValue();
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.PlayPosSample %d, %d, %d, %d:", p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
static void IsPlay(void) {
|
||||
int ch = getCaliValue();
|
||||
int *result = getCaliVariable();
|
||||
|
||||
if (ch == 0) {
|
||||
*result = current_no && musbgm_isplaying(current_no);
|
||||
} else {
|
||||
*result = muspcm_isplaying(SLOT);
|
||||
}
|
||||
TRACE("S3xMusic.IsPlay %d => %d:", ch, *result);
|
||||
}
|
||||
|
||||
static void Stop(void) {
|
||||
int ch = getCaliValue();
|
||||
|
||||
if (ch == 0) {
|
||||
if (current_no)
|
||||
musbgm_stop(current_no, 0);
|
||||
current_no = 0;
|
||||
} else {
|
||||
muspcm_stop(SLOT);
|
||||
}
|
||||
TRACE("S3xMusic.Stop %d:", ch);
|
||||
}
|
||||
|
||||
static void Restart(void) {
|
||||
int p1 = getCaliValue();
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.Restart %d:", p1);
|
||||
}
|
||||
|
||||
static void GetPlayPos(void) {
|
||||
int ch = getCaliValue();
|
||||
int *hour = getCaliVariable();
|
||||
int *min = getCaliVariable();
|
||||
int *sec = getCaliVariable();
|
||||
int *msec = getCaliVariable();
|
||||
if (ch == 0) {
|
||||
int time = musbgm_getpos(current_no);
|
||||
*hour = time / 360000;
|
||||
*min = (time / 6000) % 60;
|
||||
*sec = (time / 100) % 60;
|
||||
*msec = (time % 100) * 10;
|
||||
} else {
|
||||
// not implemented
|
||||
*hour = 0;
|
||||
*min = 0;
|
||||
*sec = 0;
|
||||
*msec = 0;
|
||||
}
|
||||
TRACE("S3xMusic.GetPlayPos %d => %d, %d, %d, %d:", ch, *hour, *min, *sec, *msec);
|
||||
}
|
||||
|
||||
static void GetPlayPosSample(void) {
|
||||
int p1 = getCaliValue();
|
||||
int *var1 = getCaliVariable();
|
||||
int *var2 = getCaliVariable();
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.GetPlayPosSample %d, %p, %p:", p1, var1, var2);
|
||||
}
|
||||
|
||||
static void SetRepeatStart(void) {
|
||||
int p1 = getCaliValue();
|
||||
int p2 = getCaliValue();
|
||||
int p3 = getCaliValue();
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.SetRepeatStart %d, %d, %d:", p1, p2, p3);
|
||||
}
|
||||
|
||||
static void SetRepeatEnd(void) {
|
||||
int p1 = getCaliValue();
|
||||
int p2 = getCaliValue();
|
||||
int p3 = getCaliValue();
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.SetRepeatEnd %d, %d, %d:", p1, p2, p3);
|
||||
}
|
||||
|
||||
static void FadeVolume(void) {
|
||||
int ch = getCaliValue();
|
||||
int time = getCaliValue();
|
||||
int volume = getCaliValue();
|
||||
int stop_after_fade = getCaliValue();
|
||||
|
||||
if (ch == 0) {
|
||||
if (stop_after_fade) {
|
||||
musbgm_stop(current_no, time / 10);
|
||||
} else {
|
||||
musbgm_fade(current_no, time / 10, volume);
|
||||
}
|
||||
} else {
|
||||
if (stop_after_fade) {
|
||||
muspcm_fadeout(SLOT, time);
|
||||
} else {
|
||||
muspcm_setvol(SLOT, volume);
|
||||
}
|
||||
}
|
||||
TRACE("S3xMusic.FadeVolume %d, %d, %d, %d:", ch, time, volume, stop_after_fade);
|
||||
}
|
||||
|
||||
static void IsFade(void) {
|
||||
int ch = getCaliValue();
|
||||
int *result = getCaliVariable();
|
||||
*result = 0;
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.IsFade %d => %d:", ch, *result);
|
||||
}
|
||||
|
||||
static void StopFade(void) {
|
||||
int ch = getCaliValue();
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.StopFade %d:", ch);
|
||||
}
|
||||
|
||||
static void WaitEnd(void) {
|
||||
int p1 = getCaliValue();
|
||||
int p2 = getCaliValue(); // IWinMsg
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.WaitEnd %d, %d:", p1, p2);
|
||||
}
|
||||
|
||||
static void sleep(void) {
|
||||
int p1 = getCaliValue(); // IWinMsg
|
||||
TRACE_UNIMPLEMENTED("S3xMusic.sleep %d:", p1);
|
||||
}
|
||||
|
||||
static const ModuleFunc functions[] = {
|
||||
{"CreateChannel", CreateChannel},
|
||||
{"FadePlay", FadePlay},
|
||||
{"FadeVolume", FadeVolume},
|
||||
{"GetPlayPos", GetPlayPos},
|
||||
{"GetPlayPosSample", GetPlayPosSample},
|
||||
{"Init", Init},
|
||||
{"IsFade", IsFade},
|
||||
{"IsPlay", IsPlay},
|
||||
{"Play", Play},
|
||||
{"PlayPosSample", PlayPosSample},
|
||||
{"Prepare", Prepare},
|
||||
{"Restart", Restart},
|
||||
{"SetRepeatEnd", SetRepeatEnd},
|
||||
{"SetRepeatStart", SetRepeatStart},
|
||||
{"Stop", Stop},
|
||||
{"StopFade", StopFade},
|
||||
{"Unprepare", Unprepare},
|
||||
{"WaitEnd", WaitEnd},
|
||||
{"sleep", sleep},
|
||||
};
|
||||
|
||||
const Module module_S3xMusic = {"S3xMusic", functions, sizeof(functions) / sizeof(ModuleFunc)};
|
||||
+1
-1
@@ -1838,7 +1838,7 @@ static void MusicPlay() {
|
||||
int wFadeTime = getCaliValue();
|
||||
int wVolume = getCaliValue();
|
||||
|
||||
musbgm_play(wNum, wFadeTime, wVolume);
|
||||
musbgm_play(wNum, wFadeTime, wVolume, 0);
|
||||
|
||||
TRACE("SACT.MusicPlay %d,%d,%d:", wNum, wFadeTime, wVolume);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ static const Module *modules[] = {
|
||||
&module_NIGHTDLL,
|
||||
&module_NightDemonDemo,
|
||||
&module_RandMT,
|
||||
&module_S3xMusic,
|
||||
&module_SACT,
|
||||
&module_ShArray,
|
||||
&module_ShCalc,
|
||||
|
||||
@@ -42,6 +42,7 @@ extern const Module module_MsgSkip;
|
||||
extern const Module module_NIGHTDLL;
|
||||
extern const Module module_NightDemonDemo;
|
||||
extern const Module module_RandMT;
|
||||
extern const Module module_S3xMusic;
|
||||
extern const Module module_SACT;
|
||||
extern const Module module_ShArray;
|
||||
extern const Module module_ShCalc;
|
||||
|
||||
@@ -71,7 +71,7 @@ static void Run() {
|
||||
|
||||
while (sys_getInputInfo()); // wait for key up
|
||||
|
||||
musbgm_play(TDEMO_MUSIC_NO, 0, 100);
|
||||
musbgm_play(TDEMO_MUSIC_NO, 0, 100, 0);
|
||||
|
||||
uint32_t start = sdl_getTicks();
|
||||
while (!nact->is_quit) {
|
||||
|
||||
@@ -44,9 +44,9 @@ int musbgm_reset(void) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
EM_JS(int, musbgm_play, (int no, int time, int vol), {
|
||||
EM_JS(int, musbgm_play, (int no, int time, int vol, int loop_count), {
|
||||
xsystem35.cdPlayer.fade(time * 10, vol / 100);
|
||||
xsystem35.cdPlayer.play(no, 1);
|
||||
xsystem35.cdPlayer.play(no, loop_count == 0);
|
||||
return xsystem35.Status.OK;
|
||||
});
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
int musbgm_init(DRIFILETYPE type, int base_no);
|
||||
int musbgm_exit(void);
|
||||
int musbgm_reset(void);
|
||||
int musbgm_play(int no, int time, int vol);
|
||||
int musbgm_play(int no, int time, int vol, int loop_count);
|
||||
int musbgm_stop(int no, int time);
|
||||
int musbgm_fade(int no, int time, int vol);
|
||||
int musbgm_getpos(int no);
|
||||
|
||||
+2
-2
@@ -96,7 +96,7 @@ int musbgm_reset(void) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
int musbgm_play(int no, int time, int vol) {
|
||||
int musbgm_play(int no, int time, int vol, int loop_count) {
|
||||
if (current_no)
|
||||
musbgm_stop(current_no, 0);
|
||||
|
||||
@@ -107,7 +107,7 @@ int musbgm_play(int no, int time, int vol) {
|
||||
// understands loop info in the WAVE's "smpl" chunk.
|
||||
|
||||
Mix_VolumeMusic(vol * MIX_MAX_VOLUME / 100);
|
||||
if (Mix_FadeInMusic(mix_music, -1, time * 10) != 0) {
|
||||
if (Mix_FadeInMusic(mix_music, loop_count == 0 ? -1 : loop_count, time * 10) != 0) {
|
||||
free_music();
|
||||
return NG;
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ static int cdrom_bgm_reset(void) {
|
||||
}
|
||||
|
||||
static int cdrom_bgm_start(int trk, int loop) {
|
||||
if (musbgm_play(trk, 0, 100) != OK)
|
||||
if (musbgm_play(trk, 0, 100, loop) != OK)
|
||||
return NG;
|
||||
current_track = trk;
|
||||
return OK;
|
||||
|
||||
@@ -28,6 +28,7 @@ extern int muspcm_init(int audio_buffer_size);
|
||||
extern int muspcm_exit(void);
|
||||
extern int muspcm_reset(void);
|
||||
extern int muspcm_load_no(int slot, int no);
|
||||
extern int muspcm_load_bgm(int slot, int no);
|
||||
extern int muspcm_load_mixlr(int slot, int noL, int noR);
|
||||
extern int muspcm_load_data(int slot, uint8_t *buf, uint32_t len);
|
||||
extern int muspcm_unload(int slot);
|
||||
|
||||
@@ -40,6 +40,10 @@ EM_ASYNC_JS(int, muspcm_load_no, (int slot, int no), {
|
||||
return await xsystem35.audio.pcm_load(slot, no);
|
||||
});
|
||||
|
||||
EM_ASYNC_JS(int, muspcm_load_bgm, (int slot, int no), {
|
||||
return await xsystem35.audio.pcm_load_bgm(slot, no);
|
||||
});
|
||||
|
||||
EM_ASYNC_JS(int, muspcm_load_data, (int slot, uint8_t *buf, uint32_t len), {
|
||||
return await xsystem35.audio.pcm_load_data(slot, buf, len);
|
||||
});
|
||||
|
||||
+18
-5
@@ -62,8 +62,8 @@ static mmap_t *wai_map;
|
||||
* 指定の番号の .WAV|.OGG をロードする。
|
||||
* @param no: DRIファイル番号
|
||||
*/
|
||||
static Mix_Chunk *load_asset(int no) {
|
||||
dridata *dfile = ald_getdata(DRIFILE_WAVE, no -1);
|
||||
static Mix_Chunk *load_asset(DRIFILETYPE type, int no) {
|
||||
dridata *dfile = ald_getdata(type, no -1);
|
||||
if (dfile == NULL) {
|
||||
WARNING("DRIFILE_WAVE fail to open %d", no -1);
|
||||
return NULL;
|
||||
@@ -99,8 +99,8 @@ static int load_chunk(int slot, Mix_Chunk *chunk) {
|
||||
* @return : 合成後の Mix_Chunk
|
||||
*/
|
||||
static Mix_Chunk *pcm_mixlr(int noL, int noR) {
|
||||
Mix_Chunk *chunkL = load_asset(noL);
|
||||
Mix_Chunk *chunkR = load_asset(noR);
|
||||
Mix_Chunk *chunkL = load_asset(DRIFILE_WAVE, noL);
|
||||
Mix_Chunk *chunkR = load_asset(DRIFILE_WAVE, noR);
|
||||
if (chunkL == NULL || chunkR == NULL) {
|
||||
if (chunkL)
|
||||
Mix_FreeChunk(chunkL);
|
||||
@@ -163,7 +163,7 @@ int muspcm_load_no(int slot, int no) {
|
||||
if ((unsigned)slot >= PCM_SLOTS)
|
||||
return NG;
|
||||
|
||||
Mix_Chunk *chunk = load_asset(no);
|
||||
Mix_Chunk *chunk = load_asset(DRIFILE_WAVE, no);
|
||||
if (chunk == NULL) {
|
||||
return NG;
|
||||
}
|
||||
@@ -179,6 +179,19 @@ int muspcm_load_no(int slot, int no) {
|
||||
return load_chunk(slot, chunk);
|
||||
}
|
||||
|
||||
int muspcm_load_bgm(int slot, int no) {
|
||||
if ((unsigned)slot >= PCM_SLOTS)
|
||||
return NG;
|
||||
|
||||
Mix_Chunk *chunk = load_asset(DRIFILE_BGM, no);
|
||||
if (chunk == NULL) {
|
||||
return NG;
|
||||
}
|
||||
prv.vol_pcm_sub[slot] = 0;
|
||||
|
||||
return load_chunk(slot, chunk);
|
||||
}
|
||||
|
||||
int muspcm_load_mixlr(int slot, int noL, int noR) {
|
||||
if ((unsigned)slot >= PCM_SLOTS)
|
||||
return NG;
|
||||
|
||||
Reference in New Issue
Block a user