/* Automatically generated by
	VMPluginCodeGenerator Melchor-tonel.1 uuid: 785c93c8-6a01-0e00-9cf3-c8e307f47eec
   from
	SurfacePlugin VMMaker-tonel.1 uuid: f83de1c8-6a01-0e00-9cf8-b5fb07f47eec
 */
static char __buildInfo[] = "SurfacePlugin VMMaker-tonel.1 uuid: f83de1c8-6a01-0e00-9cf8-b5fb07f47eec " __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 "virtualMachine.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 "memoryAccess.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 l2;
	}
	_surface = &(surfaceArray[((int) _surfaceID )]);
	if (!(dispatchOf(_surface))) {
		_result = 0;
		goto l2;
	}
	surfaceIndexputHandle(((int) _surfaceID ), 0);
	surfaceIndexputDispatch(((int) _surfaceID ), 0);
	numSurfaces -= 1;
	_result = 1;
	l2:
	;
	/* 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 */
