mirror of
https://github.com/Oibaf66/uae-wii.git
synced 2024-11-22 02:29:17 +01:00
Added ZIP, DMS and floppy sound support
This commit is contained in:
parent
b5feec8512
commit
e1cf346493
@ -56,6 +56,7 @@ src/tools/genlinetoscr.exe:
|
||||
clean:
|
||||
@echo Cleaning $(OBJ_DIR)
|
||||
@rm -rf $(OBJS) $(OBJ_DIR) src/machdep src/target.h src/md-fpp.h src/sysconfig.h $(SYMLINKS)
|
||||
@rm -rf dist
|
||||
@rm -f src/blit.h src/blitfunc.c src/blitfunc.h src/blittable.c src/linetoscr.c
|
||||
@rm -f uae.dol uae.elf
|
||||
cd src/tools/ && make -f Makefile.wii clean
|
||||
@ -143,7 +144,7 @@ COMMON_FLAGS := -g -O3 -G8 -mrvl -Wall -D__inline__=__inline__ $(MACHDEP) -Wno-u
|
||||
INCLUDES := -Isrc/md-generic/ -Isrc/include -Isrc -I$(DEVKITPRO)/libogc/include -I$(DEVKITPRO)/libogc/include/SDL -I$(PORTLIBS)/include
|
||||
DEFINES := -DOS_WITHOUT_MEMORY_MANAGEMENT -DSAVESTATE -DUSE_SDL -DSUPPORT_THREADS -DCPUEMU_0 -DCPUEMU_5 -DCPUEMU_6 \
|
||||
-DFPUEMU -DAGA -DAUTOCONFIG -DFILESYS \
|
||||
-DTD_START_HEIGHT=16
|
||||
-DTD_START_HEIGHT=16 -DDRIVESOUND
|
||||
CFLAGS := $(COMMON_FLAGS) $(INCLUDES) $(DEFINES)
|
||||
|
||||
#unused defines; -DFDI2RAW
|
||||
@ -181,6 +182,7 @@ distsource:
|
||||
cd .. && cp -r uae-wii uae-wii-v
|
||||
cd ../uae-wii-v && find . -name ".svn" | xargs rm -rf
|
||||
cd .. && tar -czf uae-wii-v.tar.gz uae-wii-v
|
||||
cd .. && rm -fr uae-wii-v
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
@ -21,17 +21,18 @@
|
||||
#include "custom_private.h"
|
||||
#include "newcpu.h"
|
||||
#include "gensound.h"
|
||||
#include "driveclick.h"
|
||||
#include "sounddep/sound.h"
|
||||
#include "events.h"
|
||||
#include "audio.h"
|
||||
#include "savestate.h"
|
||||
#include "driveclick.h"
|
||||
#ifdef AVIOUTPUT
|
||||
# include "avioutput.h"
|
||||
#endif
|
||||
#include "sinctable.h"
|
||||
#include "gui.h" /* for gui_ledstate */
|
||||
|
||||
|
||||
#define MAX_EV ~0ul
|
||||
//#define DEBUG_AUDIO
|
||||
#define DEBUG_CHANNEL_MASK 15
|
||||
|
150
src/driveclick.c
150
src/driveclick.c
@ -13,14 +13,21 @@
|
||||
|
||||
#include "uae.h"
|
||||
#include "options.h"
|
||||
#include "driveclick.h"
|
||||
#include "sounddep/sound.h"
|
||||
#include "zfile.h"
|
||||
#include "events.h"
|
||||
|
||||
#include "driveclick.h"
|
||||
|
||||
#include "fsdb.h"
|
||||
|
||||
#include "resource/drive_click.c"
|
||||
#include "resource/drive_snatch.c"
|
||||
#include "resource/drive_spin.c"
|
||||
#include "resource/drive_startup.c"
|
||||
|
||||
|
||||
|
||||
static struct drvsample drvs[4][DS_END];
|
||||
static int freq = 44100;
|
||||
|
||||
@ -51,7 +58,18 @@ uae_s16 *decodewav (uae_u8 *s, int *lenp)
|
||||
s += 4;
|
||||
len = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
|
||||
dst = xmalloc (len);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
{
|
||||
int i;
|
||||
uae_u8* d = (uae_u8*) dst;
|
||||
for (i = 0; i < len; i+= 2) {
|
||||
d[i] = s[i + 5];
|
||||
d[i+1] = s[i + 4];
|
||||
}
|
||||
}
|
||||
#else
|
||||
memcpy (dst, s + 4, len);
|
||||
#endif
|
||||
*lenp = len / 2;
|
||||
return dst;
|
||||
}
|
||||
@ -65,24 +83,77 @@ static int loadsample (const char *path, struct drvsample *ds)
|
||||
struct zfile *f;
|
||||
uae_u8 *buf;
|
||||
int size;
|
||||
int i;
|
||||
|
||||
f = zfile_fopen (path, "rb");
|
||||
if (!f) {
|
||||
write_log ("driveclick: can't open '%s'\n", path);
|
||||
return 0;
|
||||
}
|
||||
// ("driveclick: loading '%s'\n", path);
|
||||
zfile_fseek (f, 0, SEEK_END);
|
||||
size = zfile_ftell (f);
|
||||
buf = malloc (size);
|
||||
zfile_fseek (f, 0, SEEK_SET);
|
||||
zfile_fread (buf, size, 1, f);
|
||||
zfile_fclose (f);
|
||||
|
||||
/*
|
||||
printf("size=%i \n", size);
|
||||
for (i = 0; i < size; i++) {
|
||||
printf("0x%02x,", buf[i]);
|
||||
if (i % 20 == 19) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
flush(NULL);
|
||||
}
|
||||
*/
|
||||
|
||||
ds->len = size;
|
||||
ds->p = decodewav (buf, &ds->len);
|
||||
|
||||
free (buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//The same function as load sample, but the wav data is already in memory.
|
||||
//No read, just decode.
|
||||
static int loadsample_resource(int resId, struct drvsample *ds) {
|
||||
uae_u8* buf = NULL;
|
||||
int size;
|
||||
switch (resId) {
|
||||
case DS_CLICK: {
|
||||
buf = res_drive_click;
|
||||
size = res_drive_click_size;
|
||||
} break;
|
||||
case DS_SPIN :
|
||||
case DS_SPINND: {
|
||||
buf = res_drive_spin;
|
||||
size = res_drive_spin_size;
|
||||
} break;
|
||||
case DS_START: {
|
||||
buf = res_drive_startup;
|
||||
size = res_drive_startup_size;
|
||||
} break;
|
||||
case DS_SNATCH: {
|
||||
buf = res_drive_snatch;
|
||||
size = res_drive_snatch_size;
|
||||
} break;
|
||||
|
||||
default: return 0;
|
||||
} //end of switch
|
||||
|
||||
|
||||
//write_log("loading click resource %i \n", resId);
|
||||
ds->len = size;
|
||||
ds->p = decodewav (buf, &ds->len);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static void freesample (struct drvsample *s)
|
||||
{
|
||||
free (s->p);
|
||||
@ -94,47 +165,72 @@ extern char *start_path;
|
||||
void driveclick_init (void)
|
||||
{
|
||||
int v, vv, i, j;
|
||||
char tmp[1000];
|
||||
static char tmp_path[1024];
|
||||
|
||||
driveclick_free ();
|
||||
vv = 0;
|
||||
|
||||
write_log("driveclick init...\n");
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (currprefs.dfxclick[i]) {
|
||||
/* TODO: Implement location of sample data */
|
||||
#if 0
|
||||
if (currprefs.dfxclick[i] > 0) {
|
||||
v = 0;
|
||||
if (driveclick_loadresource (drvs[i], currprefs.dfxclick[i]))
|
||||
v = 3;
|
||||
} else if (currprefs.dfxclick[i] == -1) {
|
||||
sprintf (tmp, "%suae_data%cdrive_click_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v = loadsample (tmp, &drvs[i][DS_CLICK]);
|
||||
sprintf (tmp, "%suae_data%cdrive_spin_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp, &drvs[i][DS_SPIN]);
|
||||
sprintf (tmp, "%suae_data%cdrive_spinnd_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp, &drvs[i][DS_SPINND]);
|
||||
sprintf (tmp, "%suae_data%cdrive_startup_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp, &drvs[i][DS_START]);
|
||||
sprintf (tmp, "%suae_data%cdrive_snatch_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp, &drvs[i][DS_SNATCH]);
|
||||
//load from resource
|
||||
if (currprefs.dfxclick[i] > 0) { // > 0
|
||||
v = loadsample_resource(DS_CLICK, &drvs[i][DS_CLICK]);
|
||||
v += loadsample_resource(DS_SPIN, &drvs[i][DS_SPIN]);
|
||||
v += loadsample_resource(DS_SPINND, &drvs[i][DS_SPINND]);
|
||||
v += loadsample_resource(DS_SNATCH, &drvs[i][DS_SNATCH]);
|
||||
v += loadsample_resource(DS_START, &drvs[i][DS_START]);
|
||||
|
||||
} else
|
||||
//load from file
|
||||
if (currprefs.dfxclick[i] == -1) {
|
||||
#ifdef GEKKO //currprefs.dfxclickexternal[i] is the path to the wav directory (path contains trailing separator)
|
||||
sprintf (tmp_path, "%sdrive_click.wav", currprefs.dfxclickexternal[i]);
|
||||
v = loadsample (tmp_path, &drvs[i][DS_CLICK]);
|
||||
sprintf (tmp_path, "%sdrive_spin.wav", currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_SPIN]);
|
||||
sprintf (tmp_path, "%sdrive_spinnd.wav", currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_SPINND]);
|
||||
sprintf (tmp_path, "%sdrive_startup.wav", currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_START]);
|
||||
sprintf (tmp_path, "%sdrive_snatch.wav", currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_SNATCH]);
|
||||
#else
|
||||
char * start_path = "."; //TODO - ??? set correct path
|
||||
sprintf (tmp_path, "%suae_data%cdrive_click_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v = loadsample (tmp_path, &drvs[i][DS_CLICK]);
|
||||
sprintf (tmp_path, "%suae_data%cdrive_spin_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_SPIN]);
|
||||
sprintf (tmp_path, "%suae_data%cdrive_spinnd_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_SPINND]);
|
||||
sprintf (tmp_path, "%suae_data%cdrive_startup_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_START]);
|
||||
sprintf (tmp_path, "%suae_data%cdrive_snatch_%s", start_path, FSDB_DIR_SEPARATOR, currprefs.dfxclickexternal[i]);
|
||||
v += loadsample (tmp_path, &drvs[i][DS_SNATCH]);
|
||||
#endif /* GEKKO */
|
||||
}
|
||||
if (v == 0) {
|
||||
int j;
|
||||
for (j = 0; j < DS_END; j++)
|
||||
freesample (&drvs[i][j]);
|
||||
currprefs.dfxclick[i] = changed_prefs.dfxclick[i] = 0;
|
||||
int j;
|
||||
for (j = 0; j < DS_END; j++) {
|
||||
freesample (&drvs[i][j]);
|
||||
}
|
||||
currprefs.dfxclick[i] = changed_prefs.dfxclick[i] = 0;
|
||||
}
|
||||
for (j = 0; j < DS_END; j++)
|
||||
drvs[i][j].len <<= DS_SHIFT;
|
||||
for (j = 0; j < DS_END; j++) {
|
||||
drvs[i][j].len <<= DS_SHIFT;
|
||||
}
|
||||
drvs[i][DS_CLICK].pos = drvs[i][DS_CLICK].len;
|
||||
drvs[i][DS_SNATCH].pos = drvs[i][DS_SNATCH].len;
|
||||
vv += currprefs.dfxclick[i];
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
if (vv > 0) {
|
||||
driveclick_reset ();
|
||||
click_initialized = 1;
|
||||
write_log("reset driveclick \n");
|
||||
driveclick_reset ();
|
||||
click_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,18 +149,16 @@ static const char *graphic_messages[] = {
|
||||
|
||||
/*00*/ "Correct aspect",
|
||||
/*01*/ "^|off|100%|95%|93%|90%|custom",
|
||||
/*02*/ " ",
|
||||
/*03*/ "Scanlines",
|
||||
/*04*/ "^|on|off",
|
||||
/*05*/ " ",
|
||||
/*06*/ "Leds",
|
||||
/*02*/ "Scanlines",
|
||||
/*03*/ "^|on|off",
|
||||
/*04*/ "Leds",
|
||||
/*05*/ "^|on|off",
|
||||
/*06*/ "Floppy sound",
|
||||
/*07*/ "^|on|off",
|
||||
/*08*/ " ",
|
||||
/*09*/ "Port",
|
||||
/*10*/ "^|SD|USB|SMB",
|
||||
/*11*/ " ",
|
||||
/*12*/ "Rumble",
|
||||
/*13*/ "^|on|off",
|
||||
/*08*/ "Port",
|
||||
/*09*/ "^|SD|USB|SMB",
|
||||
/*10*/ "Rumble",
|
||||
/*11*/ "^|on|off",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -538,6 +536,25 @@ cfgfile_save(&changed_prefs, user_options, 0);
|
||||
msgInfo("Configurations saved",3000,NULL);
|
||||
}
|
||||
|
||||
int get_dfxclick(void)
|
||||
{
|
||||
int sounddf_on = 0;
|
||||
int i;
|
||||
|
||||
for (i=0; i < 4; i++)
|
||||
if (changed_prefs.dfxclick[i]&&(changed_prefs.dfxtype[i]>=0)) sounddf_on =1;
|
||||
|
||||
return sounddf_on;
|
||||
}
|
||||
|
||||
void set_dfxclick(int sounddf_on)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < 4; i++)
|
||||
if ((changed_prefs.dfxtype[i]>=0)&&(changed_prefs.dfxclick[i]!=sounddf_on))
|
||||
changed_prefs.dfxclick[i] = sounddf_on;
|
||||
}
|
||||
|
||||
static void emulation_options(void)
|
||||
{
|
||||
int submenus[7];
|
||||
@ -571,7 +588,7 @@ static void emulation_options(void)
|
||||
|
||||
static void graphic_options(void)
|
||||
{
|
||||
int submenus[5];
|
||||
int submenus[6];
|
||||
int opt;
|
||||
|
||||
memset(submenus, 0, sizeof(submenus));
|
||||
@ -580,8 +597,9 @@ static void graphic_options(void)
|
||||
submenus[0] = get_gfx_aspect_ratio();
|
||||
submenus[1] = !(changed_prefs.gfx_linedbl == 2) ;
|
||||
submenus[2] = !changed_prefs.leds_on_screen;
|
||||
submenus[3] = changed_prefs.Port;
|
||||
submenus[4] = !changed_prefs.rumble;
|
||||
submenus[3] = !get_dfxclick();
|
||||
submenus[4] = changed_prefs.Port;
|
||||
submenus[5] = !changed_prefs.rumble;
|
||||
|
||||
opt = menu_select_title("Other options menu",
|
||||
graphic_messages, submenus);
|
||||
@ -591,8 +609,9 @@ static void graphic_options(void)
|
||||
set_gfx_aspect_ratio(submenus[0]);
|
||||
changed_prefs.gfx_linedbl = submenus[1] ? 1 : 2;
|
||||
changed_prefs.leds_on_screen = !submenus[2];
|
||||
set_Port(submenus[3]);
|
||||
changed_prefs.rumble = !submenus[4];
|
||||
set_dfxclick(!submenus[3]);
|
||||
set_Port(submenus[4]);
|
||||
changed_prefs.rumble = !submenus[5];
|
||||
currprefs.leds_on_screen = changed_prefs.leds_on_screen;
|
||||
currprefs.rumble = changed_prefs.rumble;
|
||||
}
|
||||
|
@ -21,6 +21,14 @@
|
||||
#include "menu.h"
|
||||
#include "VirtualKeyboard.h"
|
||||
|
||||
struct joyinfo {
|
||||
SDL_Joystick *joy;
|
||||
unsigned int axles;
|
||||
unsigned int buttons;
|
||||
};
|
||||
|
||||
extern unsigned int nr_joysticks;
|
||||
extern struct joyinfo joys[];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -269,7 +277,7 @@ static const char **get_file_list(const char *base_dir)
|
||||
{
|
||||
char buf[255];
|
||||
const char *exts[] = {".adf", ".ADF", ".adz", ".ADZ", ".ipf", ".IPF", ".fdi", ".FDI",
|
||||
".sav", ".SAV", ".uss", ".USS", ".rom", ".ROM", NULL};
|
||||
".sav", ".SAV", ".uss", ".USS", ".rom", ".ROM", ".zip",".ZIP",".dms", ".DMS",NULL};
|
||||
struct stat st;
|
||||
|
||||
snprintf(buf, 255, "%s/%s", base_dir, de->d_name);
|
||||
@ -687,8 +695,8 @@ uint32_t menu_wait_key_press(void)
|
||||
static int joy_keys_last;
|
||||
|
||||
/* Wii-specific, sorry */
|
||||
for (nr = 0; nr < SDL_NumJoysticks(); nr++) {
|
||||
joy = SDL_JoystickOpen(nr);
|
||||
for (nr = 0; nr < nr_joysticks; nr++) {
|
||||
joy = joys[nr].joy;
|
||||
if (!joy)
|
||||
continue;
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
extern int gui_is_active;
|
||||
|
||||
static unsigned int nr_joysticks;
|
||||
unsigned int nr_joysticks;
|
||||
static int initialized;
|
||||
|
||||
struct joyinfo {
|
||||
@ -31,7 +31,7 @@ struct joyinfo {
|
||||
unsigned int buttons;
|
||||
};
|
||||
|
||||
static struct joyinfo joys[MAX_INPUT_DEVICES];
|
||||
struct joyinfo joys[MAX_INPUT_DEVICES];
|
||||
|
||||
//Wiimote Rumble
|
||||
#ifdef GEKKO
|
||||
|
@ -1,227 +1,231 @@
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Support for SDL sound
|
||||
*
|
||||
* Copyright 1997 Bernd Schmidt
|
||||
* Copyright 2003-2006 Richard Drummond
|
||||
*/
|
||||
|
||||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "gensound.h"
|
||||
#include "sounddep/sound.h"
|
||||
#include "threaddep/thread.h"
|
||||
#include <SDL_audio.h>
|
||||
#include <SDL.h>
|
||||
|
||||
static int have_sound = 0;
|
||||
|
||||
uae_u16 sndbuffer[44100];
|
||||
uae_u16 *sndbufpt;
|
||||
int sndbufsize;
|
||||
static SDL_AudioSpec spec;
|
||||
|
||||
static smp_comm_pipe to_sound_pipe;
|
||||
static uae_sem_t data_available_sem, callback_done_sem, sound_init_sem;
|
||||
|
||||
static int in_callback, closing_sound;
|
||||
|
||||
static void clearbuffer (void)
|
||||
{
|
||||
memset (sndbuffer, (spec.format == AUDIO_U8) ? SOUND8_BASE_VAL : SOUND16_BASE_VAL, sizeof (sndbuffer));
|
||||
}
|
||||
|
||||
/* This shouldn't be necessary . . . */
|
||||
static void dummy_callback (void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void sound_callback (void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
if (closing_sound)
|
||||
return;
|
||||
in_callback = 1;
|
||||
/* Wait for data to finish. */
|
||||
uae_sem_wait (&data_available_sem);
|
||||
if (! closing_sound) {
|
||||
memcpy (stream, sndbuffer, sndbufsize);
|
||||
/* Notify writer that we're done. */
|
||||
uae_sem_post (&callback_done_sem);
|
||||
}
|
||||
in_callback = 0;
|
||||
}
|
||||
|
||||
void finish_sound_buffer (void)
|
||||
{
|
||||
uae_sem_post (&data_available_sem);
|
||||
uae_sem_wait (&callback_done_sem);
|
||||
}
|
||||
|
||||
/* Try to determine whether sound is available. */
|
||||
int setup_sound (void)
|
||||
{
|
||||
int success = 0;
|
||||
|
||||
if (SDL_InitSubSystem (SDL_INIT_AUDIO) == 0) {
|
||||
spec.freq = currprefs.sound_freq;
|
||||
spec.format = currprefs.sound_bits == 8 ? AUDIO_U8 : AUDIO_S16SYS;
|
||||
spec.channels = currprefs.sound_stereo ? 2 : 1;
|
||||
spec.callback = dummy_callback;
|
||||
spec.samples = spec.freq * currprefs.sound_latency / 1000;
|
||||
spec.callback = sound_callback;
|
||||
spec.userdata = 0;
|
||||
|
||||
if (SDL_OpenAudio (&spec, 0) < 0) {
|
||||
write_log ("Couldn't open audio: %s\n", SDL_GetError());
|
||||
SDL_QuitSubSystem (SDL_INIT_AUDIO);
|
||||
} else {
|
||||
success = 1;
|
||||
SDL_CloseAudio ();
|
||||
}
|
||||
}
|
||||
|
||||
sound_available = success;
|
||||
|
||||
return sound_available;
|
||||
}
|
||||
|
||||
static int open_sound (void)
|
||||
{
|
||||
spec.freq = currprefs.sound_freq;
|
||||
spec.format = currprefs.sound_bits == 8 ? AUDIO_U8 : AUDIO_S16SYS;
|
||||
spec.channels = currprefs.sound_stereo ? 2 : 1;
|
||||
spec.samples = spec.freq * currprefs.sound_latency / 1000;
|
||||
spec.callback = sound_callback;
|
||||
spec.userdata = 0;
|
||||
|
||||
clearbuffer();
|
||||
if (SDL_OpenAudio (&spec, NULL) < 0) {
|
||||
write_log ("Couldn't open audio: %s\n", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (spec.format == AUDIO_S16SYS) {
|
||||
init_sound_table16 ();
|
||||
sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler;
|
||||
} else {
|
||||
init_sound_table8 ();
|
||||
sample_handler = currprefs.sound_stereo ? sample8s_handler : sample8_handler;
|
||||
}
|
||||
have_sound = 1;
|
||||
|
||||
sound_available = 1;
|
||||
obtainedfreq = currprefs.sound_freq;
|
||||
sndbufsize = spec.samples * currprefs.sound_bits / 8 * spec.channels;
|
||||
write_log ("SDL sound driver found and configured for %d bits at %d Hz, buffer is %d ms (%d bytes).\n",
|
||||
currprefs.sound_bits, spec.freq, spec.samples * 1000 / spec.freq, sndbufsize);
|
||||
sndbufpt = sndbuffer;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *sound_thread (void *dummy)
|
||||
{
|
||||
for (;;) {
|
||||
int cmd = read_comm_pipe_int_blocking (&to_sound_pipe);
|
||||
int n;
|
||||
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
open_sound ();
|
||||
uae_sem_post (&sound_init_sem);
|
||||
break;
|
||||
case 1:
|
||||
uae_sem_post (&sound_init_sem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We need a thread for this, since communication between finish_sound_buffer
|
||||
* and the callback works through semaphores. In theory, this is unnecessary,
|
||||
* since SDL uses a sound thread internally, and the callback runs in its
|
||||
* context. But we don't want to depend on SDL's internals too much. */
|
||||
static void init_sound_thread (void)
|
||||
{
|
||||
uae_thread_id tid;
|
||||
|
||||
init_comm_pipe (&to_sound_pipe, 20, 1);
|
||||
uae_sem_init (&data_available_sem, 0, 0);
|
||||
uae_sem_init (&callback_done_sem, 0, 0);
|
||||
uae_sem_init (&sound_init_sem, 0, 0);
|
||||
uae_start_thread (sound_thread, NULL, &tid);
|
||||
}
|
||||
|
||||
void close_sound (void)
|
||||
{
|
||||
if (! have_sound)
|
||||
return;
|
||||
|
||||
SDL_PauseAudio (1);
|
||||
clearbuffer();
|
||||
if (in_callback) {
|
||||
closing_sound = 1;
|
||||
uae_sem_post (&data_available_sem);
|
||||
}
|
||||
write_comm_pipe_int (&to_sound_pipe, 1, 1);
|
||||
uae_sem_wait (&sound_init_sem);
|
||||
SDL_CloseAudio ();
|
||||
uae_sem_destroy (&data_available_sem);
|
||||
uae_sem_destroy (&sound_init_sem);
|
||||
uae_sem_destroy (&callback_done_sem);
|
||||
have_sound = 0;
|
||||
}
|
||||
|
||||
int init_sound (void)
|
||||
{
|
||||
in_callback = 0;
|
||||
closing_sound = 0;
|
||||
|
||||
init_sound_thread ();
|
||||
write_comm_pipe_int (&to_sound_pipe, 0, 1);
|
||||
uae_sem_wait (&sound_init_sem);
|
||||
SDL_PauseAudio (0);
|
||||
|
||||
return have_sound;
|
||||
}
|
||||
|
||||
void pause_sound (void)
|
||||
{
|
||||
SDL_PauseAudio (1);
|
||||
}
|
||||
|
||||
void resume_sound (void)
|
||||
{
|
||||
clearbuffer();
|
||||
SDL_PauseAudio (0);
|
||||
}
|
||||
|
||||
void reset_sound (void)
|
||||
{
|
||||
clearbuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
void sound_volume (int dir)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle audio specific cfgfile options
|
||||
*/
|
||||
void audio_default_options (struct uae_prefs *p)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_save_options (FILE *f, const struct uae_prefs *p)
|
||||
{
|
||||
}
|
||||
|
||||
int audio_parse_option (struct uae_prefs *p, const char *option, const char *value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Support for SDL sound
|
||||
*
|
||||
* Copyright 1997 Bernd Schmidt
|
||||
* Copyright 2003-2006 Richard Drummond
|
||||
*/
|
||||
|
||||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "gensound.h"
|
||||
#include "sounddep/sound.h"
|
||||
#include "threaddep/thread.h"
|
||||
#include <SDL_audio.h>
|
||||
#include <SDL.h>
|
||||
|
||||
static int have_sound = 0;
|
||||
|
||||
uae_u16 sndbuffer[44100];
|
||||
uae_u16 *sndbufpt;
|
||||
int sndbufsize;
|
||||
static SDL_AudioSpec spec;
|
||||
|
||||
static smp_comm_pipe to_sound_pipe;
|
||||
static uae_sem_t data_available_sem, callback_done_sem, sound_init_sem;
|
||||
|
||||
static int in_callback, closing_sound;
|
||||
|
||||
static void clearbuffer (void)
|
||||
{
|
||||
memset (sndbuffer, (spec.format == AUDIO_U8) ? SOUND8_BASE_VAL : SOUND16_BASE_VAL, sizeof (sndbuffer));
|
||||
}
|
||||
|
||||
/* This shouldn't be necessary . . . */
|
||||
static void dummy_callback (void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void sound_callback (void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
if (closing_sound)
|
||||
return;
|
||||
in_callback = 1;
|
||||
/* Wait for data to finish. */
|
||||
uae_sem_wait (&data_available_sem);
|
||||
if (! closing_sound) {
|
||||
memcpy (stream, sndbuffer, sndbufsize);
|
||||
/* Notify writer that we're done. */
|
||||
uae_sem_post (&callback_done_sem);
|
||||
}
|
||||
in_callback = 0;
|
||||
}
|
||||
|
||||
void finish_sound_buffer (void)
|
||||
{
|
||||
uae_sem_post (&data_available_sem);
|
||||
uae_sem_wait (&callback_done_sem);
|
||||
}
|
||||
|
||||
/* Try to determine whether sound is available. */
|
||||
int setup_sound (void)
|
||||
{
|
||||
int success = 0;
|
||||
|
||||
if (SDL_InitSubSystem (SDL_INIT_AUDIO) == 0) {
|
||||
spec.freq = currprefs.sound_freq;
|
||||
spec.format = currprefs.sound_bits == 8 ? AUDIO_U8 : AUDIO_S16SYS;
|
||||
spec.channels = currprefs.sound_stereo ? 2 : 1;
|
||||
spec.callback = dummy_callback;
|
||||
spec.samples = spec.freq * currprefs.sound_latency / 1000;
|
||||
spec.callback = sound_callback;
|
||||
spec.userdata = 0;
|
||||
|
||||
if (SDL_OpenAudio (&spec, 0) < 0) {
|
||||
write_log ("Couldn't open audio: %s\n", SDL_GetError());
|
||||
SDL_QuitSubSystem (SDL_INIT_AUDIO);
|
||||
} else {
|
||||
success = 1;
|
||||
SDL_CloseAudio ();
|
||||
}
|
||||
}
|
||||
|
||||
sound_available = success;
|
||||
|
||||
return sound_available;
|
||||
}
|
||||
|
||||
static int open_sound (void)
|
||||
{
|
||||
spec.freq = currprefs.sound_freq;
|
||||
spec.format = currprefs.sound_bits == 8 ? AUDIO_U8 : AUDIO_S16SYS;
|
||||
spec.channels = currprefs.sound_stereo ? 2 : 1;
|
||||
spec.samples = spec.freq * currprefs.sound_latency / 1000;
|
||||
spec.callback = sound_callback;
|
||||
spec.userdata = 0;
|
||||
|
||||
clearbuffer();
|
||||
if (SDL_OpenAudio (&spec, NULL) < 0) {
|
||||
write_log ("Couldn't open audio: %s\n", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (spec.format == AUDIO_S16SYS) {
|
||||
init_sound_table16 ();
|
||||
sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler;
|
||||
} else {
|
||||
init_sound_table8 ();
|
||||
sample_handler = currprefs.sound_stereo ? sample8s_handler : sample8_handler;
|
||||
}
|
||||
have_sound = 1;
|
||||
|
||||
sound_available = 1;
|
||||
obtainedfreq = currprefs.sound_freq;
|
||||
sndbufsize = spec.samples * currprefs.sound_bits / 8 * spec.channels;
|
||||
write_log ("SDL sound driver found and configured for %d bits at %d Hz, buffer is %d ms (%d bytes).\n",
|
||||
currprefs.sound_bits, spec.freq, spec.samples * 1000 / spec.freq, sndbufsize);
|
||||
sndbufpt = sndbuffer;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *sound_thread (void *dummy)
|
||||
{
|
||||
for (;;) {
|
||||
int cmd = read_comm_pipe_int_blocking (&to_sound_pipe);
|
||||
int n;
|
||||
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
open_sound ();
|
||||
uae_sem_post (&sound_init_sem);
|
||||
break;
|
||||
case 1:
|
||||
uae_sem_post (&sound_init_sem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We need a thread for this, since communication between finish_sound_buffer
|
||||
* and the callback works through semaphores. In theory, this is unnecessary,
|
||||
* since SDL uses a sound thread internally, and the callback runs in its
|
||||
* context. But we don't want to depend on SDL's internals too much. */
|
||||
static void init_sound_thread (void)
|
||||
{
|
||||
uae_thread_id tid;
|
||||
|
||||
init_comm_pipe (&to_sound_pipe, 20, 1);
|
||||
uae_sem_init (&data_available_sem, 0, 0);
|
||||
uae_sem_init (&callback_done_sem, 0, 0);
|
||||
uae_sem_init (&sound_init_sem, 0, 0);
|
||||
uae_start_thread (sound_thread, NULL, &tid);
|
||||
}
|
||||
|
||||
void close_sound (void)
|
||||
{
|
||||
if (! have_sound)
|
||||
return;
|
||||
|
||||
SDL_PauseAudio (1);
|
||||
clearbuffer();
|
||||
if (in_callback) {
|
||||
closing_sound = 1;
|
||||
uae_sem_post (&data_available_sem);
|
||||
}
|
||||
write_comm_pipe_int (&to_sound_pipe, 1, 1);
|
||||
uae_sem_wait (&sound_init_sem);
|
||||
SDL_CloseAudio ();
|
||||
uae_sem_destroy (&data_available_sem);
|
||||
uae_sem_destroy (&sound_init_sem);
|
||||
uae_sem_destroy (&callback_done_sem);
|
||||
have_sound = 0;
|
||||
}
|
||||
|
||||
int init_sound (void)
|
||||
{
|
||||
in_callback = 0;
|
||||
closing_sound = 0;
|
||||
|
||||
init_sound_thread ();
|
||||
write_comm_pipe_int (&to_sound_pipe, 0, 1);
|
||||
uae_sem_wait (&sound_init_sem);
|
||||
SDL_PauseAudio (0);
|
||||
|
||||
#ifdef DRIVESOUND
|
||||
driveclick_init();
|
||||
#endif
|
||||
|
||||
return have_sound;
|
||||
}
|
||||
|
||||
void pause_sound (void)
|
||||
{
|
||||
SDL_PauseAudio (1);
|
||||
}
|
||||
|
||||
void resume_sound (void)
|
||||
{
|
||||
clearbuffer();
|
||||
SDL_PauseAudio (0);
|
||||
}
|
||||
|
||||
void reset_sound (void)
|
||||
{
|
||||
clearbuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
void sound_volume (int dir)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle audio specific cfgfile options
|
||||
*/
|
||||
void audio_default_options (struct uae_prefs *p)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_save_options (FILE *f, const struct uae_prefs *p)
|
||||
{
|
||||
}
|
||||
|
||||
int audio_parse_option (struct uae_prefs *p, const char *option, const char *value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ extern void reset_sound (void);
|
||||
STATIC_INLINE void check_sound_buffers (void)
|
||||
{
|
||||
if ((char *)sndbufpt - (char *)sndbuffer >= sndbufsize) {
|
||||
#ifdef DRIVESOUND
|
||||
driveclick_mix ((uae_s16*)sndbuffer, sndbufsize >> 1);
|
||||
#endif
|
||||
finish_sound_buffer ();
|
||||
sndbufpt = sndbuffer;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user