
/*
**
**	wbstart.library emulation v44
**	© 1999 by Stephan Rupprecht
**	All Rights reserved
**
*/

#include <exec/resident.h>
#include <exec/initializers.h>
#include <exec/execbase.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <dos/dos.h>

#include <inline/exec.h>
#include <inline/wb.h>
#include <inline/utility.h>
#include <inline/dos.h>

#include "library.h"

#define SysBase			WBStartBase->wbsb_SysBase
#define WorkbenchBase	WBStartBase->wbsb_WorkbenchBase
#define UtilityBase		WBStartBase->wbsb_UtilityBase
#define DOSBase			WBStartBase->wbsb_DOSBase

#ifndef BPTR
#define BPTR		ULONG
#endif

#define REG(r)		__asm( #r )
#define VERSION		2
#define REVISION	2

/****************************************************************************/

 struct Library *LibInit(ULONG Segment REG(a0), struct WBStartBase *WBStartBase REG(d0), struct Library * REG(a6));
 struct Library *LibOpen(struct WBStartBase *WBStartBase REG(a6));
 ULONG LibExpunge(struct WBStartBase *WBStartBase REG(a6));
 ULONG LibClose(struct WBStartBase *WBStartBase REG(a6));
 LONG LibExtFunc(void);
 BOOL L_OpenLibs( struct WBStartBase *WBStartBase );
 VOID L_CloseLibs( struct WBStartBase *WBStartBase );
 LONG WBStartTagList( struct TagItem *tlist REG(a0), struct WBStartBase *WBStartBase REG(a6) );

/****************************************************************************/

ULONG LibVectors[] =
{
	(ULONG)LibOpen,
	(ULONG)LibClose,
	(ULONG)LibExpunge,
	(ULONG)LibExtFunc,
	(ULONG)LibExtFunc,
	(ULONG)WBStartTagList,
	(ULONG)-1L
};

UBYTE	LibName[] = "wbstart.library",
		LibID[] = "wbstart.library 44.1 (22.10.99) emulation (C) 1999 by Stephan Rupprecht";

ULONG LibInitTab[] =
{
	(ULONG) sizeof(struct WBStartBase),
	(ULONG) LibVectors,
	(ULONG) NULL,
	(ULONG) LibInit
};

struct Resident ROMTag =     /* do not change */
{
	RTC_MATCHWORD,
 	&ROMTag,
 	&ROMTag + 1,
	RTF_AUTOINIT,
 	VERSION,
	NT_LIBRARY,
 	0,
	LibName,
	LibID,
	(APTR)&LibInitTab
};

/****************************************************************************/

LONG nop(void)
{
	return(-1L);
}

/****************************************************************************/

LONG LibExtFunc(void)
{
	return(0L);
}

/****************************************************************************/

#if 0
void kprintf( STRPTR FormatStr, ... )
{
	#undef SysBase
	struct Library	*SysBase = (*(struct Library **)4L);
	TEXT	PutChData[64];
	STRPTR	p = PutChData;
	
	RawDoFmt(FormatStr, ((STRPTR)(&FormatStr))+4, (void (*)())"\x16\xc0\x4e\x75", PutChData);
	
	do RawPutChar( *p );
	while( *p++ );
	#define SysBase	WBStartBase->wbsb_SysBase
}
#else
#define kprintf(...)
#endif

/****************************************************************************/

struct Library *
  LibInit(ULONG Segment REG(a0), struct WBStartBase *WBStartBase REG(d0), struct Library *ExecBase REG(a6))
{
	kprintf( "LibInit()\n" );

	SysBase = ExecBase;
	WBStartBase->LibSegment = Segment;
	WBStartBase->LibNode.lib_Revision = REVISION;
	
	InitSemaphore( &WBStartBase->wbsb_LibLock );
	ObtainSemaphore( &WBStartBase->wbsb_LibLock );
	
	if( ((struct ExecBase *)ExecBase)->AttnFlags & AFF_68020 )
	{	
		if( L_OpenLibs( WBStartBase ) )
		{	
			kprintf( "LibInit()- ok\n" );
			ReleaseSemaphore( &WBStartBase->wbsb_LibLock );
			return((struct Library *)WBStartBase);			 
		}
		
		L_CloseLibs( WBStartBase );
	}

	ReleaseSemaphore( &WBStartBase->wbsb_LibLock );

	FreeMem((BYTE *)WBStartBase-WBStartBase->LibNode.lib_NegSize, 
		WBStartBase->LibNode.lib_NegSize + WBStartBase->LibNode.lib_PosSize);
	
	kprintf( "LibInit() - error\n" );
	
	return(NULL);
}

/****************************************************************************/

struct Library *  LibOpen(struct WBStartBase *WBStartBase REG(a6))
{	
	kprintf( "LibOpen()\n" );
	ObtainSemaphore( &WBStartBase->wbsb_LibLock );
	WBStartBase->LibNode.lib_Flags &= ~LIBF_DELEXP;
	WBStartBase->LibNode.lib_OpenCnt++;
	ReleaseSemaphore( &WBStartBase->wbsb_LibLock );
	kprintf( "LibOpen() - okay\n" );
	return((struct Library *)WBStartBase);
}

/****************************************************************************/

