Revert "Introduce a small api for loading code (codecs,plugins) from disk/memory."

I don't understand the build error at all, plugin_bss_start is clearly defined in plugin.lds

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27901 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/codecs.c b/apps/codecs.c
index b072c65..9e77dd9 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -28,7 +28,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include "string-extra.h"
-#include "load_code.h"
 #include "debug.h"
 #include "button.h"
 #include "dir.h"
@@ -75,13 +74,26 @@
 
 extern void* plugin_get_audio_buffer(size_t *buffer_size);
 
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE) && defined(HAVE_RECORDING)
 #undef open
 static int open(const char* pathname, int flags, ...)
 {
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
+    int fd;
+    if (flags & O_CREAT)
+    {
+        va_list ap;
+        va_start(ap, flags);
+        fd = sim_open(pathname, flags, va_arg(ap, unsigned int));
+        va_end(ap);
+    }
+    else
+        fd = sim_open(pathname, flags);
+
+    return fd;
+#else
     return file_open(pathname, flags);
-}
 #endif
+}
 struct codec_api ci = {
 
     0, /* filesize */
@@ -185,46 +197,62 @@
              CODECS_DIR, codec_root_fn);
 }
 
-static int codec_load_ram(void *handle, struct codec_api *api)
+static int codec_load_ram(int size, struct codec_api *api)
 {
-    struct codec_header *hdr = lc_get_header(handle);
+    struct codec_header *hdr;
     int status;
-
-    if (hdr == NULL
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+    hdr = (struct codec_header *)codecbuf;
+        
+    if (size <= (signed)sizeof(struct codec_header)
         || (hdr->magic != CODEC_MAGIC
 #ifdef HAVE_RECORDING
              && hdr->magic != CODEC_ENC_MAGIC
 #endif
             )
         || hdr->target_id != TARGET_ID
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
         || hdr->load_addr != codecbuf
-        || hdr->end_addr > codecbuf + CODEC_SIZE
-#endif
-        )
+        || hdr->end_addr > codecbuf + CODEC_SIZE)
     {
         logf("codec header error");
-        lc_close(handle);
         return CODEC_ERROR;
     }
 
+    codec_size = hdr->end_addr - codecbuf;
+
+#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
+    void *pd;
+    
+    hdr = sim_codec_load_ram(codecbuf, size, &pd);
+
+    if (pd == NULL)
+        return CODEC_ERROR;
+
+    if (hdr == NULL
+        || (hdr->magic != CODEC_MAGIC
+#ifdef HAVE_RECORDING
+             && hdr->magic != CODEC_ENC_MAGIC
+#endif
+           )
+        || hdr->target_id != TARGET_ID) {
+        sim_codec_close(pd);
+        return CODEC_ERROR;
+    }
+
+    codec_size = codecbuf - codecbuf;
+
+#endif /* CONFIG_PLATFORM */
     if (hdr->api_version > CODEC_API_VERSION
         || hdr->api_version < CODEC_MIN_API_VERSION) {
-        logf("codec api version error");
-        lc_close(handle);
+        sim_codec_close(pd);
         return CODEC_ERROR;
     }
 
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
-    codec_size = hdr->end_addr - codecbuf;
-#else
-    codec_size = 0;
-#endif
-
     *(hdr->api) = api;
+    cpucache_invalidate();
     status = hdr->entry_point();
 
-    lc_close(handle);
+    sim_codec_close(pd);
 
     return status;
 }
