/* Automatically generated by
	VMPluginCodeGenerator Melchor-tonel.1 uuid: fa0bd7f0-2b00-0e00-b22c-e67100d6ef30
   from
	SurfacePlugin VMMaker-tonel.1 uuid: 9a9a25f1-2b00-0e00-b230-d12e00d6ef30
 */
static char __buildInfo[] = "SurfacePlugin VMMaker-tonel.1 uuid: 9a9a25f1-2b00-0e00-b230-d12e00d6ef30 " __DATE__ ;



#include "config.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
#include "sqConfig.h"			/* Configuration options */
#include "sqVirtualMachine.h"	/*  The virtual machine proxy definition */
#include "sqPlatformSpecific.h"	/* Platform specific definitions */

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */
#ifdef SQUEAK_BUILTIN_PLUGIN
# undef EXPORT
# define EXPORT(returnType) static returnType
#endif

#include "SurfacePlugin.h"
#include "sqMemoryAccess.h"


/*** Function Prototypes ***/
EXPORT(const char*) getModuleName(void);
EXPORT(sqInt) initialiseModule(void);
EXPORT(sqInt) ioFindSurface(int surfaceID, sqSurfaceDispatch *fn, sqIntptr_t *surfaceHandle);
EXPORT(sqInt) ioGetSurfaceFormat(int surfaceID, int *width, int *height, int *depth, int *isMSB);
EXPORT(sqInt) ioLockSurface(int surfaceID, int *pitch, int x, int y, int w, int h);
EXPORT(sqInt) ioRegisterSurface(sqIntptr_t surfaceHandle, sqSurfaceDispatch *fn, int *surfaceIDPtr);
EXPORT(sqInt) ioShowSurface(int surfaceID, int x, int y, int w, int h);
EXPORT(sqInt) ioUnlockSurface(int surfaceID, int x, int y, int w, int h);
EXPORT(sqInt) ioUnregisterSurface(int surfaceID);
EXPORT(sqInt) primitiveCreateManualSurface(void);
EXPORT(sqInt) primitiveDestroyManualSurface(void);
EXPORT(sqInt) primitiveFindSurface(void);
EXPORT(sqInt) primitiveRegisterSurface(void);
EXPORT(sqInt) primitiveSetManualSurfacePointer(void);
EXPORT(sqInt) primitiveUnregisterSurface(void);
EXPORT(sqInt) setInterpreter(struct VirtualMachine *anInterpreter);
EXPORT(sqInt) shutdownModule(void);


/*** Variables ***/

#if !defined(SQUEAK_BUILTIN_PLUGIN)
static sqInt (*booleanValueOf)(sqInt obj);
static sqInt (*byteSizeOf)(sqInt oop);
static sqInt (*classExternalAddress)(void);
static sqInt (*failed)(void);
static sqInt (*falseObject)(void);
static sqInt (*fetchPointerofObject)(sqInt index, sqInt oop);
static void * (*firstIndexableField)(sqInt oop);
static sqInt (*isKindOfClass)(sqInt oop, sqInt aClass);
static sqInt (*isBytes)(sqInt oop);
static sqInt (*methodArgumentCount)(void);
static sqInt (*pop)(sqInt nItems);
static void (*popthenPush)(sqInt nItems, sqInt oop);
static usqIntptr_t (*positiveMachineIntegerValueOf)(sqInt oop);
static sqInt (*primitiveFail)(void);
static sqInt (*signed32BitIntegerFor)(sqInt integerValue);
static sqInt (*stackIntegerValue)(sqInt offset);
static sqInt (*stackObjectValue)(sqInt offset);
static sqInt (*stackValue)(sqInt offset);
static sqInt (*trueObject)(void);
#else /* !defined(SQUEAK_BUILTIN_PLUGIN) */
extern sqInt booleanValueOf(sqInt obj);
extern sqInt byteSizeOf(sqInt oop);
extern sqInt classExternalAddress(void);
extern sqInt failed(void);
extern sqInt falseObject(void);
extern sqInt fetchPointerofObject(sqInt index, sqInt oop);
extern void * firstIndexableField(sqInt oop);
extern sqInt isKindOfClass(sqInt oop, sqInt aClass);
extern sqInt isBytes(sqInt oop);
extern sqInt methodArgumentCount(void);
extern sqInt pop(sqInt nItems);
extern void popthenPush(sqInt nItems, sqInt oop);
extern usqIntptr_t positiveMachineIntegerValueOf(sqInt oop);
extern sqInt primitiveFail(void);
extern sqInt signed32BitIntegerFor(sqInt integerValue);
extern sqInt stackIntegerValue(sqInt offset);
extern sqInt stackObjectValue(sqInt offset);
extern sqInt stackValue(sqInt offset);
extern sqInt trueObject(void);
extern
#endif
struct VirtualMachine* interpreterProxy;
static int maxSurfaces = 0;
static const char *moduleName =
#ifdef SQUEAK_BUILTIN_PLUGIN
	"SurfacePlugin VMMaker-tonel.1 (i)"
