diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..388b8c4 --- /dev/null +++ b/Makefile @@ -0,0 +1,116 @@ +CC = kos32-gcc +AR = kos32-ar +LD = kos32-ld +STRIP = kos32-strip + +LIBNAME = libSDL2 + +LIBS:= -lgcc -lc.dll -ldll -lsound + +LDFLAGS+= -shared -s -T dll.lds --entry _DllStartup --image-base=0 --out-implib $(LIBNAME).dll.a +LDFLAGS+= -L/home/autobuild/tools/win32/mingw32/lib + +atomic_OBJS = src/atomic/SDL_atomic.o src/atomic/SDL_spinlock.o + +audio_OBJS = src/audio/SDL_audio.o src/audio/SDL_audiocvt.o \ + src/audio/SDL_audiodev.o src/audio/SDL_audiotypecvt.o \ + src/audio/SDL_mixer.o src/audio/SDL_wave.o \ + src/audio/kolibri/SDL_kolibriaudio.o + +cpuinfo_OBJS = src/cpuinfo/SDL_cpuinfo.o + +events_OBJS = src/events/imKStoUCS.o src/events/SDL_clipboardevents.o \ + src/events/SDL_displayevents.o src/events/SDL_dropevents.o \ + src/events/SDL_events.o src/events/SDL_gesture.o \ + src/events/SDL_keyboard.o src/events/SDL_keysym_to_scancode.o \ + src/events/SDL_mouse.o src/events/SDL_quit.o \ + src/events/SDL_scancode_tables.o src/events/SDL_touch.o \ + src/events/SDL_windowevents.o + +file_OBJS = src/file/SDL_rwops.o + +haptic_OBJS = src/haptic/SDL_haptic.o src/haptic/dummy/SDL_syshaptic.o + +hidapi_OBJS = src/hidapi/SDL_hidapi.o + +joystick_OBJS = src/joystick/controller_type.o src/joystick/SDL_gamecontroller.o \ + src/joystick/SDL_joystick.o src/joystick/SDL_steam_virtual_gamepad.o \ + src/joystick/dummy/SDL_sysjoystick.o + +loadso_OBJS = src/loadso/dummy/SDL_sysloadso.o + +power_OBJS = src/power/SDL_power.o + +filesystem_OBJS = src/filesystem/dummy/SDL_sysfilesystem.o + +locale_OBJS = src/locale/SDL_locale.o src/locale/dummy/SDL_syslocale.o + +misc_OBJS = src/misc/SDL_url.o src/misc/dummy/SDL_sysurl.o + +render_OBJS = src/render/SDL_render.o src/render/SDL_yuv_sw.o \ + src/render/software/SDL_blendfillrect.o src/render/software/SDL_blendline.o \ + src/render/software/SDL_blendpoint.o src/render/software/SDL_drawline.o \ + src/render/software/SDL_drawpoint.o src/render/software/SDL_render_sw.o \ + src/render/software/SDL_rotate.o src/render/software/SDL_triangle.o + +sensor_OBJS = src/sensor/SDL_sensor.o src/sensor/dummy/SDL_dummysensor.o + +stdlib_OBJS = src/stdlib/SDL_crc16.o src/stdlib/SDL_crc32.o src/stdlib/SDL_getenv.o \ + src/stdlib/SDL_iconv.o src/stdlib/SDL_malloc.o src/stdlib/SDL_mslibc.o \ + src/stdlib/SDL_qsort.o src/stdlib/SDL_stdlib.o src/stdlib/SDL_string.o \ + src/stdlib/SDL_strtokr.o + +libm_OBJS = src/libm/e_atan2.o src/libm/e_exp.o src/libm/e_fmod.o src/libm/e_log.o \ + src/libm/e_log10.o src/libm/e_pow.o src/libm/e_rem_pio2.o src/libm/e_sqrt.o \ + src/libm/k_cos.o src/libm/k_rem_pio2.o src/libm/k_sin.o src/libm/k_tan.o \ + src/libm/s_atan.o src/libm/s_copysign.o src/libm/s_cos.o src/libm/s_fabs.o \ + src/libm/s_floor.o src/libm/s_scalbn.o src/libm/s_sin.o src/libm/s_tan.o + +thread_OBJS = src/thread/SDL_thread.o src/thread/generic/SDL_syscond.o \ + src/thread/generic/SDL_sysmutex.o src/thread/generic/SDL_syssem.o \ + src/thread/generic/SDL_systhread.o src/thread/generic/SDL_systls.o + +timer_OBJS = src/timer/SDL_timer.o src/timer/dummy/SDL_systimer.o + +video_OBJS = src/video/SDL_blit_0.o src/video/SDL_blit_1.o src/video/SDL_blit_A.o \ + src/video/SDL_blit_auto.o src/video/SDL_blit_copy.o src/video/SDL_blit_N.o \ + src/video/SDL_blit_slow.o src/video/SDL_blit.o src/video/SDL_bmp.o \ + src/video/SDL_clipboard.o src/video/SDL_egl.o src/video/SDL_fillrect.o \ + src/video/SDL_pixels.o src/video/SDL_rect.o src/video/SDL_RLEaccel.o \ + src/video/SDL_shape.o src/video/SDL_stretch.o src/video/SDL_surface.o \ + src/video/SDL_video.o src/video/SDL_yuv.o src/video/yuv2rgb/yuv_rgb_lsx.o \ + src/video/yuv2rgb/yuv_rgb_sse.o src/video/yuv2rgb/yuv_rgb_std.o \ + src/video/dummy/SDL_nullevents.o src/video/dummy/SDL_nullframebuffer.o \ + src/video/dummy/SDL_nullvideo.o + +curr_OBJS = src/SDL_assert.o src/SDL_dataqueue.o src/SDL_error.o src/SDL_guid.o \ + src/SDL_hints.o src/SDL_list.o src/SDL_log.o src/SDL_utils.o src/SDL.o + +OBJS = $(atomic_OBJS) $(audio_OBJS) $(cpuinfo_OBJS) $(events_OBJS) $(file_OBJS) $(haptic_OBJS) \ + $(hidapi_OBJS) $(joystick_OBJS) $(loadso_OBJS) $(power_OBJS) $(filesystem_OBJS) \ + $(locale_OBJS) $(misc_OBJS) $(render_OBJS) $(sensor_OBJS) $(stdlib_OBJS) $(libm_OBJS) \ + $(thread_OBJS) $(timer_OBJS) $(video_OBJS) $(curr_OBJS) + +CFLAGS = -c -O2 -mpreferred-stack-boundary=2 -fno-ident -fomit-frame-pointer -fno-stack-check \ + -fno-stack-protector -mno-stack-arg-probe -fno-exceptions -fno-asynchronous-unwind-tables \ + -ffast-math -mno-ms-bitfields -fexpensive-optimizations \ + -D__KOLIBRI__ -D_KOLIBRI -DKOLIBRI -D_KOS_ -D_KOS -DKOS -DPACKAGE=\"SDL\" -DVERSION=\"2.30.3\" \ + -U_Win32 -UWIN32 -U_WIN32 -U__MINGW32__ -U__WIN32__ \ + -I../newlib/libc/include/ -Iinclude/ -Iatomic/ -Iaudio/ -Icpuinfo/ -Ievents/ -Ifile/ -Ihaptic/ \ + -Ihidapi/ -Ijoystick/ -Iloadso/ -Ipower/ -Ifilesystem/ -Ilocale/ -Imisc/ -Irender/ -Isensor/ \ + -Istdlib/ -Ilibm/ -Ithread/ -Itimer/ -Ivideo/ -I. + +all: $(LIBNAME).a $(LIBNAME).dll + +$(LIBNAME).a: $(OBJS) + $(AR) -crs ../../lib/$(LIBNAME).a $(OBJS) + +$(LIBNAME).dll: $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + $(STRIP) -S $@ + +%.o : %.c Makefile + $(CC) $(CFLAGS) -o $@ $< + +clean: + rm -f $(OBJS) diff --git a/include/SDL_config_kolibri.h b/include/SDL_config_kolibri.h index e95e475..123e1b6 100644 --- a/include/SDL_config_kolibri.h +++ b/include/SDL_config_kolibri.h @@ -100,7 +100,7 @@ #define SDL_VIDEO_DRIVER_DUMMY 1 /* Enable the dummy audio driver (src/audio/dummy/\*.c) */ -#define SDL_AUDIO_DRIVER_DUMMY 1 +#define SDL_AUDIO_DRIVER_KOLIBRI 1 /* Enable the stub joystick driver (src/joystick/dummy/\*.c) */ #define SDL_JOYSTICK_DISABLED 1 diff --git a/src/audio/kolibri/SDL_kolibriaudio.c b/src/audio/kolibri/SDL_kolibriaudio.c new file mode 100644 index 0000000..bf0e62d --- /dev/null +++ b/src/audio/kolibri/SDL_kolibriaudio.c @@ -0,0 +1,229 @@ +#include "../../SDL_internal.h" + +#ifdef SDL_AUDIO_DRIVER_KOLIBRI + +#include +#include + +#include "SDL_audio.h" + +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" + +#include "SDL_kolibriaudio.h" + +/* The tag name used by Kolibri audio */ +#define AUDIO_THREAD_STACK_SIZE 40960 +#define KOLIBRIAUDIO_DRIVER_NAME "kolibri" + +/* Variables required for spawning a thread for audio */ +static ksys_thread_t thread_info; +static int main_slot; +static uint32_t main_tid; +static uint32_t thread_stack[AUDIO_THREAD_STACK_SIZE]; +static SDL_AudioDevice *global_device; + +static void kolibri_audio_callback(void) +{ + ksys_signal_info_t snd_signal; + SDL_AudioDevice *this; + SDL_AudioCallback callback; + + int bPaused; + char str[100]; + + // initialize + this = global_device; + callback = this->spec.callback; + + if (CreateBuffer(private->used_format | PCM_RING, 0, &private->hBuff)) { + private->audio_response = 1; + exit(0); + } + + GetBufferSize(private->hBuff, &this->spec.size); + sprintf(str, "buffer created, size is %d\n", this->spec.size); + _ksys_debug_puts(str); + + this->spec.size >>= 1; + this->work_buffer = SDL_calloc(1, this->spec.size); + private->audio_response = 1; + if (!this->work_buffer) { + DestroyBuffer(private->hBuff); + exit(0); + } + + // wait for resume + while (SDL_AtomicGet(&this->paused)) + _ksys_thread_yield(); + _ksys_debug_puts("audio_thread created\n"); + + bPaused = 0; + private->audio_response = 1; + PlayBuffer(private->hBuff, 0); + + // main loop + while (1) { + if (!SDL_AtomicGet(&this->paused)) { + PlayBuffer(private->hBuff, 0); + bPaused = 0; + private->audio_response = 1; + } else if (SDL_AtomicGet(&this->paused)) { + StopBuffer(private->hBuff); + bPaused = 1; + private->audio_response = 1; + } else if (SDL_AtomicGet(&this->shutdown)) { + private->audio_response = 1; + StopBuffer(private->hBuff); + DestroyBuffer(private->hBuff); + exit(0); + } else { + _ksys_thread_info(&thread_info, main_slot); + if (thread_info.slot_state == KSYS_SLOT_STATE_FREE || thread_info.pid != main_tid) { + SDL_AtomicSet(&this->shutdown, 1); + continue; + } + } + if (bPaused) { + _ksys_delay(5); + } else { + _ksys_wait_signal(&snd_signal); + if (snd_signal.id != 0xFF000001) + continue; + callback(this->spec.userdata, this->work_buffer, this->spec.size); + SetBuffer(private->hBuff, this->work_buffer, ((int *)snd_signal.data)[2], this->spec.size); + } + } +} + +static void KOLIBRIAUDIO_CloseDevice(SDL_AudioDevice *device) +{ + if (device->hidden->audio_tid) + return; + + device->hidden->audio_response = 0; + while (!device->hidden->audio_response) + _ksys_thread_yield(); + + SDL_free(device->work_buffer); + SDL_free(device->hidden); +} + +static int KOLIBRIAUDIO_OpenDevice(_THIS, const char *devname) +{ + int ver; + char buff[100]; + + if (InitSound(&ver)) { + _ksys_debug_puts("Error: cannot load drivers!\n"); + return -1; + } + + private = (SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*private)); + if (!private) { + return SDL_OutOfMemory(); + } + + switch (this->spec.freq) { + +#define HANDLE_FREQ(freq, symb) \ + case freq: \ + switch (this->spec.channels) { \ + case 1: \ + switch (this->spec.format) { \ + case AUDIO_U8: \ + case AUDIO_S8: \ + private->used_format = PCM_1_8_##symb; \ + break; \ + case AUDIO_U16SYS: \ + case AUDIO_S16SYS: \ + private->used_format = PCM_1_16_##symb; \ + break; \ + } \ + break; \ + case 2: \ + switch (this->spec.format) { \ + case AUDIO_U8: \ + case AUDIO_S8: \ + private->used_format = PCM_2_8_##symb; \ + break; \ + case AUDIO_U16SYS: \ + case AUDIO_S16SYS: \ + private->used_format = PCM_2_16_##symb; \ + break; \ + } \ + break; \ + } \ + break; + + HANDLE_FREQ(48000, 48); + HANDLE_FREQ(44100, 44); + HANDLE_FREQ(32000, 32); + HANDLE_FREQ(24000, 24); + HANDLE_FREQ(22050, 22); + HANDLE_FREQ(16000, 16); + HANDLE_FREQ(12000, 12); + HANDLE_FREQ(11025, 11); + HANDLE_FREQ(8000, 8); + } + + if (!private->used_format) { + _ksys_debug_puts("Unknown audio format"); + return -1; + } + + _ksys_thread_info(&thread_info, KSYS_THIS_SLOT); + main_tid = thread_info.pid; + for (main_slot = 0;; main_slot++) { + _ksys_thread_info(&thread_info, main_slot); + if (thread_info.slot_state != KSYS_SLOT_STATE_FREE && thread_info.pid == main_tid) + break; + } + + global_device = this; + private->audio_tid = _ksys_create_thread(kolibri_audio_callback, thread_stack + AUDIO_THREAD_STACK_SIZE); + if (private->audio_tid < 0) { + _ksys_debug_puts("Cannot create audio thread"); + return -1; + } + + _ksys_focus_window(main_slot); + while (!private->audio_response) + _ksys_thread_yield(); + + if (!private->hBuff) { + _ksys_debug_puts("Cannot create audio buffer"); + return -1; + } + if (!this->work_buffer) { + _ksys_debug_puts("Cannot allocate audio buffer"); + return -1; + } + + this->spec.silence = (this->spec.format == AUDIO_U8 ? 0x80 : 0); + this->spec.samples = this->spec.size / this->spec.channels; + if (this->spec.format == AUDIO_U16SYS || this->spec.format == AUDIO_S16SYS) + this->spec.samples /= 2; + + sprintf(buff, "obtained size is %d, samples %d\n", this->spec.size, this->spec.samples); + _ksys_debug_puts(buff); + + return 0; +} + +static SDL_bool KOLIBRIAUDIO_Init(SDL_AudioDriverImpl *impl) +{ + impl->CloseDevice = KOLIBRIAUDIO_CloseDevice; + impl->OpenDevice = KOLIBRIAUDIO_OpenDevice; + impl->OnlyHasDefaultOutputDevice = SDL_TRUE; + impl->ProvidesOwnCallbackThread = SDL_TRUE; + + return SDL_TRUE; +} + +AudioBootStrap KOLIBRIAUDIO_bootstrap = { + KOLIBRIAUDIO_DRIVER_NAME, "Kolibri Audio Driver", + KOLIBRIAUDIO_Init, SDL_FALSE +}; + +#endif diff --git a/src/audio/kolibri/SDL_kolibriaudio.h b/src/audio/kolibri/SDL_kolibriaudio.h new file mode 100644 index 0000000..d835166 --- /dev/null +++ b/src/audio/kolibri/SDL_kolibriaudio.h @@ -0,0 +1,16 @@ + +#ifndef SDL_kolibriaudio_h_ +#define SDL_kolibriaudio_h_ + +#define _THIS SDL_AudioDevice *this +#define private this->hidden + +typedef struct SDL_PrivateAudioData +{ + SNDBUF hBuff; + int audio_tid; + uint32_t used_format; + volatile int audio_response; +} SDL_PrivateAudioData; + +#endif