#include "Assembler.hpp"
#include "Scanner.hpp"
#include "Instruction.hpp"
#include "Error.hpp"

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
/*
void setBits(unsigned int *bitBuffer, int i, int n)
{
	int j = i / 32;
	int k = i % 32;

	while(n > 0)
	{
		unsigned int x = -1;

		int y = x >> (32 - n);
		x = n < 32 ? y : x;

		x <<= k;
		n += k;
		k = 0;

		bitBuffer[j++] |= x;

		n -= 32;
	}
}
*/
void testSetBits()
{
	SoftWire::Assembler x86("SetBits.asm");

	void (__cdecl *setBits)(unsigned int*, int, int) = (void(__cdecl*)(unsigned int*, int, int))x86.callable();

	if(setBits)
	{
		printf("Execute code (y/n)?\n\n");

		int c;
		do
		{
			c = getch();
		}
		while(c != 'y' && c != 'n');

		if(c == 'y')
		{
			unsigned int bitBuffer[] = {0x00000000, 0x00000000};

			setBits(bitBuffer, 5, 44);

			printf("output: %.8X %.8X\n\n", bitBuffer[1], bitBuffer[0]);
		}
	}
}
/*
void crossProduct(float *V0, float *V1, float *V2)
{
	V2[0] = V0[1] * V1[2] - V0[2] * V1[1];
	V2[1] = V0[2] * V1[0] - V0[0] * V1[2];
	V2[2] = V0[0] * V1[1] - V0[1] * V1[0];
}
*/
void testCrossProduct()
{
	SoftWire::Assembler x86("CrossProduct.asm");

	void (__cdecl *crossProduct)(float*, float*, float*) = (void(__cdecl*)(float*, float*, float*))x86.callable();

	if(crossProduct)
	{
		printf("Execute code (y/n)?\n\n");

		int c;
		do
		{
			c = getch();
		}
		while(c != 'y' && c != 'n');

		if(c == 'y')
		{
			float V0[3] = {1, 0, 0};
			float V1[3] = {0, 1, 0};
			float V2[3];

			crossProduct(V0, V1, V2);

			printf("output: (%.3f, %.3f, %.3f)\n\n", V2[0], V2[1], V2[2]);
		}
	}
}
/*
int alphaBlend(int c1, int c2, int a)
{
	__asm
	{
		movd mm0, a
		punpcklwd mm0, mm0
		punpckldq mm0, mm0
		pcmpeqb mm7, mm7
		psubw mm7, mm0
		
		punpcklbw mm1, c1
		psrlw mm1, 8
		punpcklbw mm2, c2
		psrlw mm2, 8

		pmullw mm1, mm7
		pmullw mm2, mm0
		paddw mm1, mm2

		psrlw mm1, 8
		packuswb mm1, mm1
		movd eax, mm1
	}
} 
*/
void testAlphaBlend()
{
	SoftWire::Assembler x86("AlphaBlend.asm");

	int (__cdecl *alphaBlend)(int, int, int) = (int(__cdecl*)(int, int, int))x86.callable();

	if(alphaBlend)
	{
		printf("Execute code (y/n)?\n\n");

		int c;
		do
		{
			c = getch();
		}
		while(c != 'y' && c != 'n');

		if(c == 'y')
		{
			int x = alphaBlend(0x00FF00FF, 0xFF00FF00, 128);

			printf("output: %.8X\n\n", x);
		}
	}
}
/*
void helloWorld(int (*print)(const char *format, ...), const char *string)
{
	print(string);
}
*/
void testHelloWorld()
{
	SoftWire::Assembler x86("HelloWorld.asm");

	void (__cdecl *helloWorld)(int(*)(const char*, ...), const char*) = (void(__cdecl*)(int(*)(const char*, ...), const char*))x86.callable();

	if(helloWorld)
	{
		printf("Execute code (y/n)?\n\n");

		int c;
		do
		{
			c = getch();
		}
		while(c != 'y' && c != 'n');

		if(c == 'y')
		{
			printf("output: ");
			helloWorld(printf, "Hello world!\n\n");
		}
	}
}

void main()
{
	testSetBits();
	testCrossProduct();
	testAlphaBlend();
	testHelloWorld();

	printf("Press any key to continue");
	getch();

	return;
}