#else
	"SurfacePlugin VMMaker-tonel.1 (e)"
#endif
;
static int numSurfaces = 0;
static SqueakSurface *surfaceArray = NULL;


/*** Macros ***/
#define dispatchOfSurfaceIndex(i) surfaceArray[i].dispatch
#define dispatchOf(aSurface) aSurface->dispatch
#define getSurfaceFormatOf(aSurface) aSurface->dispatch->getSurfaceFormat
#define handleOf(aSurface) aSurface->handle
#define lockSurfaceOf(aSurface) aSurface->dispatch->lockSurface
#define showSurfaceOf(aSurface) aSurface->dispatch->showSurface
#define surfaceIndexputDispatch(i,aValue) surfaceArray[i].dispatch = aValue
#define surfaceIndexputHandle(i,aValue) surfaceArray[i].handle = aValue
#define unlockSurfaceOf(aSurface) aSurface->dispatch->unlockSurface

/*	Note: This is hardcoded so it can be run from Squeak. 
	The module name is used for validating a module *after* 
	it is loaded to check if it does really contain the module 
	we're thinking it contains. This is important! */
/* InterpreterPlugin>>#getModuleName */
EXPORT(const char*)
getModuleName(void)
{
	return moduleName;
}
/* SurfacePlugin>>#initialiseModule */
EXPORT(sqInt)
initialiseModule(void)
{
	surfaceArray = null;
	numSurfaces = 0;
	maxSurfaces = 0;
	return 1;
}
/*	Find the surface with the given ID, and, optionally, 
	the given set of surface functions. The registered handle 
	is returned in surfaceHandle. Return true if successful 
	(e.g., the surface has been found), false otherwise. */
/* SurfacePlugin>>#ioFindSurface:_:_: */
EXPORT(sqInt)
ioFindSurface(int surfaceID, sqSurfaceDispatch *fn, sqIntptr_t *surfaceHandle)
{
	SqueakSurface *surface;

	if ((surfaceID < 0) || (surfaceID > maxSurfaces)) {
		return 0;
	}
	surface = &(surfaceArray[surfaceID]);
	if (!(dispatchOf(surface))) {
		return 0;
	}
	if ((fn != 0) && (fn != (dispatchOf(surface)))) {
		return 0;
	}
	*surfaceHandle = surface->handle;
	return 1;
}
/*	Return information describing the given surface. 
	Return true if successful, false otherwise. */
/* SurfacePlugin>>#ioGetSurfaceFormat:_:_:_:_: */
EXPORT(sqInt)
ioGetSurfaceFormat(int surfaceID, int *width, int *height, int *depth, int *isMSB)
{
	fn_getSurfaceFormat fnGetSurfaceFormat;
	SqueakSurface *surface;

	if ((surfaceID < 0) || (surfaceID > maxSurfaces)) {
		primitiveFail();
		return 0;
	}
	surface = &(surfaceArray[surfaceID]);
	if (!(dispatchOf(surface))) {
		primitiveFail();
		return 0;
	}
	if (!((fnGetSurfaceFormat = getSurfaceFormatOf(surface)))) {
		return -1;
	}
	return fnGetSurfaceFormat(handleOf(surface), width, height, depth, isMSB);
}
/*	Lock the bits of the surface.  
	Return a pointer to the actual surface bits, 
	or NULL on failure. */