@@ -232,37 +260,36 @@
 int codec_load_buf(unsigned int hid, struct codec_api *api)
 {
     int rc;
-    void *handle;
     rc = bufread(hid, CODEC_SIZE, codecbuf);
     if (rc < 0) {
         logf("error loading codec");
         return CODEC_ERROR;
     }
-    handle = lc_open_from_mem(codecbuf, rc);
-    if (handle == NULL)
-    {
-        logf("error loading codec");
-        return CODEC_ERROR;
-    }
-
     api->discard_codec();
-    return codec_load_ram(handle, api);
+    return codec_load_ram(rc, api);
 }
 
 int codec_load_file(const char *plugin, struct codec_api *api)
 {
     char path[MAX_PATH];
-    void *handle;
+    int fd;
+    int rc;
 
     codec_get_full_path(path, plugin);
-
-    handle = lc_open(path, codecbuf, CODEC_SIZE);
-
-    if (handle == NULL) {
-        logf("Codec load error");
+    
+    fd = open(path, O_RDONLY);
+    if (fd < 0) {
+        logf("Codec load error:%d", fd);
         splashf(HZ*2, "Couldn't load codec: %s", path);
+        return fd;
+    }
+    
+    rc = read(fd, &codecbuf[0], CODEC_SIZE);
+    close(fd);
+    if (rc <= 0) {
+        logf("Codec read error");
         return CODEC_ERROR;
     }
 
-    return codec_load_ram(handle, api);
+    return codec_load_ram((size_t)rc, api);
 }
diff --git a/apps/plugin.c b/apps/plugin.c
index 53a05bf..cc540cd 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -42,7 +42,6 @@
 #include "errno.h"
 #include "diacritic.h"
 #include "filefuncs.h"
-#include "load_code.h"
 
 #if CONFIG_CHARGING
 #include "power.h"
@@ -76,19 +75,21 @@
 
 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
+void *sim_plugin_load(char *plugin, void **pd);
+void sim_plugin_close(void *pd);
 void sim_lcd_ex_init(unsigned long (*getpixel)(int, int));
 void sim_lcd_ex_update_rect(int x, int y, int width, int height);
 #else
+#define sim_plugin_close(x)
 extern unsigned char pluginbuf[];
 #include "bitswap.h"
 #endif
 
 /* for actual plugins only, not for codecs */
+static bool plugin_loaded = false;
 static int  plugin_size = 0;
 static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
 static char current_plugin[MAX_PATH];
-/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */
-static void *current_plugin_handle;
 
 char *plugin_get_current_filename(void);
 
@@ -727,60 +728,98 @@
 {
     int rc, i;
     struct plugin_header *hdr;
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
+    void *pd;
+#else /* PLATFOR_NATIVE */
+    int fd;
+    ssize_t readsize;
+#if NUM_CORES > 1
+    unsigned my_core;
+#endif
+#endif /* CONFIG_PLATFORM */
 
 #if LCD_DEPTH > 1
     fb_data* old_backdrop;
 #endif
 
-    if (current_plugin_handle && pfn_tsr_exit)
-    {    /* if we have a resident old plugin and a callback */
+    if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
+    {
         if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false )
         {
             /* not allowing another plugin to load */
             return PLUGIN_OK;
         }
-        lc_close(current_plugin_handle);
-        current_plugin_handle = pfn_tsr_exit = NULL;
+        pfn_tsr_exit = NULL;
+        plugin_loaded = false;
     }
 
     splash(0, ID2P(LANG_WAIT));
     strcpy(current_plugin, plugin);
 
-    current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE);
-    if (current_plugin_handle == NULL) {
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
+    hdr = sim_plugin_load((char *)plugin, &pd);
+    if (pd == NULL) {
         splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
         return -1;
     }
-
-    hdr = lc_get_header(current_plugin_handle);
-
     if (hdr == NULL
         || hdr->magic != PLUGIN_MAGIC
-        || hdr->target_id != TARGET_ID
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
-        || hdr->load_addr != pluginbuf
-        || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE
-#endif
-        )
-    {
-        lc_close(current_plugin_handle);
+        || hdr->target_id != TARGET_ID) {
+        sim_plugin_close(pd);
         splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
         return -1;
     }
     if (hdr->api_version > PLUGIN_API_VERSION
-        || hdr->api_version < PLUGIN_MIN_API_VERSION)
-    {
-        lc_close(current_plugin_handle);
+        || hdr->api_version < PLUGIN_MIN_API_VERSION) {
+        sim_plugin_close(pd);
         splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
         return -1;
     }
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
-    plugin_size = hdr->end_addr - pluginbuf;
 #else
-    plugin_size = 0;
+    fd = open(plugin, O_RDONLY);
+    if (fd < 0) {
+        splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
+        return fd;
+    }
+#if NUM_CORES > 1
+    /* Make sure COP cache is flushed and invalidated before loading */
+    my_core = switch_core(CURRENT_CORE ^ 1);
+    cpucache_invalidate();
+    switch_core(my_core);
+#endif
+
+    readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE);
+    close(fd);
+
+    if (readsize < 0) {
+        splashf(HZ*2, str(LANG_READ_FAILED), plugin);
+        return -1;
+    }
+    hdr = (struct plugin_header *)pluginbuf;
+
+    if ((unsigned)readsize <= sizeof(struct plugin_header)
+        || hdr->magic != PLUGIN_MAGIC
+        || hdr->target_id != TARGET_ID
+        || hdr->load_addr != pluginbuf
+        || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) {
+        splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
+        return -1;
+    }
+    if (hdr->api_version > PLUGIN_API_VERSION
+        || hdr->api_version < PLUGIN_MIN_API_VERSION) {
+        splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
+        return -1;
+    }
+    plugin_size = hdr->end_addr - pluginbuf;
+
+    /* zero out bss area only, above guards end of pluginbuf */
+    if (plugin_size > readsize)
+        memset(pluginbuf + readsize, 0, plugin_size - readsize);
 #endif
 
     *(hdr->api) = &rockbox_api;
+    plugin_loaded = true;
+    
 
 #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
     old_backdrop = lcd_get_backdrop();
@@ -795,6 +834,8 @@
 
     FOR_NB_SCREENS(i)
        viewportmanager_theme_enable(i, false, NULL);
+
+    cpucache_invalidate();
     
 #ifdef HAVE_TOUCHSCREEN
     touchscreen_set_mode(TOUCHSCREEN_BUTTON);
@@ -806,12 +847,6 @@
 
     rc = hdr->entry_point(parameter);
 
-    if (!pfn_tsr_exit)
-    {   /* close handle if plugin is no tsr one */
-        lc_close(current_plugin_handle);
-        current_plugin_handle = NULL;
-    }
-
     /* Go back to the global setting in case the plugin changed it */
 #ifdef HAVE_TOUCHSCREEN
     touchscreen_set_mode(global_settings.touch_mode);
@@ -852,8 +887,11 @@
     FOR_NB_SCREENS(i)
         viewportmanager_theme_undo(i, false);
 
+    if (pfn_tsr_exit == NULL)
+        plugin_loaded = false;
+
 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
-    if(open_files != 0 && !current_plugin_handle)
+    if(open_files != 0 && !plugin_loaded)
     {
         int fd;
         logf("Plugin '%s' leaks file handles", plugin);
@@ -871,6 +909,8 @@
     }
 #endif
 
+    sim_plugin_close(pd);
+
     if (rc == PLUGIN_ERROR)
         splash(HZ*2, str(LANG_PLUGIN_ERROR));
 
@@ -883,7 +923,7 @@
 {
     int buffer_pos;
 
-    if (current_plugin_handle)
+    if (plugin_loaded)
     {
         if (plugin_size >= PLUGIN_BUFFER_SIZE)
             return NULL;
diff --git a/apps/plugins/plugin_crt0.c b/apps/plugins/plugin_crt0.c
index e34124c..536ecca 100644
--- a/apps/plugins/plugin_crt0.c
+++ b/apps/plugins/plugin_crt0.c
@@ -32,8 +32,6 @@
 #define EXIT_MAGIC 0x0CDEBABE
 
 extern enum plugin_status plugin_start(const void*);
-extern unsigned char plugin_bss_start[];
-extern unsigned char plugin_end_addr[];
 
 static jmp_buf __exit_env;
 /* only 1 atexit handler for now, chain in the exit handler if you need more */
@@ -63,10 +61,6 @@
     int exit_ret;
     enum plugin_status ret;
 
-    /* zero out the bss section */
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
-    rb->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start);
-#endif
     /* we come back here if exit() was called or the plugin returned normally */
     exit_ret = setjmp(__exit_env);
     if (exit_ret == 0)
diff --git a/firmware/SOURCES b/firmware/SOURCES
index f83b789..e6157fa 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -3,7 +3,6 @@
 backlight.c
 buffer.c
 general.c
-load_code.c
 powermgmt.c
 system.c
 usb.c
diff --git a/firmware/export/load_code.h b/firmware/export/load_code.h
deleted file mode 100644
index f4fa8f9..0000000
--- a/firmware/export/load_code.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
- *             __________               __   ___.
- *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
- *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
- *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
- *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
- *                     \/            \/     \/    \/            \/
- * $Id$
- *
- * Copyright (C) 2010 by Thomas Martitz
- *
- * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-
-#include "config.h"
-
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
-#include "system.h"
-
-extern void *lc_open(const char *filename, char *buf, size_t buf_size);
-/* header is always at the beginning of the blob, and handle actually points
- * to the start of the blob */
-static inline char *lc_open_from_mem(void* addr, size_t blob_size)
-{
-    (void)blob_size;
-    cpucache_invalidate();
-    return addr;
-}
-static inline void *lc_get_header(void *handle) { return handle; }
-/* no need to do anything */
-static inline void lc_close(void *handle) { (void)handle; }
-
-#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
-
-/* don't call these directly for loading code
- * they're to be wrapped by platform specific functions */
-extern void *_lc_open(const char *filename, char *buf, size_t buf_size);
-extern void *_lc_get_header(void *handle);
-extern void  _lc_close(void *handle);
-
-extern void *lc_open(const char *filename, char *buf, size_t buf_size);
-/* not possiible on hosted platforms */
-extern void *lc_open_from_mem(void *addr, size_t blob_size);
-extern void *lc_get_header(void *handle);
-extern void  lc_close(void *handle);
-extern const char* lc_last_error(void);
-#endif
diff --git a/firmware/load_code.c b/firmware/load_code.c
deleted file mode 100644
index 9e8e71f..0000000
--- a/firmware/load_code.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/***************************************************************************
- *             __________               __   ___.
- *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
- *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
- *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
- *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
- *                     \/            \/     \/    \/            \/
- * $Id$
- *
- * Copyright (C) 2010 by Thomas Martitz
- *
- * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include "config.h"
-#include "system.h"
-#include "file.h"
-#include "debug.h"
-#include "load_code.h"
-
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
-/* load binary blob from disk to memory, returning a handle */
-void * lc_open(const char *filename, char *buf, size_t buf_size)
-{
-    int fd = open(filename, O_RDONLY);
-    ssize_t read_size;
-
-    if (fd < 0)
-    {
-        DEBUGF("Could not open file");
-        return NULL;
-    }
-
-#if NUM_CORES > 1
-    /* Make sure COP cache is flushed and invalidated before loading */
-    {
-        int my_core = switch_core(CURRENT_CORE ^ 1);
-        cpucache_invalidate();
-        switch_core(my_core);
-    }
-#endif
-
-    read_size = read(fd, buf, buf_size);
-    close(fd);
-    cpucache_invalidate();
-
-    if (read_size < 0)
-    {
-        DEBUGF("Could not read from file");
-        return NULL;
-    }
-    return buf;
-}
-
-#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
-/* libdl wrappers */
-
-
-#ifdef WIN32
-/* win32 */
-#include <windows.h>
-#define dlopen(_x_, _y_) LoadLibraryW(_x_)
-#define dlsym(_x_, _y_) (void *)GetProcAddress(_x_, _y_)
-#define dlclose(_x_) FreeLibrary(_x_)
-static inline char *_dlerror(void)
-{
-    static char err_buf[64];
-    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
-                   err_buf, sizeof(err_buf), NULL);
-    return err_buf;
-}
-#define dlerror _dlerror
-#else
-/* unix */
-#include <dlfcn.h>
-#define O_BINARY 0
-#endif
-#include <stdio.h>
-#include "rbpaths.h"
-#include "general.h"
-
-void * _lc_open(const char *filename, char *buf, size_t buf_size)
-{
-    (void)buf;
-    (void)buf_size;
-    void* dl_handle = dlopen(filename, RTLD_NOW);
-    return dl_handle;
-}
-
-void *lc_open_from_mem(void *addr, size_t blob_size)
-{
-    int fd, i;
-    char temp_filename[MAX_PATH];
-
-    /* We have to create the dynamic link library file from ram so we
-       can simulate the codec loading. With voice and crossfade,
-       multiple codecs may be loaded at the same time, so we need
-       to find an unused filename */
-    for (i = 0; i < 10; i++)
-    {
-#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
-        /* we need that path fixed, since get_user_file_path()
-         * gives us the folder on the sdcard where we cannot load libraries
-         * from (no exec permissions)
-         */
-        snprintf(temp_filename, sizeof(temp_filename),
-                 "/data/data/org.rockbox/app_rockbox/libtemp_binary_%d.so", i);
-#else
-        char name[MAX_PATH];
-        const char *_name = get_user_file_path(ROCKBOX_DIR, NEED_WRITE, name, sizeof(name));
-        snprintf(temp_filename, sizeof(temp_filename),
-                 "%slibtemp_binary_%d.dll", _name, i);
-#endif
-        fd = open(temp_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0766);
-        if (fd >= 0)
-            break;  /* Created a file ok */
-    }
-
-    DEBUGF("Creating %s\n", temp_filename);
-    if (fd < 0)
-    {
-        DEBUGF("open failed\n");
-        return NULL;
-    }
-
-    if (write(fd, addr, blob_size) < (ssize_t)blob_size)
-    {
-        DEBUGF("Write failed\n");
-        close(fd);
-        remove(temp_filename);
-        return NULL;
-    }
-
-    close(fd);
-    return lc_open(temp_filename, NULL, 0);
-}
-
-
-void *_lc_get_header(void *handle)
-{
-    char *ret = dlsym(handle, "__header");
-    if (ret == NULL)
-        ret = dlsym(handle, "___header");
-
-    return ret;
-}
-
-void _lc_close(void *handle)
-{
-    if (handle)
-        dlclose(handle);
-}
-
-const char *lc_last_error(void)
-{
-    return dlerror();
-}
-#endif
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c
index c8d6a8a..4c0fa33 100644
--- a/uisimulator/common/io.c
+++ b/uisimulator/common/io.c
@@ -58,7 +58,6 @@
 #include "debug.h"
 #include "ata.h" /* for IF_MV2 et al. */
 #include "rbpaths.h"
-#include "load_code.h"
 
 /* keep this in sync with file.h! */
 #undef MAX_PATH /* this avoids problems when building simulator */
@@ -531,28 +530,116 @@
 #include <dlfcn.h>
 #endif
 
-
-void *lc_open(const char *filename, char *buf, size_t buf_size)
+void *sim_codec_load_ram(char* codecptr, int size, void **pd)
 {
-    const char *sim_path = get_sim_pathname(filename);
-    void *handle = _lc_open((const char*)UTF8_TO_OS(sim_path), buf, buf_size);
+    void *hdr;
+    char path[MAX_PATH];
+    int fd;
+    int codec_count;
+#ifdef WIN32
+    char buf[MAX_PATH];
+#endif
 
-    if (handle == NULL)
+    *pd = NULL;
+
+    /* We have to create the dynamic link library file from ram so we
+       can simulate the codec loading. With voice and crossfade,
+       multiple codecs may be loaded at the same time, so we need
+       to find an unused filename */
+    for (codec_count = 0; codec_count < 10; codec_count++)
     {
-        DEBUGF("failed to load %s\n", filename);
-        DEBUGF("lc_open(%s): %s\n", filename, lc_last_error());
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+        /* we need that path fixed, since get_user_file_path()
+         * gives us the folder on the sdcard where we cannot load libraries
+         * from (no exec permissions)
+         */
+        snprintf(path, sizeof(path),
+                 "/data/data/org.rockbox/app_rockbox/libtemp_codec_%d.so",
+                 codec_count);
+#else
+        char name[MAX_PATH];
+        const char *_name = get_user_file_path(ROCKBOX_DIR, 0, name, sizeof(name));
+        snprintf(path, sizeof(path), "%s/_temp_codec%d.dll", get_sim_pathname(_name), codec_count);
+#endif
+        fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU);
+        if (fd >= 0)
+            break;  /* Created a file ok */
     }
-    return handle;
+    if (fd < 0)
+    {
+        DEBUGF("failed to open for write: %s\n", path);
+        return NULL;
+    }
+
+    if (write(fd, codecptr, size) != size)
+    {
+        DEBUGF("write failed");
+        return NULL;
+    }
+    close(fd);
+
+    /* Now load the library. */
+    *pd = dlopen(path, RTLD_NOW);
+    if (*pd == NULL) 
+    {
+        DEBUGF("failed to load %s\n", path);
+#ifdef WIN32
+        FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
+                       buf, sizeof buf, NULL);
+        DEBUGF("dlopen(%s): %s\n", path, buf);
+#else
+        DEBUGF("dlopen(%s): %s\n", path, dlerror());
+#endif
+        return NULL;
+    }
+
+    hdr = dlsym(*pd, "__header");
+    if (!hdr)
+        hdr = dlsym(*pd, "___header");
+
+    return hdr;       /* maybe NULL if symbol not present */
 }
 
