shithub: choc

Download patch

ref: a4695f20fbaba6d4fc351edb78825328cd95f49f
parent: 1d92cd1477d44245c151c1f39b15c356019d8359
author: Simon Howard <fraggle@gmail.com>
date: Wed May 27 14:01:00 EDT 2009

Add initial SDL driver.

Subversion-branch: /branches/opl-branch
Subversion-revision: 1534

--- a/opl/Makefile.am
+++ b/opl/Makefile.am
@@ -7,5 +7,6 @@
                             opl_internal.h        \
         opl.c               opl.h                 \
         opl_linux.c                               \
+        opl_sdl.c                                 \
         fmopl.c             fmopl.h
 
--- /dev/null
+++ b/opl/opl_sdl.c
@@ -1,0 +1,172 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 Simon Howard
+//
+// 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.
+//
+// DESCRIPTION:
+//     OPL SDL interface.
+//
+//-----------------------------------------------------------------------------
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "SDL.h"
+#include "SDL_mixer.h"
+
+#include "fmopl.h"
+
+#include "opl.h"
+#include "opl_internal.h"
+
+// TODO:
+#define opl_sample_rate 22050
+
+static FM_OPL *opl_emulator = NULL;
+static int sdl_was_initialised = 0;
+static int mixing_freq, mixing_channels;
+static Uint16 mixing_format;
+
+static int SDLIsInitialised(void)
+{
+    int freq, channels;
+    Uint16 format;
+
+    return Mix_QuerySpec(&freq, &format, &channels);
+}
+
+// Callback function to fill a new sound buffer:
+
+static void OPL_Mix_Callback(void *udata, Uint8 *stream, int len)
+{
+}
+
+static void OPL_SDL_Shutdown(void)
+{
+    if (sdl_was_initialised)
+    {
+        Mix_CloseAudio();
+        SDL_QuitSubSystem(SDL_INIT_AUDIO);
+        sdl_was_initialised = 0;
+    }
+
+    if (opl_emulator != NULL)
+    {
+        OPLDestroy(opl_emulator);
+        opl_emulator = NULL;
+    }
+}
+
+static int OPL_SDL_Init(unsigned int port_base)
+{
+    // Check if SDL_mixer has been opened already
+    // If not, we must initialise it now
+
+    if (!SDLIsInitialised())
+    {
+        if (SDL_Init(SDL_INIT_AUDIO) < 0)
+        {
+            fprintf(stderr, "Unable to set up sound.\n");
+            return 0;
+        }
+
+        if (Mix_OpenAudio(opl_sample_rate, AUDIO_S16SYS, 2, 1024) < 0)
+        {
+            fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
+
+            SDL_QuitSubSystem(SDL_INIT_AUDIO);
+            return 0;
+        }
+
+        SDL_PauseAudio(0);
+
+        // When this module shuts down, it has the responsibility to 
+        // shut down SDL.
+
+        sdl_was_initialised = 1;
+    }
+    else
+    {
+        sdl_was_initialised = 0;
+    }
+
+    // Get the mixer frequency, format and number of channels.
+
+    Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels);
+
+    // Only supports AUDIO_S16SYS
+
+    if (mixing_format != AUDIO_S16SYS || mixing_channels != 2)
+    {
+        fprintf(stderr, 
+                "OPL_SDL only supports native signed 16-bit LSB, "
+                "stereo format!\n");
+
+        OPL_SDL_Shutdown();
+        return 0;
+    }
+
+    // Create the emulator structure:
+
+    opl_emulator = makeAdlibOPL(mixing_freq);
+
+    if (opl_emulator == NULL)
+    {
+        fprintf(stderr, "Failed to initialise software OPL emulator!\n");
+        OPL_SDL_Shutdown();
+        return 0;
+    }
+
+    // TODO: This should be music callback? or-?
+    Mix_SetPostMix(OPL_Mix_Callback, NULL);
+
+    return 1;
+}
+
+static unsigned int OPL_SDL_PortRead(opl_port_t port)
+{
+    if (opl_emulator != NULL)
+    {
+        return OPLRead(opl_emulator, port);
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+static void OPL_SDL_PortWrite(opl_port_t port, unsigned int value)
+{
+    if (opl_emulator != NULL)
+    {
+        OPLWrite(opl_emulator, port, value);
+    }
+}
+
+opl_driver_t opl_sdl_driver =
+{
+    "SDL",
+    OPL_SDL_Init,
+    OPL_SDL_Shutdown,
+    OPL_SDL_PortRead,
+    OPL_SDL_PortWrite
+};
+