/* SurfacePlugin>>#ioLockSurface:_:_:_:_:_: */
EXPORT(sqInt)
ioLockSurface(int surfaceID, int *pitch, int x, int y, int w, int h)
{
	fn_lockSurface fnLockSurface;
	SqueakSurface *surface;

	if ((surfaceID < 0) || (surfaceID > maxSurfaces)) {
		primitiveFail();
		return 0;
	}
	surface = &(surfaceArray[surfaceID]);
	if (!(dispatchOf(surface))) {
		primitiveFail();
		return 0;
	}
	if (!((fnLockSurface = lockSurfaceOf(surface)))) {
		primitiveFail();
		return 0;
	}
	return fnLockSurface(handleOf(surface), pitch, x, y, w, h);
}
/*	Register a new surface with the given handle and 
	the set of surface functions. The new ID is returned 
	in surfaceID. Returns true if successful, false  
	otherwise. */
/* SurfacePlugin>>#ioRegisterSurface:_:_: */
EXPORT(sqInt)
ioRegisterSurface(sqIntptr_t surfaceHandle, sqSurfaceDispatch *fn, int *surfaceIDPtr)
{
	sqInt i;
	int index;

	if (fn == 0) {
		return 0;
	}
	if(fn->majorVersion != 1 && fn->minorVersion != 0) return 0;
	index = -1;
	if (numSurfaces == maxSurfaces) {
		maxSurfaces = (maxSurfaces * 2) + 10;
		surfaceArray = realloc(surfaceArray, (sizeof(SqueakSurface)) * maxSurfaces);
		for (i = numSurfaces; i < maxSurfaces; i += 1) {
			surfaceIndexputHandle(i, 0);
			surfaceIndexputDispatch(i, 0);
		};
		index = numSurfaces;
	} else {
		for (i = 0; i < maxSurfaces; i += 1) {
			if ((index == -1) && ((dispatchOfSurfaceIndex(i)) == 0)) {
				index = i;
			}
		};
	}
	if (index > maxSurfaces) {
		return 0;
	}
	surfaceIndexputHandle(index, surfaceHandle);
	surfaceIndexputDispatch(index, fn);
	*surfaceIDPtr = index;
	numSurfaces += 1;
	return 1;
}
/*	Transfer the bits of a surface to the screen. */
/* SurfacePlugin>>#ioShowSurface:_:_:_:_: */
EXPORT(sqInt)
ioShowSurface(int surfaceID, int x, int y, int w, int h)
{
	fn_showSurface fnShowSurface;
	SqueakSurface *surface;

	if ((surfaceID < 0) || (surfaceID > maxSurfaces)) {
		primitiveFail();
		return 0;
	}
	surface = &(surfaceArray[surfaceID]);
	if (!(dispatchOf(surface))) {
		primitiveFail();
		return 0;
	}
	if (!((fnShowSurface = showSurfaceOf(surface)))) {
		return -1;
	}
	return fnShowSurface(handleOf(surface), x, y, w, h);
}
/*	Unlock the bits of the surface.  
	The return value is ignored. */
/* SurfacePlugin>>#ioUnlockSurface:_:_:_:_: */
EXPORT(sqInt)
ioUnlockSurface(int surfaceID, int x, int y, int w, int h)
{
	fn_unlockSurface fnUnlockSurface;
	SqueakSurface *surface;

	if ((surfaceID < 0) || (surfaceID > maxSurfaces)) {
		primitiveFail();
		return 0;
	}
	surface = &(surfaceArray[surfaceID]);
	if (!(dispatchOf(surface))) {
		primitiveFail();
		return 0;
	}
	if (!((fnUnlockSurface = unlockSurfaceOf(surface)))) {
		return -1;
	}
	return fnUnlockSurface(handleOf(surface), x, y, w, h);
}
/*	Unregister the surface with the given ID. 
	Returns true if successful, false otherwise. */
