// affine.h
// v0.1 beta (Preliminary scaling function added)
//	Functions and macros to make affine transformations easier
//	Compatable with gccVB
//	Written by Parasyte (parasytic_i[at]yahoo.com)

#ifndef __AFFINE_H
#define __AFFINE_H


#include "types.h"
#include "video.h"

#define fixed_7_9(n)		(s32)(n * (1 << 9))					// Convert from float\int\etc to 7.9 fixed
																// Use (s32) for 13.3 conversion
#define fixed_13_3(n)		(FIXED)(n * (1 << 3))				// Convert from float\int\etc to 13.3 fixed
#define inverse_fixed(n)	(FIXED)((1 << 18) / fixed_7_9(n))	// Convert with inversion.

// Clear a world's param table
void affine_clr_param(u8 world) {
	int i,tmp;
	s16 *param;

	tmp = (world << 4);
	param = (s16*)((WAM[tmp + 9] << 1) + 0x00020000);
	for (i = 0; i < (WAM[tmp + 8] << 3); i++) param[i]=0;
}

// Scale an affine background
// world: Number of the world to apply scaling to.  Must be using affine BGM.
// centerX/centerY: Center point (relative to the world) to scale around.
// imageW/imageH: Original image width and height
// scaleX/scaleY: Scale factor per axis. must be in the range: 0.008 through 512
// '1' is 100% scale, '2' is 200%, '0.01' is 1%, etc
void affine_scale(u8 world, s16 centerX, s16 centerY, u16 imageW, u16 imageH, float scaleX, float scaleY) {
	int i,tmp;
	s16 *param;
	s32 XSrc,YSrc;
	FIXED XScl,YScl;

	tmp = (world << 4);
	param = (s16*)((WAM[tmp + 9] << 1) + 0x00020000);

	XScl = inverse_fixed(scaleX);
	YScl = inverse_fixed(scaleY);

	XSrc = -fixed_7_9((centerX - ((imageW * scaleX) / 2)) / scaleX);	// Keep image centered
	YSrc = -fixed_7_9((centerY - ((imageH * scaleY) / 2)) / scaleY);

	i=0;
	while (i < (int)(WAM[tmp + 8] << 3)) {
		param[i++] = (XSrc >> 6);	// XSrc -- convert from 7.9 to 13.3 fixed
		i++;						// Prlx
		param[i++] = (YSrc >> 6);	// YSrc
		param[i++] = XScl;	 		// XScl
		i += 4;						// Skip remaining entries

		YSrc += YScl;				// Grab value of next scanline
	}
}

// Scale an affine background
// world: Number of the world to apply scaling to, must be using affine BGM
// imageW/imageH: Original image width and height
// scale: Scale factor. Must be in the range: 0.008 through 512
// '1' is 100% scale, '2' is 200%, '0.01' is 1%, etc
affine_fast_scale(u8 world, u16 imageW, u16 imageH, float scale) {
	int i,tmp;
	s16 *param;
	s32 XSrc,YSrc;
	FIXED XScl,YScl;

	tmp = (world << 4);
	param = (s16*)((WAM[tmp + 9] << 1) + 0x00020000);

	XScl = YScl = inverse_fixed(scale);

	i = 0;
	while (i < (int)(WAM[tmp + 8] << 3)) {
		param[i++] = (XSrc >> 6);	// XSrc -- convert from 7.9 to 13.3 fixed
		i++;						// Prlx
		param[i++] = (YSrc >> 6);	// YSrc
		param[i++] = XScl;	 		// XScl
		i+=4;						// Skip remaining entries

		YSrc += YScl;				// Grab value of next scanline
	}
}


#endif