-void *lc_get_header(void *handle)
+void sim_codec_close(void *pd)
 {
-    return _lc_get_header(handle);
+    dlclose(pd);
 }
 
-void lc_close(void *handle)
+void *sim_plugin_load(char *plugin, void **pd)
 {
-    _lc_close(handle);
+    void *hdr;
+    char path[MAX_PATH];
+#ifdef WIN32
+    char buf[MAX_PATH];
+#endif
+
+    snprintf(path, sizeof(path), "%s", get_sim_pathname(plugin));
+
+    *pd = NULL;
+
+    *pd = dlopen(path, RTLD_NOW);
+    if (*pd == NULL) {
+        DEBUGF("failed to load %s\n", plugin);
+#ifdef WIN32
+        FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
+                       buf, sizeof(buf), NULL);
+        DEBUGF("dlopen(%s): %s\n", path, buf);
+#else
+        DEBUGF("dlopen(%s): %s\n", path, dlerror());
+#endif
+        return NULL;
+    }
+
+    hdr = dlsym(*pd, "__header");
+    if (!hdr)
+        hdr = dlsym(*pd, "___header");
+
+    return hdr;    /* maybe NULL if symbol not present */
+}
+
+void sim_plugin_close(void *pd)
+{
+    dlclose(pd);
 }
 
 #ifdef WIN32