/* SurfacePlugin>>#ioUnregisterSurface: */
EXPORT(sqInt)
ioUnregisterSurface(int surfaceID)
{
	SqueakSurface *surface;

	if ((surfaceID < 0) || (surfaceID > maxSurfaces)) {
		return 0;
	}
	surface = &(surfaceArray[surfaceID]);
	if (!(dispatchOf(surface))) {
		return 0;
	}
	surfaceIndexputHandle(surfaceID, 0);
	surfaceIndexputDispatch(surfaceID, 0);
	numSurfaces -= 1;
	return 1;
}
/*	arguments: name(type, stack offset) 
	width(Integer, 4) 
	height(Integer, 3) 
	rowPitch(Integer, 2) 
	depth(Integer, 1) 
	isMSB(Boolean, 0) */
/* SurfacePlugin>>#primitiveCreateManualSurface */
EXPORT(sqInt)
primitiveCreateManualSurface(void)
{
	sqInt depth;
	sqInt height;
	sqInt isMSB;
	sqInt result;
	sqInt rowPitch;
	sqInt width;

	if (!((methodArgumentCount()) == 5)) {
		return primitiveFail();
	}
	width = stackIntegerValue(4);
	height = stackIntegerValue(3);
	rowPitch = stackIntegerValue(2);
	depth = stackIntegerValue(1);
	isMSB = stackObjectValue(0);
	isMSB = booleanValueOf(isMSB);
	if (failed()) {
		return null;
	}
	{
		;
		;
		;
		;
		;
	}
	result = createManualSurface(width, height, rowPitch, depth, isMSB);
	if (result < 0) {
		return primitiveFail();
	}
	result = signed32BitIntegerFor(result);
	popthenPush(6, result);
	return 0;
}
/*	arguments: name(type, stack offset) 
	surfaceID(Integer, 0) */
/* SurfacePlugin>>#primitiveDestroyManualSurface */
EXPORT(sqInt)
primitiveDestroyManualSurface(void)
{
	sqInt result;
	sqInt surfaceID;

	if (!((methodArgumentCount()) == 1)) {
		return primitiveFail();
	}
	surfaceID = stackIntegerValue(0);
	if (failed()) {
		return null;
	}
	result = destroyManualSurface(surfaceID);
	if (result == 0) {
		return primitiveFail();
	}
	return pop(1);
}
/*	arguments: name(type, stack offset) 
	externalID(Integer, 1) 
	surfaceHandleHolder(ByteArray(4), 0) */
/* SurfacePlugin>>#primitiveFindSurface */
EXPORT(sqInt)
primitiveFindSurface(void)
{
	sqInt externalID;
	int result;
	sqInt surfaceHandleHolder;
	void *surfaceHandlePtr;

	if (!((methodArgumentCount()) == 2)) {
		return primitiveFail();
	}
	externalID = stackIntegerValue(1);
	surfaceHandleHolder = stackObjectValue(0);
	if (failed()) {
		return null;
	}
	if (!(isBytes(surfaceHandleHolder))) {
		return primitiveFail();
	}
	surfaceHandlePtr = firstIndexableField(surfaceHandleHolder);
	result = ioFindSurface(externalID, 0, surfaceHandlePtr);
	popthenPush(3, ((result)
		 ? trueObject()
		 : falseObject()));
	return 0;
}
/*	arguments: name(type, stack offset) 
	surfaceHandle(ExternalAddress, 2) 
	dispatch(ExternalAddress, 1) 
	surfaceIDHolder(ByteArray(4), 2) */