ULONG  LibExpunge(struct WBStartBase *WBStartBase REG(a6))
{
	ULONG	retval = NULL;
	kprintf( "LibExpunge()\n" );
	ObtainSemaphore( &WBStartBase->wbsb_LibLock );
	
 	if( WBStartBase->LibNode.lib_OpenCnt )  
	{
		WBStartBase->LibNode.lib_Flags |= LIBF_DELEXP;
		kprintf( "LibExpunge() - still in use\n" );
	}
	else
	{						
		L_CloseLibs( WBStartBase );
			
	 	Remove((struct Node *)WBStartBase);

		FreeMem((BYTE *)WBStartBase-WBStartBase->LibNode.lib_NegSize,
	          WBStartBase->LibNode.lib_NegSize + WBStartBase->LibNode.lib_PosSize);

		retval = (ULONG) WBStartBase->LibSegment;
		
		kprintf( "LibExpunge() - okay\n" );
	}
		
	ReleaseSemaphore( &WBStartBase->wbsb_LibLock );

 	return retval;
}

/****************************************************************************/

ULONG  LibClose(struct WBStartBase *WBStartBase REG(a6))
{	
 	ULONG	retval = NULL;
	
	ObtainSemaphore( &WBStartBase->wbsb_LibLock );
	kprintf( "LibClose()\n" );
 	if( ! ( WBStartBase->LibNode.lib_OpenCnt ) || ! ( --WBStartBase->LibNode.lib_OpenCnt ) )
 	{
 		if( WBStartBase->LibNode.lib_Flags & LIBF_DELEXP )
 		{
 			retval = LibExpunge( WBStartBase );
 		}
 	}
 	
 	ReleaseSemaphore( &WBStartBase->wbsb_LibLock );
	kprintf( "LibClose - retval %08lx\n", retval );
 	return retval;
}

/****************************************************************************/

 BOOL L_OpenLibs( struct WBStartBase *WBStartBase )
{
	if(	( WorkbenchBase = OpenLibrary( "workbench.library", 44L ) ) &&
		( DOSBase = OpenLibrary( "dos.library", 40L ) ) &&
		( UtilityBase = OpenLibrary( "utility.library", 40L ) ) )
	{
		return TRUE;
	}
	
	return FALSE;
}

/****************************************************************************/

 VOID L_CloseLibs( struct WBStartBase *WBStartBase )
{
	CloseLibrary( WorkbenchBase );
	CloseLibrary( DOSBase );
	CloseLibrary( UtilityBase );
}

/****************************************************************************/

 LONG WBStartTagList( struct TagItem *tlist REG(a0), struct WBStartBase *WBStartBase REG(a6) )
{
	struct TagItem	*ti;
	struct WBArg	*args = NULL;
	STRPTR			 name = NULL;
	BPTR			 dirlock = NULL;
	ULONG			 argc = 0UL, 
					 ret = 20UL;
	
	kprintf( "WBStartTagList() - taglist at %08lx\n", tlist );
	
	while( ti = NextTagItem( &tlist ) )
	{	
		ULONG	data = ti->ti_Data;
	
		switch( ti->ti_Tag )
		{
			case WBStart_Name:
				name = (STRPTR) data;
				kprintf( "Name: %s\n", name );
			break;
			
			case WBStart_DirectoryName:
				if( data )
				{
					UnLock( dirlock );				
					dirlock = Lock( (STRPTR) data, SHARED_LOCK );
					kprintf( "DirName: %s\n", data );
				}
			break;
			
			case WBStart_DirectoryLock:
				UnLock( dirlock );
				dirlock = DupLock( (BPTR) data );
				kprintf( "DirLock: %08lx\n", dirlock );
			break;
			
			case WBStart_ArgumentCount:
				argc = data;
			break;
			
			case WBStart_ArgumentList:
				args = (struct WBArg *) data;
			break;
		}
	}
	
	if( name )
	{		
		if( argc && args )
		{	
			kprintf( "Args: %ld\n", argc );
		
			if( ti = tlist = AllocVec( 2 * (argc+1) * sizeof( struct TagItem ), MEMF_ANY ) )
			{
				kprintf( "Alloced %ld bytes at: %08lx\n", 2 * (argc+1) * sizeof( struct TagItem ), tlist );
			
				while( argc-- )
				{
					kprintf( "LOCK: %08lx, NAME: %s\n", args->wa_Lock, args->wa_Name );
					ti->ti_Tag  = WBOPENA_ArgLock;
					ti->ti_Data = (ULONG) args->wa_Lock;
					ti++;
					ti->ti_Tag  = WBOPENA_ArgName;
					ti->ti_Data = (ULONG) args->wa_Name;
					ti++;
					args++;
				}				
				
				ti->ti_Tag  = TAG_DONE;
			}
			else tlist = (struct TagItem *) -1L;
		}
		else tlist = NULL;
		
		if( tlist != (struct TagItem *) -1L )
		{	
			BPTR	olddir;
		
			if( dirlock ) olddir = CurrentDir( dirlock );
			kprintf( "Calling OpenWorkbenchObjectA()\n" );
			if( OpenWorkbenchObjectA( name, tlist ) )
				ret = 0UL;
			kprintf( "Returned from OpenWorkbenchObjectA()\n" );
			if( dirlock ) CurrentDir( olddir );
			
			kprintf( "Free: %08lx\n", tlist );
			FreeVec( tlist );
		}		
	}
	
	UnLock( dirlock );
	
	kprintf( "Functions returns %ld\n", ret );
	
	return ret;
}

/****************************************************************************/
