/*
 * sdl_dll.c - Q3Base SDL shared object loading
 *
 * Copyright (C) 1999-2005  id Software
 * Copyright (C) 2005       Ed Schouten <ed@fxq.nl>
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "SDL_loadso.h"

#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"

#ifdef PKGLIBDIR
#define DLL_PATHS	4
#else
#define DLL_PATHS	3
#endif

extern char *FS_BuildOSPath (const char *base, const char *game,
	const char *qpath);

/*
 * Sys_LoadDll: Load a shared object and return its entrypoint and such
 */
void *Sys_LoadDll (const char *name, char *fqpath,
	int (**entry)(int, ...), int (*systemcalls)(int, ...)) 
{
	void  (*dllEntry)( int (*syscallptr)(int, ...));
	char *searchpath[DLL_PATHS];
	char basename[MAX_OSPATH], *fname, *gamedir;
	void *handle = NULL;
	int i;
	
	/* Get the module basename */
#if defined (_WIN32)
	Com_sprintf (basename, sizeof (basename), "%s.dll", name);
#elif defined (MACOS_X)
	Com_sprintf (basename, sizeof (basename), "%s.bundle/Contents/MacOS/%s",
		name, name);
#else	/* Asssume UNIX */
	Com_sprintf (basename, sizeof (basename), "%s.so", name);
#endif

	Com_Printf ("Sys_LoadDll: searching for %s\n", basename);

	/* Get the search paths */
	searchpath[0] = Sys_Cwd ();
	searchpath[1] = Cvar_VariableString ("fs_basepath");
#ifdef PKGLIBDIR
	searchpath[2] = PKGLIBDIR;
	searchpath[3] = Cvar_VariableString ("fs_homepath");
#else /* !PKGLIBDIR */
	searchpath[2] = Cvar_VariableString ("fs_homepath");
#endif /* PKGLIBDIR */
	gamedir = Cvar_VariableString( "fs_game" );

	for (i = 0; (i < DLL_PATHS) && !handle; i++)
	{
		fname = FS_BuildOSPath (searchpath[i], gamedir, basename);
		Com_Printf ("Sys_LoadDll: trying to load %s\n", fname);
		handle = SDL_LoadObject (fname);
	}

	if (handle == NULL)
	{
		Com_Printf ("Sys_LoadDll: unable to find %s\n", basename);
		return NULL;
	}

	dllEntry = SDL_LoadFunction (handle, "dllEntry"); 
	*entry = SDL_LoadFunction (handle, "vmMain");

	/* It looks like the object we loaded was invalid */
	if ((dllEntry == NULL) || (*entry == NULL))
	{
		Com_Printf ("Sys_LoadDll: %s seems to be invalid\n", fname);
		SDL_UnloadObject (handle);
		return NULL;
	}

	dllEntry (systemcalls);
	Q_strncpyz (fqpath, fname, MAX_QPATH);

	Com_Printf ("Sys_LoadDll: successfully loaded %s\n", fname);
	return handle;
}

/*
 * Sys_UnloadDll: Unload a shared object
 */
void Sys_UnloadDll (void *handle)
{
	SDL_UnloadObject (handle);
}