/* SurfacePlugin>>#primitiveRegisterSurface */
EXPORT(sqInt)
primitiveRegisterSurface(void)
{
	sqInt dispatchAddress;
	int result;
	sqInt sqSurfaceDispatchPtr;
	sqInt surfaceHandle;
	void *surfaceHandlePtr;
	sqInt surfaceIDHolder;
	void *surfaceIDPtr;

	if (!((methodArgumentCount()) == 3)) {
		return primitiveFail();
	}
	surfaceHandle = stackObjectValue(2);
	dispatchAddress = stackObjectValue(1);
	surfaceIDHolder = stackObjectValue(0);
	if (failed()) {
		return null;
	}
	if (!(isBytes(surfaceIDHolder))) {
		return primitiveFail();
	}
	if (!((byteSizeOf(surfaceIDHolder)) >= 4)) {
		return primitiveFail();
	}
	if (!(isKindOfClass(dispatchAddress, classExternalAddress()))) {
		return primitiveFail();
	}
	if (!(isKindOfClass(surfaceHandle, classExternalAddress()))) {
		return primitiveFail();
	}
	surfaceIDPtr = firstIndexableField(surfaceIDHolder);
	sqSurfaceDispatchPtr = fetchPointerofObject(0, dispatchAddress);
	surfaceHandlePtr = fetchPointerofObject(0, surfaceHandle);
	result = ioRegisterSurface(surfaceHandlePtr, sqSurfaceDispatchPtr, surfaceIDPtr);
	popthenPush(4, ((result)
		 ? trueObject()
		 : falseObject()));
	return 0;
}
/*	Create a 'manual surface' data-structure. See the ExternalForm class in 
	the FFI package for example usage.arguments: name(type, stack offset) 
	surfaceID(Integer, 1) 
	ptr(uint32, 0) */
/* SurfacePlugin>>#primitiveSetManualSurfacePointer */
EXPORT(sqInt)
primitiveSetManualSurfacePointer(void)
{
	usqIntptr_t ptr;
	sqInt result;
	sqInt surfaceID;

	if (!((methodArgumentCount()) == 2)) {
		return primitiveFail();
	}
	surfaceID = stackIntegerValue(1);
	ptr = positiveMachineIntegerValueOf(stackValue(0));
	if (failed()) {
		return null;
	}
	{
		;
		;
	}
	result = setManualSurfacePointer(surfaceID, (void*)ptr);
	if (result == 0) {
		return primitiveFail();
	}
	return pop(2);
}
/*	arguments: name(type, stack offset) 
	surfaceID(Integer, 0) */
/* SurfacePlugin>>#primitiveUnregisterSurface */
EXPORT(sqInt)
primitiveUnregisterSurface(void)
{
	int result;
	SqueakSurface *surface;
	sqInt surfaceID;

	if (!((methodArgumentCount()) == 1)) {
		return primitiveFail();
	}
	surfaceID = stackIntegerValue(0);
	if (failed()) {
		return null;
	}
	/* begin ioUnregisterSurface: */
	if ((((int) surfaceID ) < 0) || (((int) surfaceID ) > maxSurfaces)) {
		result = 0;
		goto l1;
	}
	surface = &(surfaceArray[((int) surfaceID )]);
	if (!(dispatchOf(surface))) {
		result = 0;
		goto l1;
	}
	surfaceIndexputHandle(((int) surfaceID ), 0);
	surfaceIndexputDispatch(((int) surfaceID ), 0);
	numSurfaces -= 1;
	result = 1;
	l1:
	;
	/* end ioUnregisterSurface: */
	popthenPush(2, ((result)
		 ? trueObject()
		 : falseObject()));
	return 0;
}
/*	Note: This is coded so that it can be run in Squeak. */
/* InterpreterPlugin>>#setInterpreter: */
EXPORT(sqInt)
setInterpreter(struct VirtualMachine *anInterpreter)
{
	sqInt ok;

	interpreterProxy = anInterpreter;
	ok = ((interpreterProxy->majorVersion()) == (VM_PROXY_MAJOR)) && ((interpreterProxy->minorVersion()) >= (VM_PROXY_MINOR));
	if (ok) {
		
#    if !(defined(SQUEAK_BUILTIN_PLUGIN))
		{
			
			{
				{
					booleanValueOf = interpreterProxy->booleanValueOf;
				}
				{
					byteSizeOf = interpreterProxy->byteSizeOf;
				}
				{
					classExternalAddress = interpreterProxy->classExternalAddress;
				}
				{
					failed = interpreterProxy->failed;
				}
				{
					falseObject = interpreterProxy->falseObject;
				}
				{
					fetchPointerofObject = interpreterProxy->fetchPointerofObject;
				}
				{
					firstIndexableField = interpreterProxy->firstIndexableField;
				}
				{
					isKindOfClass = interpreterProxy->isKindOfClass;
				}
				{
					isBytes = interpreterProxy->isBytes;
				}
				{
					methodArgumentCount = interpreterProxy->methodArgumentCount;
				}
				{
					pop = interpreterProxy->pop;
				}
				{
					popthenPush = interpreterProxy->popthenPush;
				}
				{
					positiveMachineIntegerValueOf = interpreterProxy->positiveMachineIntegerValueOf;
				}
				{
					primitiveFail = interpreterProxy->primitiveFail;
				}
				{
					signed32BitIntegerFor = interpreterProxy->signed32BitIntegerFor;
				}
				{
					stackIntegerValue = interpreterProxy->stackIntegerValue;
				}
				{
					stackObjectValue = interpreterProxy->stackObjectValue;
				}
				{
					stackValue = interpreterProxy->stackValue;
				}
				{
					trueObject = interpreterProxy->trueObject;
				}
			}
		}
#    endif /* !(defined(SQUEAK_BUILTIN_PLUGIN)) */
	}
	return ok;
}
/*	This module can only be shut down if no surfaces are registered */
/* SurfacePlugin>>#shutdownModule */
EXPORT(sqInt)
shutdownModule(void)
{
	if (!(numSurfaces == 0)) {
		return 0;
	}
	free(surfaceArray);
	return 1;
}


