mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-20 05:04:53 -04:00
mp3 support for playing background music
This commit is contained in:
parent
73a4187f79
commit
dd23d8c989
24 changed files with 2245 additions and 252 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <libs/memman.h>
|
#include <libs/memman.h>
|
||||||
|
#include <libs/music.h>
|
||||||
|
|
||||||
#define POCET_POSTAV 6
|
#define POCET_POSTAV 6
|
||||||
#define HODINA 360
|
#define HODINA 360
|
||||||
|
@ -1448,12 +1449,15 @@ void show_textured_button(int x,int y,int xs,int ys,int texture,CTL3D *border3d)
|
||||||
extern short sample_volume; //hlastitost samplu
|
extern short sample_volume; //hlastitost samplu
|
||||||
extern char **sound_table;
|
extern char **sound_table;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void init_tracks(void);
|
void init_tracks(void);
|
||||||
void recalc_volumes(int sector,int side);
|
void recalc_volumes(int sector,int side);
|
||||||
void play_effekt(int x,int y,int xd,int yd,int sector, int side,const TMA_SOUND *p);
|
void play_effekt(int x,int y,int xd,int yd,int sector, int side,const TMA_SOUND *p);
|
||||||
|
void change_music(const char *name);
|
||||||
|
char resolve_music_source(const char *name, TMUSIC_SOURCE *new_source, TMUSIC_SOURCE_TYPE *new_type);
|
||||||
void create_playlist(char *playlist);
|
void create_playlist(char *playlist);
|
||||||
const char *get_next_music_from_playlist(void);
|
const char *get_next_music_from_playlist(void);
|
||||||
const char * end_of_song_callback(void *ctx);
|
|
||||||
void purge_playlist(void);
|
void purge_playlist(void);
|
||||||
void play_sample_at_sector(int sample,int listener,int source,int track, char loop);
|
void play_sample_at_sector(int sample,int listener,int source,int track, char loop);
|
||||||
void play_sample_at_channel(int sample,int channel,int vol);
|
void play_sample_at_channel(int sample,int channel,int vol);
|
||||||
|
@ -1462,7 +1466,7 @@ char test_playing(int track);
|
||||||
void stop_track_free(int track);
|
void stop_track_free(int track);
|
||||||
void mute_all_tracks(char all);
|
void mute_all_tracks(char all);
|
||||||
void kill_all_sounds(void);
|
void kill_all_sounds(void);
|
||||||
void create_sound_table(char *template,int32_t size);
|
void create_sound_table(char *t,int32_t size);
|
||||||
void create_sound_table_old(void);
|
void create_sound_table_old(void);
|
||||||
void start_play_flute(char );
|
void start_play_flute(char );
|
||||||
void stop_play_flute(void);
|
void stop_play_flute(void);
|
||||||
|
|
|
@ -117,17 +117,6 @@ int32_t load_section(FILE *f,void **section, int *sct_type,int32_t *sect_size)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
static void ddl_file_deleter(void *ctx) {
|
|
||||||
ablock_free(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
TMPFILE_RD *open_ddl_file(const char *name, int group) {
|
|
||||||
int32_t size;
|
|
||||||
if (!test_file_exist(group, name)) return NULL;
|
|
||||||
const void *data = afile(name, group, &size);
|
|
||||||
if (!data) return NULL;
|
|
||||||
return temp_storage_from_binary(data, size, &ddl_file_deleter, (void *)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t load_section_mem(TMPFILE_RD *f,void **section, int *sct_type,int32_t *sect_size) {
|
int32_t load_section_mem(TMPFILE_RD *f,void **section, int *sct_type,int32_t *sect_size) {
|
||||||
int32_t s;
|
int32_t s;
|
||||||
|
|
195
game/skeldal.c
195
game/skeldal.c
|
@ -103,7 +103,8 @@ const void *pcx_8bit_decomp(const void *p, int32_t *s, int h);
|
||||||
const void *pcx_fade_decomp(const void *p, int32_t *s, int h);
|
const void *pcx_fade_decomp(const void *p, int32_t *s, int h);
|
||||||
const void *load_text_decomp(const void *p, int32_t *s, int h);
|
const void *load_text_decomp(const void *p, int32_t *s, int h);
|
||||||
|
|
||||||
static const char *patch_file=NULL;
|
static const char *patch_files[4]={NULL};
|
||||||
|
|
||||||
int cur_page=0;
|
int cur_page=0;
|
||||||
|
|
||||||
TSTR_LIST cur_config=NULL;
|
TSTR_LIST cur_config=NULL;
|
||||||
|
@ -530,6 +531,17 @@ void clrscr(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ddl_file_deleter(void *ctx) {
|
||||||
|
ablock_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
TMPFILE_RD *open_ddl_file(const char *name, int group) {
|
||||||
|
int32_t size;
|
||||||
|
if (!test_file_exist(group, name)) return NULL;
|
||||||
|
const void *data = afile(name, group, &size);
|
||||||
|
if (!data) return NULL;
|
||||||
|
return temp_storage_from_binary(data, size, &ddl_file_deleter, (void *)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -538,18 +550,6 @@ void back_music(THE_TIMER *t)
|
||||||
mix_back_sound(0);
|
mix_back_sound(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void *anim_idle(EVENT_MSG *msg,void **usr)
|
|
||||||
{
|
|
||||||
usr;
|
|
||||||
if (msg->msg==E_TIMER) calc_animations();
|
|
||||||
return &anim_idle;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*void timer_error(void)
|
|
||||||
{
|
|
||||||
puts("\x7");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
void timming(EVENT_MSG *msg,void **data)
|
void timming(EVENT_MSG *msg,void **data)
|
||||||
{
|
{
|
||||||
THE_TIMER *p,*q;
|
THE_TIMER *p,*q;
|
||||||
|
@ -881,37 +881,6 @@ const void *boldcz;
|
||||||
#define ERR_WINX 320
|
#define ERR_WINX 320
|
||||||
#define ERR_WINY 100
|
#define ERR_WINY 100
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
char device_error(int chyba,char disk,char info)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
void *old;
|
|
||||||
|
|
||||||
old=_STACKLOW;
|
|
||||||
_STACKLOW=NULL;
|
|
||||||
chyba,disk,info;
|
|
||||||
curfont=&boldcz;
|
|
||||||
charcolors[0]=0xffff;
|
|
||||||
for(c=1;c<5;c++) charcolors[c]=0x7fff;
|
|
||||||
memcpy(buffer_2nd,screen,screen_buffer_size);
|
|
||||||
trans_bar(320-ERR_WINX/2,240-ERR_WINY/2,ERR_WINX,ERR_WINY,0);
|
|
||||||
curcolor=0x7fff;
|
|
||||||
rectangle(320-ERR_WINX/2,240-ERR_WINY/2,320+ERR_WINX/2,240+ERR_WINY/2,0x7fff);
|
|
||||||
set_aligned_position(320,230,1,1,texty[8]);outtext(texty[8]);
|
|
||||||
set_aligned_position(320,250,1,1,texty[9]);outtext(texty[9]);
|
|
||||||
showview(0,0,0,0);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
c=getche();
|
|
||||||
}
|
|
||||||
while (c!=13 && c!=27);
|
|
||||||
memcpy(screen,buffer_2nd,screen_buffer_size);
|
|
||||||
showview(0,0,0,0);
|
|
||||||
_STACKLOW=old;
|
|
||||||
return (c==13?_ERR_RETRY:_ERR_FAIL);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void init_DDL_manager() {
|
void init_DDL_manager() {
|
||||||
|
|
||||||
|
@ -919,9 +888,14 @@ void init_DDL_manager() {
|
||||||
ddlfile = local_strdup(ddlfile);
|
ddlfile = local_strdup(ddlfile);
|
||||||
|
|
||||||
init_manager();
|
init_manager();
|
||||||
if (patch_file && !add_patch_file(patch_file)) {
|
for (size_t sz = countof(patch_files); sz > 0;) {
|
||||||
display_error("Can't open resource file (adv_patch): %s", ddlfile);
|
--sz;
|
||||||
abort();
|
if (patch_files[sz]) {
|
||||||
|
if (!add_patch_file(patch_files[sz])) {
|
||||||
|
display_error("Can't open resource file (adv_patch): %s", patch_files[sz]);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const char *lang_fld = lang_get_folder();
|
const char *lang_fld = lang_get_folder();
|
||||||
if (lang_fld) {
|
if (lang_fld) {
|
||||||
|
@ -981,6 +955,12 @@ void show_loading_picture(char *filename)
|
||||||
ablock_free(p);
|
ablock_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char end_of_song_callback(void *, TMUSIC_SOURCE *s, TMUSIC_SOURCE_TYPE *t) {
|
||||||
|
const char *ms = get_next_music_from_playlist();
|
||||||
|
return resolve_music_source(ms, s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void init_skeldal(const INI_CONFIG *cfg)
|
void init_skeldal(const INI_CONFIG *cfg)
|
||||||
{
|
{
|
||||||
|
@ -1173,121 +1153,7 @@ void enter_game(void)
|
||||||
if (end==255) konec_hry();
|
if (end==255) konec_hry();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*int dos58(int mode);
|
|
||||||
#pragma aux dos58=\
|
|
||||||
"mov al,1"\
|
|
||||||
"mov ah,58h"\
|
|
||||||
"int 21h"\
|
|
||||||
parm[ebx] value [eax]
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
static int do_config_skeldal(int num,int numdata,char *txt)
|
|
||||||
{
|
|
||||||
switch (num)
|
|
||||||
{
|
|
||||||
case 0:vmode=numdata;break;
|
|
||||||
case 1:zoom_speed(numdata);break;
|
|
||||||
case 2:turn_speed(numdata);break;
|
|
||||||
case 3:init_music_vol=numdata;break;
|
|
||||||
case 4:init_gfx_vol=numdata;break;
|
|
||||||
case 5:sscanf(txt,"%d %x %d %d",&snd_devnum,&snd_parm1,&snd_parm2,&snd_parm3);
|
|
||||||
sound_detection=0;
|
|
||||||
break;
|
|
||||||
case 6:snd_mixing=numdata;break;
|
|
||||||
case 7:strcopy_n(default_map,txt,20);default_map[19]='\0';break;
|
|
||||||
case 8:gamespeed=numdata;break;
|
|
||||||
case 9:level_preload=numdata;break;
|
|
||||||
// case 10:system(txt);break;
|
|
||||||
case 11:mman_patch=numdata;break;
|
|
||||||
case 12:skip_intro=numdata;break;
|
|
||||||
case 13:autosave_enabled=numdata;break;
|
|
||||||
case 14: debug_enabled=numdata;break;
|
|
||||||
case 15:full_video=numdata;break;
|
|
||||||
case 16:patch_file=getmem(strlen(txt)+1);
|
|
||||||
strcpy(patch_file,txt);
|
|
||||||
txt=strchr(patch_file,'\n');if (txt!=NULL) txt[0]=0;
|
|
||||||
break;
|
|
||||||
case 17:titles_on=numdata;break;
|
|
||||||
case 18:charmin=numdata;break;
|
|
||||||
case 19:charmax=numdata;break;
|
|
||||||
case 20:game_extras=numdata;break;
|
|
||||||
case 21:windowed=numdata;break;
|
|
||||||
case 22:gamespeedbattle=numdata;break;
|
|
||||||
case 23:windowedzoom=numdata;break;
|
|
||||||
case 24:monitor=numdata;break;
|
|
||||||
case 25:if (VERSIONNUM<numdata)
|
|
||||||
display_error("Pozor! Hra je starsi verze, nez vyzaduje dobrodruzstvi. Ve vlastnim zajmu si stahnete novou verzi, protoze toto dobrodruzstvi nemusi byt s aktualni verzi dohratelne");
|
|
||||||
break;
|
|
||||||
case 26:refresh=numdata;break;
|
|
||||||
default:num-=CESTY_POS;
|
|
||||||
gpathtable[num] = strdup(txt);
|
|
||||||
SEND_LOG("(GAME) Directory '%s' has been assigned to group nb. %d",txt,num);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
static void config_skeldal(const char *line)
|
|
||||||
{
|
|
||||||
int ndata=0,i,maxi;
|
|
||||||
|
|
||||||
char *data=0;char *c;
|
|
||||||
|
|
||||||
c=strchr(line,' ');if (c==NULL) return;
|
|
||||||
c++;
|
|
||||||
maxi=strlen(c);
|
|
||||||
data=alloca(maxi+1);
|
|
||||||
strcpy(data,c);
|
|
||||||
while (maxi && (isspace(data[maxi-1]))) {
|
|
||||||
--maxi;
|
|
||||||
data[maxi]=0;
|
|
||||||
}
|
|
||||||
maxi=(sizeof(sinit)/sizeof(INIS));
|
|
||||||
for(i=0;i<maxi;i++) if (comcmp(line,sinit[i].heslo)) break;
|
|
||||||
if (i==maxi)
|
|
||||||
{
|
|
||||||
char s[256];
|
|
||||||
i=data-line;
|
|
||||||
|
|
||||||
strcpy(s,"Chyba v INI souboru: Neznama promenna - ");
|
|
||||||
strncat(s,line,i);
|
|
||||||
SEND_LOG("(ERROR) %s",s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (sinit[i].parmtype==INI_INT) if (sscanf(data,"%d",&ndata)!=1)
|
|
||||||
{
|
|
||||||
char s[256];
|
|
||||||
|
|
||||||
sprintf(s,"Chyba v INI souboru: Ocekava se ciselna hodnota\n%s\n",line);
|
|
||||||
SEND_LOG("(ERROR) %s",s);
|
|
||||||
}
|
|
||||||
do_config_skeldal(i,ndata,data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
static void configure(char *filename)
|
|
||||||
{
|
|
||||||
SEND_LOG("(GAME) Reading config. file '%s'",filename);
|
|
||||||
cur_config=read_config(filename);
|
|
||||||
if (cur_config==NULL)
|
|
||||||
{
|
|
||||||
char s[256];
|
|
||||||
|
|
||||||
sprintf(s,"\nNemohu precist konfiguracni soubor \"%s\".\n",filename);
|
|
||||||
SEND_LOG("(ERROR) %s",s);
|
|
||||||
puts(s);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
process_ini(cur_config,config_skeldal);
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
static int update_config(void)
|
static int update_config(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1314,6 +1180,7 @@ void set_verify(char state);
|
||||||
*/
|
*/
|
||||||
void play_movie_seq(const char *s,int y)
|
void play_movie_seq(const char *s,int y)
|
||||||
{
|
{
|
||||||
|
change_music(NULL);
|
||||||
play_animation(s,0,y,0);
|
play_animation(s,0,y,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1647,7 +1514,7 @@ const char *configure_pathtable(const INI_CONFIG *cfg) {
|
||||||
if (defmap) {
|
if (defmap) {
|
||||||
strcopy_n(default_map, defmap, sizeof(default_map));
|
strcopy_n(default_map, defmap, sizeof(default_map));
|
||||||
}
|
}
|
||||||
patch_file = ini_get_string(paths, "patch_file", NULL);
|
patch_files[0] = ini_get_string(paths, "patch_file", NULL);
|
||||||
if (ini_get_boolean(paths, "patch_mode", 0)) {
|
if (ini_get_boolean(paths, "patch_mode", 0)) {
|
||||||
mman_patch = 1;
|
mman_patch = 1;
|
||||||
}
|
}
|
||||||
|
@ -1721,6 +1588,10 @@ int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (start_cfg->patch_file) {
|
||||||
|
patch_files[1] = start_cfg->patch_file;
|
||||||
|
}
|
||||||
|
|
||||||
if (start_cfg->adventure_path) {
|
if (start_cfg->adventure_path) {
|
||||||
TSTR_LIST adv_config=read_config(start_cfg->adventure_path);
|
TSTR_LIST adv_config=read_config(start_cfg->adventure_path);
|
||||||
if (!adv_config) {
|
if (!adv_config) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ typedef struct {
|
||||||
const char *adventure_path;
|
const char *adventure_path;
|
||||||
const char *config_path;
|
const char *config_path;
|
||||||
const char *lang_path;
|
const char *lang_path;
|
||||||
|
const char *patch_file;
|
||||||
|
|
||||||
|
|
||||||
} SKELDAL_CONFIG;
|
} SKELDAL_CONFIG;
|
||||||
|
|
|
@ -498,9 +498,6 @@ void create_playlist(char *playlist)
|
||||||
playing_track=-1;
|
playing_track=-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * end_of_song_callback(void *ctx) {
|
|
||||||
return get_next_music_from_playlist();
|
|
||||||
}
|
|
||||||
const char *get_next_music_from_playlist()
|
const char *get_next_music_from_playlist()
|
||||||
{
|
{
|
||||||
int i,step;
|
int i,step;
|
||||||
|
@ -520,10 +517,7 @@ const char *get_next_music_from_playlist()
|
||||||
}
|
}
|
||||||
while (step);
|
while (step);
|
||||||
playing_track=i;
|
playing_track=i;
|
||||||
const char *d = build_pathname(2, gpathtable[SR_MUSIC], cur_playlist[i]+1);
|
const char *d = cur_playlist[i]+1;
|
||||||
if (!check_file_exists(d)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
cur_playlist[i][0]=33;
|
cur_playlist[i][0]=33;
|
||||||
remain_play--;
|
remain_play--;
|
||||||
return d;
|
return d;
|
||||||
|
@ -722,3 +716,37 @@ char enable_sound(char enbl)
|
||||||
SEND_LOG("(SOUND) Sound status (en/dis) changed: new %d, old %d",enbl,save);
|
SEND_LOG("(SOUND) Sound status (en/dis) changed: new %d, old %d",enbl,save);
|
||||||
return save;
|
return save;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void change_music(const char *name) {
|
||||||
|
TMUSIC_SOURCE src;
|
||||||
|
TMUSIC_SOURCE_TYPE t;
|
||||||
|
if (resolve_music_source(name, &src, &t)) {
|
||||||
|
play_music(&src, t);
|
||||||
|
} else {
|
||||||
|
stop_play_music();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void music_destructor(TMUSIC_SOURCE *me) {
|
||||||
|
afile_mapped_free(me->data, me->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
char resolve_music_source(const char *name, TMUSIC_SOURCE *new_source, TMUSIC_SOURCE_TYPE *new_type) {
|
||||||
|
if (name == NULL || !test_file_exist(SR_MUSIC, name)) return 0;
|
||||||
|
int32_t sz;
|
||||||
|
size_t l = strlen(name);
|
||||||
|
if (l<4) return 0;
|
||||||
|
|
||||||
|
if (istrcmp(name+l-4, ".MUS") == 0) *new_type = MUSIC_SOURCE_MUS;
|
||||||
|
else if (istrcmp(name+l-4, ".MP3") == 0) *new_type = MUSIC_SOURCE_MP3;
|
||||||
|
else return 0;
|
||||||
|
|
||||||
|
const void *v = afile_mapped(name, SR_MUSIC, &sz);
|
||||||
|
new_source->data = v;
|
||||||
|
new_source->size = sz;
|
||||||
|
new_source->destructor = music_destructor;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ SET(files basicobj.c
|
||||||
wav_mem.c
|
wav_mem.c
|
||||||
strlite.c
|
strlite.c
|
||||||
cztable.c
|
cztable.c
|
||||||
|
minimp3.c
|
||||||
music.cpp
|
music.cpp
|
||||||
string_table.cpp )
|
string_table.cpp )
|
||||||
|
|
||||||
|
|
|
@ -334,6 +334,12 @@ int test_file_exist(int group,const char *filename)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int file_is_in_ddl(int group, const char *filename) {
|
||||||
|
THANDLE_DATA h;
|
||||||
|
return get_file_entry(group, filename, &h);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
THANDLE_DATA *def_handle(int handle,const char *filename,ABLOCK_DECODEPROC decompress,char path)
|
THANDLE_DATA *def_handle(int handle,const char *filename,ABLOCK_DECODEPROC decompress,char path)
|
||||||
{
|
{
|
||||||
THANDLE_DATA *h;
|
THANDLE_DATA *h;
|
||||||
|
@ -369,11 +375,11 @@ THANDLE_DATA *def_handle(int handle,const char *filename,ABLOCK_DECODEPROC decom
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
const void *afile(const char *filename,int group,int32_t *blocksize)
|
static const void *afile2(const char *filename,int group,int32_t *blocksize, char mapped)
|
||||||
{
|
{
|
||||||
char *d;
|
char *d;
|
||||||
char entr;
|
char entr;
|
||||||
void *p;
|
const void *p;
|
||||||
|
|
||||||
d=alloca(strlen(filename)+1);
|
d=alloca(strlen(filename)+1);
|
||||||
strcpy(d,filename);
|
strcpy(d,filename);
|
||||||
|
@ -388,18 +394,36 @@ const void *afile(const char *filename,int group,int32_t *blocksize)
|
||||||
*blocksize = *szptr;
|
*blocksize = *szptr;
|
||||||
return szptr+1;
|
return szptr+1;
|
||||||
}
|
}
|
||||||
else if (mman_pathlist!=NULL)
|
else if (mman_pathlist!=NULL) {
|
||||||
{
|
|
||||||
const char *name = build_pathname(2,mman_pathlist[group],d);
|
const char *name = build_pathname(2,mman_pathlist[group],d);
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
SEND_LOG("(LOAD) Afile is loading file '%s' from disk (group %d)",d,group);
|
SEND_LOG("(LOAD) Afile is loading file '%s' from disk (group %d)",d,group);
|
||||||
p=load_file(name, &sz);
|
if (mapped) {
|
||||||
*blocksize=sz;
|
const char *iname = file_icase_find(name);
|
||||||
|
p = map_file_to_memory(iname, &sz);
|
||||||
|
*blocksize = sz;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p=load_file(name, &sz);
|
||||||
|
*blocksize=sz;
|
||||||
}
|
}
|
||||||
else return NULL;
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *afile(const char *filename,int group,int32_t *blocksize) {
|
||||||
|
return afile2(filename, group, blocksize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *afile_mapped(const char *filename,int group,int32_t *blocksize) {
|
||||||
|
return afile2(filename, group, blocksize, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void *afile_copy(const char *filename,int group,int32_t *blocksize) {
|
void *afile_copy(const char *filename,int group,int32_t *blocksize) {
|
||||||
const void *ptr = afile(filename, group, blocksize);
|
const void *ptr = afile(filename, group, blocksize);
|
||||||
|
@ -721,3 +745,8 @@ int32_t get_handle_size(int handle)
|
||||||
void ablock_free(const void *ptr) {
|
void ablock_free(const void *ptr) {
|
||||||
if (need_to_be_free(ptr)) free((void *)ptr);
|
if (need_to_be_free(ptr)) free((void *)ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void afile_mapped_free(const void *ptr, int32_t sz) {
|
||||||
|
if (need_to_be_free(ptr)) unmap_file(ptr, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,12 +96,18 @@ THANDLE_DATA *zneplatnit_block(int handle); //zneplatni data bloku
|
||||||
THANDLE_DATA *get_handle(int handle); //vraci informace o rukojeti
|
THANDLE_DATA *get_handle(int handle); //vraci informace o rukojeti
|
||||||
int find_handle(const char *name,ABLOCK_DECODEPROC decomp); //hleda mezi rukojeti stejnou definici
|
int find_handle(const char *name,ABLOCK_DECODEPROC decomp); //hleda mezi rukojeti stejnou definici
|
||||||
int test_file_exist(int group,const char *filename); //testuje zda soubor existuje v ramci mmanageru
|
int test_file_exist(int group,const char *filename); //testuje zda soubor existuje v ramci mmanageru
|
||||||
|
int file_is_in_ddl(int group, const char *filename); //testuje zde je soubor v DDL
|
||||||
const void *afile(const char *filename,int group,int32_t *blocksize); //nahraje do pameti soubor registrovany v ramci mmanageru
|
const void *afile(const char *filename,int group,int32_t *blocksize); //nahraje do pameti soubor registrovany v ramci mmanageru
|
||||||
void *afile_copy(const char *filename,int group,int32_t *blocksize); //nahraje do pameti soubor registrovany v ramci mmanageru
|
void *afile_copy(const char *filename,int group,int32_t *blocksize); //nahraje do pameti soubor registrovany v ramci mmanageru
|
||||||
int32_t get_handle_size(int handle);
|
int32_t get_handle_size(int handle);
|
||||||
//void get_mem_info(MEMORYSTATUS *mem);
|
//void get_mem_info(MEMORYSTATUS *mem);
|
||||||
void ablock_free(const void *ptr);
|
void ablock_free(const void *ptr);
|
||||||
|
|
||||||
|
//access file using memory mapping feature
|
||||||
|
const void *afile_mapped(const char *filename,int group,int32_t *blocksize);
|
||||||
|
//free file memory opened by afile_mapped
|
||||||
|
void afile_mapped_free(const void *ptr, int32_t sz);
|
||||||
|
|
||||||
|
|
||||||
int read_group(int index);
|
int read_group(int index);
|
||||||
char add_patch_file(const char *filename); //pripojuje zaplatu
|
char add_patch_file(const char *filename); //pripojuje zaplatu
|
||||||
|
|
|
@ -185,8 +185,7 @@ void BigPlayProc(MGIF_HEADER_T *hdr,int act,const void *data,int csize)
|
||||||
void play_animation(const char *filename,char mode,int posy,char sound)
|
void play_animation(const char *filename,char mode,int posy,char sound)
|
||||||
{
|
{
|
||||||
size_t sz;
|
size_t sz;
|
||||||
void *mgf=map_file_to_memory(file_icase_find(filename), &sz);
|
const void *mgf=map_file_to_memory(file_icase_find(filename), &sz);
|
||||||
change_music(NULL);
|
|
||||||
if (mgf==NULL) return;
|
if (mgf==NULL) return;
|
||||||
game_display_disable_crt_effect_temporary(1);
|
game_display_disable_crt_effect_temporary(1);
|
||||||
PlayMGFFile(mgf,BigPlayProc,posy,mode & 0x80);
|
PlayMGFFile(mgf,BigPlayProc,posy,mode & 0x80);
|
||||||
|
|
3
libs/minimp3.c
Normal file
3
libs/minimp3.c
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define MINIMP3_IMPLEMENTATION
|
||||||
|
#define MINIMP3_ONLY_MP3
|
||||||
|
#include "minimp3.h"
|
1865
libs/minimp3.h
Normal file
1865
libs/minimp3.h
Normal file
File diff suppressed because it is too large
Load diff
148
libs/music.cpp
148
libs/music.cpp
|
@ -1,8 +1,10 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "music.h"
|
#include "music.h"
|
||||||
|
#include "minimp3.h"
|
||||||
#include <platform/platform.h>
|
#include <platform/platform.h>
|
||||||
|
|
||||||
|
#include "memman.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -10,30 +12,40 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct MResDeleter {
|
||||||
|
TMUSIC_SOURCE src;
|
||||||
|
void operator()(const void *ptr) {
|
||||||
|
src.destructor(&src);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using MusicData = std::unique_ptr<const void, MResDeleter>;
|
||||||
|
|
||||||
|
|
||||||
class MUSStreamParser: public IMusicStream {
|
class MUSStreamParser: public IMusicStream {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MUSStreamParser(const char *name) {
|
MUSStreamParser(const TMUSIC_SOURCE *src)
|
||||||
_data = map_file_to_memory(file_icase_find(name), &sz);
|
:_mdata(src->data, {*src}) {
|
||||||
if (_data) {
|
|
||||||
_loaded = true;
|
if (_mdata) {
|
||||||
iter = reinterpret_cast<const uint8_t *>(_data);
|
_data = _mdata.get();
|
||||||
chans = read_short();
|
if (_data) {
|
||||||
freq = read_int();
|
_loaded = true;
|
||||||
iter += 4;
|
iter = reinterpret_cast<const uint8_t *>(_data);
|
||||||
blocks = read_int();
|
chans = read_short();
|
||||||
iter += 8;
|
freq = read_int();
|
||||||
btable = reinterpret_cast<const short *>(iter);
|
iter += 4;
|
||||||
iter += 512;
|
blocks = read_int();
|
||||||
|
iter += 8;
|
||||||
|
btable = reinterpret_cast<const short *>(iter);
|
||||||
|
iter += 512;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~MUSStreamParser() {
|
|
||||||
if (_data) unmap_file(_data, sz);
|
|
||||||
}
|
|
||||||
MUSStreamParser(const MUSStreamParser &) = delete;
|
MUSStreamParser(const MUSStreamParser &) = delete;
|
||||||
MUSStreamParser& operator=(const MUSStreamParser &) = delete;
|
MUSStreamParser& operator=(const MUSStreamParser &) = delete;
|
||||||
|
|
||||||
|
@ -60,8 +72,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _loaded = false;
|
bool _loaded = false;
|
||||||
void *_data;
|
MusicData _mdata;
|
||||||
std::size_t sz;
|
const void *_data;
|
||||||
|
|
||||||
std::int16_t chans;
|
std::int16_t chans;
|
||||||
std::int32_t freq;
|
std::int32_t freq;
|
||||||
|
@ -111,6 +123,85 @@ protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MP3StreamParser: public IMusicStream {
|
||||||
|
public:
|
||||||
|
MP3StreamParser(const TMUSIC_SOURCE *src)
|
||||||
|
:_data(src->data, {*src})
|
||||||
|
,_mp3_size(src->size) {
|
||||||
|
|
||||||
|
|
||||||
|
if (_data && find_music_info()) {
|
||||||
|
_info.format = 2;
|
||||||
|
_loaded = true;
|
||||||
|
mp3dec_init(&dec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string_view read() override {
|
||||||
|
if (!_put_back_buffer.empty() || _eof) return std::exchange(_put_back_buffer, {});
|
||||||
|
while (_mp3_offset < _mp3_size) {
|
||||||
|
mp3dec_frame_info_t frame_info;
|
||||||
|
int samples = mp3dec_decode_frame(&dec,
|
||||||
|
reinterpret_cast<const uint8_t *>(_data.get())+_mp3_offset,
|
||||||
|
_mp3_size - _mp3_offset, pcm_buffer,&frame_info);
|
||||||
|
|
||||||
|
if (samples == 0) {
|
||||||
|
// Nenalezen platný frame, posuneme se o 1 bajt a zkusíme dál
|
||||||
|
_mp3_offset++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mp3_offset += frame_info.frame_bytes ;
|
||||||
|
|
||||||
|
size_t data_size = samples* frame_info.channels * sizeof(mp3d_sample_t);
|
||||||
|
|
||||||
|
return std::string_view(reinterpret_cast<const char*>(pcm_buffer), data_size);
|
||||||
|
}
|
||||||
|
_eof = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
virtual void put_back(std::string_view data) override {
|
||||||
|
_put_back_buffer = data;
|
||||||
|
}
|
||||||
|
virtual TMUSIC_STREAM_INFO get_info() const override {
|
||||||
|
return _info;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_loaded() const {return _loaded;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MusicData _data;
|
||||||
|
size_t _mp3_size;
|
||||||
|
size_t _mp3_offset = 0;
|
||||||
|
TMUSIC_STREAM_INFO _info = {};
|
||||||
|
mp3dec_t dec{};
|
||||||
|
|
||||||
|
std::string_view _put_back_buffer = {};
|
||||||
|
mp3d_sample_t pcm_buffer[MINIMP3_MAX_SAMPLES_PER_FRAME] = {};
|
||||||
|
bool _eof = false;
|
||||||
|
bool _loaded = false;
|
||||||
|
|
||||||
|
bool find_music_info() {
|
||||||
|
mp3dec_t tmpdec{};
|
||||||
|
mp3dec_init(&tmpdec);
|
||||||
|
size_t ofs = 0;
|
||||||
|
size_t max_ofs = std::min<size_t>(_mp3_size,4096);
|
||||||
|
mp3dec_frame_info_t frame_info;
|
||||||
|
while (ofs < max_ofs) {
|
||||||
|
int samples = mp3dec_decode_frame(&tmpdec,
|
||||||
|
reinterpret_cast<const uint8_t *>(_data.get())+ofs,
|
||||||
|
_mp3_size-ofs, pcm_buffer, &frame_info);
|
||||||
|
if (samples > 0) {
|
||||||
|
_info.freq = frame_info.hz;
|
||||||
|
_info.channels = frame_info.channels;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
++ofs;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void music_close(TMUSIC_STREAM *stream) {
|
void music_close(TMUSIC_STREAM *stream) {
|
||||||
if (stream) {
|
if (stream) {
|
||||||
|
@ -119,13 +210,31 @@ void music_close(TMUSIC_STREAM *stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TMUSIC_STREAM *music_open(const char *filename) {
|
TMUSIC_STREAM *music_open_mus(const TMUSIC_SOURCE *src) {
|
||||||
MUSStreamParser *player = new MUSStreamParser(filename);
|
auto player = new MUSStreamParser(src);
|
||||||
if (player->is_loaded()) return player;
|
if (player->is_loaded()) return player;
|
||||||
delete player;
|
delete player;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TMUSIC_STREAM *music_open_mp3(const TMUSIC_SOURCE *src) {
|
||||||
|
auto player = new MP3StreamParser(src);
|
||||||
|
if (player->is_loaded()) return player;
|
||||||
|
delete player;
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TMUSIC_STREAM *music_open(const TMUSIC_SOURCE *source, TMUSIC_SOURCE_TYPE t) {
|
||||||
|
if (t == MUSIC_SOURCE_MUS) {
|
||||||
|
return music_open_mus(source);
|
||||||
|
} else {
|
||||||
|
return music_open_mp3(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TMUSIC_STREAM_CHUNK music_read(TMUSIC_STREAM *stream) {
|
TMUSIC_STREAM_CHUNK music_read(TMUSIC_STREAM *stream) {
|
||||||
TMUSIC_STREAM_CHUNK r = {NULL,0};
|
TMUSIC_STREAM_CHUNK r = {NULL,0};
|
||||||
if (stream) {
|
if (stream) {
|
||||||
|
@ -157,4 +266,3 @@ TMUSIC_STREAM_INFO music_get_info(const TMUSIC_STREAM *stream) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
libs/music.h
31
libs/music.h
|
@ -5,6 +5,17 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum music_source_type {
|
||||||
|
MUSIC_SOURCE_MUS,
|
||||||
|
MUSIC_SOURCE_MP3
|
||||||
|
} TMUSIC_SOURCE_TYPE;
|
||||||
|
|
||||||
|
typedef struct music_source_t {
|
||||||
|
const void *data;
|
||||||
|
size_t size;
|
||||||
|
void (*destructor)(struct music_source_t *me);
|
||||||
|
} TMUSIC_SOURCE;
|
||||||
|
|
||||||
typedef struct music_stream_t {
|
typedef struct music_stream_t {
|
||||||
char dummy;
|
char dummy;
|
||||||
} TMUSIC_STREAM;
|
} TMUSIC_STREAM;
|
||||||
|
@ -23,8 +34,23 @@ typedef struct music_stream_chunk_t {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///open music stream
|
|
||||||
TMUSIC_STREAM *music_open(const char *filename);
|
///open music stream MUS file
|
||||||
|
/**
|
||||||
|
* @param source source descriptor - it is copied into reader
|
||||||
|
* @return music stream if valid, or NULL, if not
|
||||||
|
*/
|
||||||
|
TMUSIC_STREAM *music_open_mus(const TMUSIC_SOURCE *source);
|
||||||
|
|
||||||
|
///open music stream MP3 file
|
||||||
|
/**
|
||||||
|
* @param source source descriptor - it is copied into reader
|
||||||
|
* @return music stream if valid, or NULL, if not
|
||||||
|
*/
|
||||||
|
TMUSIC_STREAM *music_open_mp3(const TMUSIC_SOURCE *source);
|
||||||
|
|
||||||
|
TMUSIC_STREAM *music_open(const TMUSIC_SOURCE *source, TMUSIC_SOURCE_TYPE type);
|
||||||
|
|
||||||
///retrieve information
|
///retrieve information
|
||||||
TMUSIC_STREAM_INFO music_get_info(const TMUSIC_STREAM *stream);
|
TMUSIC_STREAM_INFO music_get_info(const TMUSIC_STREAM *stream);
|
||||||
|
|
||||||
|
@ -38,6 +64,7 @@ void music_put_back_chunk(TMUSIC_STREAM *stream, const TMUSIC_STREAM_CHUNK *chun
|
||||||
void music_close(TMUSIC_STREAM *stream);
|
void music_close(TMUSIC_STREAM *stream);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,11 @@ void show_help(const char *arg0) {
|
||||||
"\n"
|
"\n"
|
||||||
"Usage:"
|
"Usage:"
|
||||||
);
|
);
|
||||||
printf("%s [-f <file>] [-a <file>] [-l <lang>] [-s <dir>] [-h]\n\n", arg0);
|
printf("%s [-f <file>] [-a <file>] [-p <file> ] [-l <lang>] [-s <dir>] [-h]\n\n", arg0);
|
||||||
|
|
||||||
printf("-f <file> path to configuration file\n"
|
printf("-f <file> path to configuration file\n"
|
||||||
"-a <adv> path for adventure file (.adv)\n"
|
"-a <adv> path for adventure file (.adv)\n"
|
||||||
|
"-p <file> patch data with custom DDL\n"
|
||||||
"-l <lang> set language (cz|en)\n"
|
"-l <lang> set language (cz|en)\n"
|
||||||
"-s <directory> generate string-tables (for localization) and exit\n"
|
"-s <directory> generate string-tables (for localization) and exit\n"
|
||||||
"-h this help\n");
|
"-h this help\n");
|
||||||
|
@ -33,12 +34,14 @@ int main(int argc, char **argv) {
|
||||||
std::string config_name = SKELDALINI;
|
std::string config_name = SKELDALINI;
|
||||||
std::string adv_config_file;
|
std::string adv_config_file;
|
||||||
std::string gen_stringtable_path;
|
std::string gen_stringtable_path;
|
||||||
|
std::string patch;
|
||||||
std::string lang;
|
std::string lang;
|
||||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:")) != -1; ) {
|
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:p:")) != -1; ) {
|
||||||
switch (optchr) {
|
switch (optchr) {
|
||||||
case 'f': config_name = optarg;break;
|
case 'f': config_name = optarg;break;
|
||||||
case 'a': adv_config_file = optarg;break;
|
case 'a': adv_config_file = optarg;break;
|
||||||
case 'h': show_help(argv[0]);break;
|
case 'h': show_help(argv[0]);break;
|
||||||
|
case 'p': patch = optarg; break;
|
||||||
case 'l': lang = optarg;break;
|
case 'l': lang = optarg;break;
|
||||||
case 's': gen_stringtable_path = optarg;break;
|
case 's': gen_stringtable_path = optarg;break;
|
||||||
default: show_help_short();
|
default: show_help_short();
|
||||||
|
@ -54,6 +57,7 @@ int main(int argc, char **argv) {
|
||||||
cfg.adventure_path = adv_config_file.empty()?NULL:adv_config_file.c_str();
|
cfg.adventure_path = adv_config_file.empty()?NULL:adv_config_file.c_str();
|
||||||
cfg.config_path = config_name.c_str();
|
cfg.config_path = config_name.c_str();
|
||||||
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
||||||
|
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!gen_stringtable_path.empty()) {
|
if (!gen_stringtable_path.empty()) {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
// Funkce pro mapování souboru do paměti
|
// Funkce pro mapování souboru do paměti
|
||||||
void* map_file_to_memory(const char *name, size_t *sz) {
|
const void* map_file_to_memory(const char *name, size_t *sz) {
|
||||||
if (!name || !sz) {
|
if (!name || !sz) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,13 @@ void* map_file_to_memory(const char *name, size_t *sz) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funkce pro zrušení mapování
|
// Funkce pro zrušení mapování
|
||||||
void unmap_file(void *ptr, size_t sz) {
|
void unmap_file(const void *ptr, size_t sz) {
|
||||||
if (!ptr || sz == 0) {
|
if (!ptr || sz == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zrušení mapování
|
// Zrušení mapování
|
||||||
if (munmap(ptr, sz) == -1) {
|
if (munmap((void *)ptr, sz) == -1) {
|
||||||
perror("Chyba při rušení mapování");
|
perror("Failed to unmap file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *map_file_to_memory(const char *name, size_t *sz);
|
const void *map_file_to_memory(const char *name, size_t *sz);
|
||||||
void unmap_file(void *ptr, size_t sz);
|
void unmap_file(const void *ptr, size_t sz);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,8 @@ char change_current_directory(const char *path);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void *map_file_to_memory(const char *name, size_t *sz);
|
const void *map_file_to_memory(const char *name, size_t *sz);
|
||||||
void unmap_file(void *ptr, size_t sz);
|
void unmap_file(const void *ptr, size_t sz);
|
||||||
|
|
||||||
char copy_text_to_clipboard(const char *);
|
char copy_text_to_clipboard(const char *);
|
||||||
|
|
||||||
|
|
|
@ -130,10 +130,10 @@ size_t copy_to_music_buffer(const void *data, size_t data_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char * (*end_of_song_callback)(void *ctx) = NULL;
|
static TEND_OF_SONG_CALLBACK end_of_song_callback;
|
||||||
static void *end_of_song_callback_ctx = NULL;
|
static void *end_of_song_callback_ctx = NULL;
|
||||||
|
|
||||||
void set_end_of_song_callback(const char * (*cb)(void *), void *ctx) {
|
void set_end_of_song_callback(TEND_OF_SONG_CALLBACK cb, void *ctx) {
|
||||||
end_of_song_callback = cb;
|
end_of_song_callback = cb;
|
||||||
end_of_song_callback_ctx = ctx;
|
end_of_song_callback_ctx = ctx;
|
||||||
}
|
}
|
||||||
|
@ -191,9 +191,9 @@ void create_new_music_track(int freq, int buffsize) {
|
||||||
music_buffer_write_pos = buffsize/2;
|
music_buffer_write_pos = buffsize/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unique_ptr<IMusicStream> load_music_ex(const char *name) {
|
static std::unique_ptr<IMusicStream> load_music_ex(const TMUSIC_SOURCE *src, TMUSIC_SOURCE_TYPE type) {
|
||||||
if (name) {
|
if (src) {
|
||||||
TMUSIC_STREAM *stream = music_open(name);
|
TMUSIC_STREAM *stream = music_open(src, type);
|
||||||
if (stream) {
|
if (stream) {
|
||||||
TMUSIC_STREAM_INFO nfo = music_get_info(stream);
|
TMUSIC_STREAM_INFO nfo = music_get_info(stream);
|
||||||
if (nfo.channels != 2) {
|
if (nfo.channels != 2) {
|
||||||
|
@ -212,8 +212,10 @@ static std::unique_ptr<IMusicStream> load_music_ex(const char *name) {
|
||||||
static void handle_end_of_song() {
|
static void handle_end_of_song() {
|
||||||
current_music.reset();
|
current_music.reset();
|
||||||
if (end_of_song_callback != NULL) {
|
if (end_of_song_callback != NULL) {
|
||||||
const char *new_music = end_of_song_callback(end_of_song_callback_ctx);
|
TMUSIC_SOURCE src;
|
||||||
current_music = load_music_ex(new_music);
|
TMUSIC_SOURCE_TYPE type;
|
||||||
|
char ok = end_of_song_callback(end_of_song_callback_ctx, &src, &type);
|
||||||
|
current_music = ok?load_music_ex(&src, type):std::unique_ptr<IMusicStream>{};
|
||||||
if (current_music) {
|
if (current_music) {
|
||||||
auto nfo = current_music->get_info();
|
auto nfo = current_music->get_info();
|
||||||
create_new_music_track(nfo.freq, BACK_BUFF_SIZE);
|
create_new_music_track(nfo.freq, BACK_BUFF_SIZE);
|
||||||
|
@ -246,13 +248,16 @@ int mix_back_sound(int _) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//int open_backsound(char *filename);
|
void stop_play_music() {
|
||||||
void change_music(const char *filename) {
|
|
||||||
if (music_source) {
|
if (music_source) {
|
||||||
fade_music();
|
fade_music();
|
||||||
stop_music();
|
stop_music();
|
||||||
}
|
}
|
||||||
current_music = load_music_ex(filename);
|
}
|
||||||
|
|
||||||
|
void play_music(const TMUSIC_SOURCE *source, TMUSIC_SOURCE_TYPE type) {
|
||||||
|
stop_play_music();
|
||||||
|
current_music = load_music_ex(source, type);
|
||||||
if (current_music) {
|
if (current_music) {
|
||||||
auto nfo = current_music->get_info();
|
auto nfo = current_music->get_info();
|
||||||
create_new_music_track(nfo.freq, BACK_BUFF_SIZE);
|
create_new_music_track(nfo.freq, BACK_BUFF_SIZE);
|
||||||
|
|
|
@ -24,14 +24,19 @@ SND_MAXFUNCT} AUDIO_PROPERTY;
|
||||||
|
|
||||||
void game_sound_init_device(const INI_CONFIG_SECTION *audio_section);
|
void game_sound_init_device(const INI_CONFIG_SECTION *audio_section);
|
||||||
|
|
||||||
|
|
||||||
|
typedef char (*TEND_OF_SONG_CALLBACK)(void *ctx, TMUSIC_SOURCE *, TMUSIC_SOURCE_TYPE *);
|
||||||
|
|
||||||
|
|
||||||
char start_mixing();
|
char start_mixing();
|
||||||
void stop_mixing();
|
void stop_mixing();
|
||||||
void play_sample(int channel,const void *sample,int32_t size,int32_t lstart,int32_t sfreq,int type);
|
void play_sample(int channel,const void *sample,int32_t size,int32_t lstart,int32_t sfreq,int type);
|
||||||
void set_channel_volume(int channel,int left,int right);
|
void set_channel_volume(int channel,int left,int right);
|
||||||
void set_end_of_song_callback(const char * (*cb)(void *), void *ctx);
|
void set_end_of_song_callback(TEND_OF_SONG_CALLBACK cb, void *ctx);
|
||||||
|
void play_music(const TMUSIC_SOURCE *source, TMUSIC_SOURCE_TYPE type);
|
||||||
|
void stop_play_music();
|
||||||
void fade_music();
|
void fade_music();
|
||||||
int mix_back_sound(int synchro);
|
int mix_back_sound(int synchro);
|
||||||
void change_music(const char *filename);
|
|
||||||
char get_channel_state(int channel);
|
char get_channel_state(int channel);
|
||||||
void get_channel_volume(int channel,int *left,int *right);
|
void get_channel_volume(int channel,int *left,int *right);
|
||||||
void mute_channel(int channel);
|
void mute_channel(int channel);
|
||||||
|
|
|
@ -21,6 +21,7 @@ void show_help(std::ostream &out, const char *arg0) {
|
||||||
out << arg0 << " [-f <file>] [-a <file>] [-l <lang>] [-s <dir>] [-h]\n\n";
|
out << arg0 << " [-f <file>] [-a <file>] [-l <lang>] [-s <dir>] [-h]\n\n";
|
||||||
out << "-f <file> path to configuration file\n"
|
out << "-f <file> path to configuration file\n"
|
||||||
"-a <adv> path for adventure file (.adv)\n"
|
"-a <adv> path for adventure file (.adv)\n"
|
||||||
|
"-p <file> patch data with custom DDL\n"
|
||||||
"-l <lang> set language (cz|en)\n"
|
"-l <lang> set language (cz|en)\n"
|
||||||
"-s <directory> generate string-tables (for localization) and exit\n"
|
"-s <directory> generate string-tables (for localization) and exit\n"
|
||||||
"-h this help\n";
|
"-h this help\n";
|
||||||
|
@ -36,12 +37,14 @@ int main(int argc, char **argv) {
|
||||||
std::string adv_config_file;
|
std::string adv_config_file;
|
||||||
std::string gen_stringtable_path;
|
std::string gen_stringtable_path;
|
||||||
std::string lang;
|
std::string lang;
|
||||||
|
std::string patch;
|
||||||
std::ostringstream console;
|
std::ostringstream console;
|
||||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:")) != -1; ) {
|
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:p:")) != -1; ) {
|
||||||
switch (optchr) {
|
switch (optchr) {
|
||||||
case 'f': config_name = optarg;break;
|
case 'f': config_name = optarg;break;
|
||||||
case 'a': adv_config_file = optarg;break;
|
case 'a': adv_config_file = optarg;break;
|
||||||
case 'h': show_help(console, argv[0]);break;
|
case 'h': show_help(console, argv[0]);break;
|
||||||
|
case 'p': patch = optarg; break;
|
||||||
case 'l': lang = optarg;break;
|
case 'l': lang = optarg;break;
|
||||||
case 's': gen_stringtable_path = optarg;break;
|
case 's': gen_stringtable_path = optarg;break;
|
||||||
default: show_help_short(console);break;
|
default: show_help_short(console);break;
|
||||||
|
@ -64,6 +67,7 @@ int main(int argc, char **argv) {
|
||||||
cfg.adventure_path = adv_config_file.empty()?NULL:adv_config_file.c_str();
|
cfg.adventure_path = adv_config_file.empty()?NULL:adv_config_file.c_str();
|
||||||
cfg.config_path = config_name.c_str();
|
cfg.config_path = config_name.c_str();
|
||||||
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
||||||
|
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string msg = console.str();
|
std::string msg = console.str();
|
||||||
|
|
|
@ -12,7 +12,7 @@ extern "C" {
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
// Funkce pro mapování souboru do paměti
|
// Funkce pro mapování souboru do paměti
|
||||||
void* map_file_to_memory_cpp(const char *name, size_t *sz) {
|
const void* map_file_to_memory_cpp(const char *name, size_t *sz) {
|
||||||
if (!name || !sz) {
|
if (!name || !sz) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -45,11 +45,11 @@ void* map_file_to_memory_cpp(const char *name, size_t *sz) {
|
||||||
return mappedData;
|
return mappedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* map_file_to_memory(const char *name, size_t *sz) {
|
const void* map_file_to_memory(const char *name, size_t *sz) {
|
||||||
return map_file_to_memory_cpp(name, sz);
|
return map_file_to_memory_cpp(name, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funkce pro zrušení mapování
|
// Funkce pro zrušení mapování
|
||||||
void unmap_file(void *ptr, size_t) {
|
void unmap_file(const void *ptr, size_t) {
|
||||||
UnmapViewOfFile(ptr);
|
UnmapViewOfFile((void *)ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
void *map_file_to_memory(const char *name, size_t *sz);
|
const void *map_file_to_memory(const char *name, size_t *sz);
|
||||||
void unmap_file(void *ptr, size_t sz);
|
void unmap_file(const void *ptr, size_t sz);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
add_executable(ddl_ar ddl_ar.cpp ddl_ar_class.cpp)
|
add_executable(ddl_ar ddl_ar.cpp ddl_ar_class.cpp)
|
||||||
add_executable(pcx_diff_tool pcx_diff_tool.c)
|
add_executable(pcx_diff_tool pcx_diff_tool.c)
|
||||||
|
add_executable(deenc deenc.c)
|
||||||
|
|
||||||
set_property(TARGET ddl_ar PROPERTY CXX_STANDARD 20)
|
set_property(TARGET ddl_ar PROPERTY CXX_STANDARD 20)
|
||||||
|
|
43
tools/deenc.c
Normal file
43
tools/deenc.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <file.ENC>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = fopen(argv[1], "rb");
|
||||||
|
if (!f) {
|
||||||
|
perror("Can't open file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Získání velikosti souboru
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
// Alokace bufferu
|
||||||
|
unsigned char *data = malloc(size);
|
||||||
|
if (!data) {
|
||||||
|
perror("Memory alloc error");
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(data, 1, size, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
int last=0;
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
last = (last + data[i]) & 0xFF;
|
||||||
|
data[i] = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Výstup na stdout
|
||||||
|
fwrite(data, 1, size, stdout);
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue