// =======================================================================
// ppc side communication dispatcher
// (c)1998 by Jacek Cybularczyk (NOE/VenusArt)
// slightly modified for specific use by Sigbjørn (CISC) Skjæret
// =======================================================================

#include "library_base.h"

#include <exec/memory.h>
#include <utility/tagitem.h>

#include <powerup/ppclib/object.h>
#include <powerup/ppclib/interface.h>
#include <powerup/ppclib/message.h>
#include <powerup/ppclib/tasks.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <powerup/gcclib/powerup_protos.h>

#include "support.h"

struct ExecBase *SysBase = NULL;

extern APTR __LibFuncTable[];

void MainEntry(void)
{
	APTR ElfObject;
	APTR PPCPort;
	APTR CallPPCMsg;
	ULONG (*function)(ULONG, ...);
	struct CallPPCData *CallPPCData;
	struct StartupData *StartupData = (struct StartupData *)PPCGetTaskAttr(PPCTASKTAG_STARTUP_MSGDATA);

	SysBase = *((struct ExecBase **)4L);
	ElfObject = StartupData->ElfObject;

	if ((PPCPort = (APTR)PPCGetTaskAttr(PPCTASKTAG_MSGPORT)))
	{
		BOOL Terminated = FALSE;

		do {
			PPCWaitPort(PPCPort);

			if ((CallPPCMsg = PPCGetMessage(PPCPort)))
			{
				CallPPCData = (struct CallPPCData *)PPCGetMessageAttr(CallPPCMsg, PPCMSGTAG_DATA);

				switch (CallPPCData->Type)
				{
					case MSGTYPE_CALL:
						function = (ULONG (*)(ULONG, ...))__LibFuncTable[CallPPCData->PPCLVO];
						CallPPCData->Return = function(CallPPCData->Args[0], CallPPCData->Args[1], CallPPCData->Args[2], CallPPCData->Args[3], CallPPCData->Args[4], CallPPCData->Args[5], CallPPCData->Args[6], CallPPCData->Args[7]);
						break;

					case MSGTYPE_INIT:
						CallPPCData->Return = (ULONG)InitSupport();
						break;

					case MSGTYPE_REMOVE:
						RemoveSupport();
						Terminated = TRUE;
						break;

					default:
						break;
				}

				PPCCacheFlushAll();
				PPCReplyMessage(CallPPCMsg);
			}
		} while (!Terminated);
	}
}