#ifdef SQUEAK_BUILTIN_PLUGIN

static char _m[] = "SurfacePlugin";
void* SurfacePlugin_exports[][3] = {
	{(void*)_m, "getModuleName", (void*)getModuleName},
	{(void*)_m, "initialiseModule", (void*)initialiseModule},
	{(void*)_m, "ioFindSurface", (void*)ioFindSurface},
	{(void*)_m, "ioGetSurfaceFormat", (void*)ioGetSurfaceFormat},
	{(void*)_m, "ioLockSurface", (void*)ioLockSurface},
	{(void*)_m, "ioRegisterSurface", (void*)ioRegisterSurface},
	{(void*)_m, "ioShowSurface", (void*)ioShowSurface},
	{(void*)_m, "ioUnlockSurface", (void*)ioUnlockSurface},
	{(void*)_m, "ioUnregisterSurface", (void*)ioUnregisterSurface},
	{(void*)_m, "primitiveCreateManualSurface\000\000", (void*)primitiveCreateManualSurface},
	{(void*)_m, "primitiveDestroyManualSurface\000\000", (void*)primitiveDestroyManualSurface},
	{(void*)_m, "primitiveFindSurface\000\002", (void*)primitiveFindSurface},
	{(void*)_m, "primitiveRegisterSurface\000\002", (void*)primitiveRegisterSurface},
	{(void*)_m, "primitiveSetManualSurfacePointer\000\000", (void*)primitiveSetManualSurfacePointer},
	{(void*)_m, "primitiveUnregisterSurface\000\000", (void*)primitiveUnregisterSurface},
	{(void*)_m, "setInterpreter", (void*)setInterpreter},
	{(void*)_m, "shutdownModule\000\377", (void*)shutdownModule},
	{NULL, NULL, NULL}
};

#else /* ifdef SQ_BUILTIN_PLUGIN */

EXPORT(signed char) primitiveCreateManualSurfaceAccessorDepth = 0;
EXPORT(signed char) primitiveDestroyManualSurfaceAccessorDepth = 0;
EXPORT(signed char) primitiveFindSurfaceAccessorDepth = 2;
EXPORT(signed char) primitiveRegisterSurfaceAccessorDepth = 2;
EXPORT(signed char) primitiveSetManualSurfacePointerAccessorDepth = 0;
EXPORT(signed char) primitiveUnregisterSurfaceAccessorDepth = 0;

#endif /* ifdef SQ_BUILTIN_PLUGIN */
