summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/video/vooddefs.ipp
blob: 07487f2bbf8df7b4c665257e8e6fd5461f6f2d2e (plain) (tree)
1
2
3
4
5
6
7
8
9
                               
                                
                                                                            
 
              
 
                                          
 
                                                                            
 

                               


            
                   
 







                                       
                             

 








                                       
                                                         
 
                                                              

                                 


                                                                           
                           
         

                                



         
                                                   
 
                                   

                                                   
                      
         
                                 

                                    
                                 

                                                

                                     
                                     
                               




                    
                                                       
 
                                 
                      
                              



                     



















                                       
                                                                 
 



                                          
                        





                                               
                           


                                                                    
                                    
         
                                               


                          
                                       














                                                                                         
                                                                                   
                                                                                                                




































                                                                                                                        
                                                                  

                                                                    
                                                      



















                                             
                                                                  

                                                                    
                                                      











                                             
                                                     













                                       
                                                                    







                                                                 
                                                                    















                                                                                      
                                                                








                                                                 
                                                                







                                    
                                                                















                                                                                          
                                                                
 
                        

                         












                                                











                                                             



                                                                                        


                                                                                          
                                                                                             
                                               
                                                                                 

                                                                                 

                                                                                         


                                                                                     

                                                                                         
                                                                                             



                                                                                             
                                                                                             



                                                                                             

         















                                                                                             

         






                                                                                         
                                                                                           












                                                                                                                                                                 









                                       


                                                                                 



                                                                                 






































                                                                                                                                                                 

         
                                                                                              
 
                                   
                                                                                                                         
                           
 
                                      

                             
                                      
                                 
                                       
                                      
                                     
                                        
                                      
                                        
                                 
                                      
                                    

                                     


            
                                                  
                                        
         
                      

 


                                                                                 
                                                                                       














                                                                                             


         


                                                                                 
                                                                                       













                                                                                             









                                       

















                                                                                                                                                                 
                                                                                               












































                                                                                                                                                                 

         
                                                                                                                                              
 
         
                                
                                                 
                                       
                                                                
                 
                                                                               








                                                     
                                                
                                    

                                        

                                                          

                                                                
                                                                                      


                                         

                                                          

                                                                 
                                                                                       


                                       

                                                          

                                                                 
                                                                                     

                                          
                                                                           



















                                                             







                                       











                                                                                             

         
                                                                                                
 








                                            






                                       




                                                                                     
                                                                                           


























































                                                                                                                                                                 

         
                                                                                                                                  
 
         



























































                                                                         







                                       





                                                                                         

                                                                                         

















































































































































                                                                                                                                                                 

         
                                                                                                                                                                                                            
 


                                      


                                                       
                                                                                



                                
                                          

                                                  
                                              




                                                                                  
                                                 

                                                       


                                        


                                            


                                                            

                                          





                                                         
                                                



                                                         
                                            
                                                     





                                                              
                                                             
                                                    






                                                              
                                                     





                                                              
                                                      



                                                      
                                                     





                                                                  
                                                                                                     






                                                                  
                                                     






                                                                             
                                     
                                                     




                                                              

                                                

                                          


                                                            

                                           





                                                         
                                                 


                                                    
                                            
                                                      





                                                               
                                                        
                                                     






                                                               
                                                      





                                                               
                                                       






                                                      
                                                      





                                                                   
                                                         
                                                        
                                                                                                                                     






                                                                   
                                                      





                                                                   
                                                      
                                                     




                                                                    



                                                  
                             
                                                    
 
                                                                              






                                          







                                       





                                                                                             
                                                                                           











                                                                                                                                                                 
                                                                                               























                                                                                                                                                                 

                                                                                                         


                                                                                                                                                                 
                                                                                                                   











                                                                                                                                                                 
                                                                                                       













































                                                                                                                                                                 

         

                                                                                                                                                                                     
 
         
                                                           
                                                             
 

                                                     


                                                                                 

                                                               



                                                                       


                                                        
                                              
                         



                                                                 
                                             


                                                                             
                                                     

                                                   


                                                                                 
                                                                           
                                                         










                                                               






                                                                                        

                                                                                         

                                                                                                 
                                                                                    








                                                                                         
                                                                         


                                                                        
                                                                                               



                                                            
                                                                    


















                                                                                 
                                                                             

                                                              

                                                               








                                                                       




                                              






                                          
                                                   
                                         

         








                                                                                                          

                                                                                 




                                                                                       
                                                                                     
                                                                                                                                                                 


                                                                                     
                                                                                           


                                                                                                   


                                                                                                      







































                                                                                                                                                                 
                                                                                           
















                                                                                                                                                                 
                                                                                               



                                                                                             
                                                                                               










                                                                                                                                                                 


                                                                                           








































                                                                                                                                                                 



                                                                                               






                                                                                             



                                                                                                




















                                                                                                                                                                 
                                                                                                       






















































                                                                                                                                                                 
                                                                                                 



































                                                                                                                                                                 
                                                                                                 































































                                                                                                                                                                 









                                       
                                                                                         

                                                                                 

                                                                                    
                                                                                                                                                                 
                                                                                     
                                                                                                                                                                 

                                                                                     
                                                                                                                                                                 





                                                                                         
                                                                                                     
                                                                                             
                                                                                             
                                                                                                 







                                                                                                                                                                 
                                                                                             
                                                                                             
                                                                                                 





                                                                                                                                                                 
                                                                                     


                                                                                         

                                                                                         








                                                                                                                                                                 
                                                                                
                                                                                     

















                                                                                                         
                                                                                     

                                                                                     
                                                                                         
                                                                                     



                                                                                     
                                                                                          



                                                                                          
                                               

                                                                                 


                                                                                     
                                                                                           



                                                                                                                                                                 
                                                                                              
                                                                                         
                                                                                             


























































                                                                                                                                                                 


                                                                                 
 
                                                                                                                                                          

                                         
         
                                    




































































                                                                           
 

                                                                                                                                                                 
                                                                                      











                                                                                                                                                                 

                                                                                         



                                                                                              
                                                                                             








                                                                                                                                                                 
 










































                                                                                                                              
                       

                                                                                                            

                                                                                 
                                                                                       

















                                                                                                                                                                 
                                                                                       





























                                                                                                                                                                 















                                                                                                                                                                 















                                                                                                                                                                 
                                                                                               






                                                                                                                                                                 
                                                                                               



                                                                                                                                                                 
                                                                                     
                                                                                 










































                                                                                                                                                                 
                                                                                                                                                                 

                                                                                     
                                                                                                                                                                 







                                                                                                                                                                 









                                                                                                                                                                 







                                                                                                                                                                 
































                                                                                                                                                                 







                                                                                                                                                                 



                                                                                     




















                                                                                                                                                                 



                                                                                     







                                                                                                                                                                 
                                                                                 

         
                                                                                                                                         
                                                                                                                                                                               
 

                          

                                            




                                                 
                                              


                                             
                                               


                                            
                                                       

                              

                                                            



                               


                                                                
                                                              




                                                
                                                        


                                               
                                                         


                                              
                                                               

                              

                                                              



                               


                                                                    
                                                                    





                                                                                  
                                              
                                                                                
                                                       


            

                                                                                    
                                                                                
                                                       






                                                    
                                                        


                                              
                                                               





                                                             
                                                        






                                                                                           
                                                        



                              

                                              
                                


                                         


                                               

                                         
                                                   



                                                                                      
                                  

                                                       


                                             

                                                        

                                             
                                                       
 
                                         






                                               
                                            


                                         
                                                  


                                         
                                                                   


                                         
                                                                   


                                               
                                                                     


                                                             
                                                    







                                                
                                                  



                                         
                                                            


                                         
                                                            


                                               
                                                              




                                                  
                                                               


                                                   
                                                         






                                                          




                                                   
                                       


                                             
                                             


                                            
                                                              


                              

                                                 

                                     
                                               
                                               
 




                                         

                                                               


                                                  
                                                        

                                                 
                                                              
 
                                  



                    






                                       
 

                                                                                                                                                                 
                                                                                                                              

                                                                                     

                                                                                      
                                                                                     

                                                                                       
                                                                                      
                                                                                       


                                                                                                  




                                                                                       



                                                                                                                                                                 
                                                                                  

                                                                                                                                                                 
                                                                                     



                                                                                                                                                                 
                                                                                           

                                                                                                                                                                 

                                                                                              






                                                                                                                                                                 













                                                                                              
                                                                                          


                                                                                             
                                                                                              

                                                                                             


                                                                                                                                                                 

                                                                                                                               



                                                                                                                                                                 



                                                                                             





                                                                                     




                                                                                         


                                                                                     




                                                                                         








                                                                                                                                                                 
                                                                                             
                                             


                                                                                                             


                                                                                                                                                                 
                                                                                           
                                      
                                                        
                                                                                                                 
                                                                                                                                 
                                                                                             



                                                                                         
                                                                                          
                                                                                     
                                                                                              
                                                                                             
                                               
                                                                                                   
                                                                                                                           
                                                                                                                                                  
                                                                                                    


                                                                                             
                                                                                                         



                                                                                                                                                                 






                                                                                                          
                                                                                                                                                                                  


                                                                                                                          
                                                                                                                              
                                                                                                                                                                                                                                  





                                                                                                                                                                 






                                                                                                                                                                 
                                                                                             


                                                                                         
                                                                                             


                                                                                         

 



                                                                                                                                 
                                                                    
                                                                                                                                 
                                                                                                     
 
                                                                                                                             
                                              


                                       
                                                                           
                                 
                              
                  
                                                   
                                    
                   

 
                                                                                                                                                                                                      
 
                         
                           


                                                           
                                                
         
                             
                                              
                            


            
                                                       

         
                     
                                                               


                          

                           
                       
                                               
                                         
                                   


                                                                                  
                                     


                                    
                                           

                                                            

                                     

                                                                

                                                                         


                                   
                                

                                                                        

                                     












                                                 
                                                                            
                                                     


                    
                                                                                 
                                                                                           
                                                             
                            
                                                                                                             





                                       


                                                        


                                                                                    

                                         





                                                                                    

                                          












































                                                 



                                                                              






                                                  



                                                                                   
















                                                                                                          
 
                                                                                             



                      
                                                                                                                                                                    
 

                                            


                                           


                                         


                                            

                                         
                                                   


                                                                              
                                  


                                                    


                                             

                                                     

                                             
                                                       
 
                                         






                                            
                                            


                                         
                                                  


                                         
                                                                   


                                         
                                                                   


                                                     
                                              
                                                    

                            
                                            


                                                                                 
                                                          



                                              
                                                         







                                             
                                                  


                                         
                                                            


                                         
                                                            


                                         
                                                            


                                                     
                                              
                                                          

                            
                                            


                                                                                 
                                                          



                                              
                                                         




                                               
                                                               


                                                
                                                         











                                                
                                       


                                             
                                             


                                            
                                                              




                                              

                                     
                                               





                                                                


                                                               

                                              
                                                              
                                               

                                                        
 
 
                                 
	// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    vooddefs.h

    3dfx Voodoo Graphics SST-1/2 emulator.

***************************************************************************/

#ifndef MAME_VIDEO_VOODDEFS_IPP
#define MAME_VIDEO_VOODDEFS_IPP

#pragma once

#include "voodoo.h"



/*************************************
 *
 *  Core types
 *
 *************************************/

typedef voodoo_reg rgb_union;





/*************************************
 *
 *  Inline FIFO management
 *
 *************************************/

inline void voodoo_device::fifo_state::add(uint32_t data)
{
	/* compute the value of 'in' after we add this item */
	int32_t next_in = in + 1;
	if (next_in >= size)
		next_in = 0;

	/* as long as it's not equal to the output pointer, we can do it */
	if (next_in != out)
	{
		base[in] = data;
		in = next_in;
	}
}


inline uint32_t voodoo_device::fifo_state::remove()
{
	uint32_t data = 0xffffffff;

	/* as long as we have data, we can do it */
	if (out != in)
	{
		int32_t next_out;

		/* fetch the data */
		data = base[out];

		/* advance the output pointer */
		next_out = out + 1;
		if (next_out >= size)
			next_out = 0;
		out = next_out;
	}
	return data;
}


inline int32_t voodoo_device::fifo_state::items() const
{
	int32_t items = in - out;
	if (items < 0)
		items += size;
	return items;
}



/*************************************
 *
 *  Computes a fast 16.16 reciprocal
 *  of a 16.32 value; used for
 *  computing 1/w in the rasterizer.
 *
 *  Since it is trivial to also
 *  compute log2(1/w) = -log2(w) at
 *  the same time, we do that as well
 *  to 16.8 precision for LOD
 *  calculations.
 *
 *  On a Pentium M, this routine is
 *  20% faster than a 64-bit integer
 *  divide and also produces the log
 *  for free.
 *
 *************************************/

static inline int32_t fast_reciplog(int64_t value, int32_t *log2)
{
	extern uint32_t voodoo_reciplog[];
	uint32_t temp, recip, rlog;
	uint32_t interp;
	uint32_t *table;
	int neg = false;
	int lz, exp = 0;

	/* always work with unsigned numbers */
	if (value < 0)
	{
		value = -value;
		neg = true;
	}

	/* if we've spilled out of 32 bits, push it down under 32 */
	if (value & 0xffff00000000U)
	{
		temp = (uint32_t)(value >> 16);
		exp -= 16;
	}
	else
		temp = (uint32_t)value;

	/* if the resulting value is 0, the reciprocal is infinite */
	if (UNEXPECTED(temp == 0))
	{
		*log2 = 1000 << LOG_OUTPUT_PREC;
		return neg ? 0x80000000 : 0x7fffffff;
	}

	/* determine how many leading zeros in the value and shift it up high */
	lz = count_leading_zeros(temp);
	temp <<= lz;
	exp += lz;

	/* compute a pointer to the table entries we want */
	/* math is a bit funny here because we shift one less than we need to in order */
	/* to account for the fact that there are two uint32_t's per table entry */
	table = &voodoo_reciplog[(temp >> (31 - RECIPLOG_LOOKUP_BITS - 1)) & ((2 << RECIPLOG_LOOKUP_BITS) - 2)];

	/* compute the interpolation value */
	interp = (temp >> (31 - RECIPLOG_LOOKUP_BITS - 8)) & 0xff;

	/* do a linear interpolatation between the two nearest table values */
	/* for both the log and the reciprocal */
	rlog = (table[1] * (0x100 - interp) + table[3] * interp) >> 8;
	recip = (table[0] * (0x100 - interp) + table[2] * interp) >> 8;

	/* the log result is the fractional part of the log; round it to the output precision */
	rlog = (rlog + (1 << (RECIPLOG_LOOKUP_PREC - LOG_OUTPUT_PREC - 1))) >> (RECIPLOG_LOOKUP_PREC - LOG_OUTPUT_PREC);

	/* the exponent is the non-fractional part of the log; normally, we would subtract it from rlog */
	/* but since we want the log(1/value) = -log(value), we subtract rlog from the exponent */
	*log2 = ((exp - (31 - RECIPLOG_INPUT_PREC)) << LOG_OUTPUT_PREC) - rlog;

	/* adjust the exponent to account for all the reciprocal-related parameters to arrive at a final shift amount */
	exp += (RECIP_OUTPUT_PREC - RECIPLOG_LOOKUP_PREC) - (31 - RECIPLOG_INPUT_PREC);

	/* shift by the exponent */
	if (exp < 0)
		recip >>= -exp;
	else
		recip <<= exp;

	/* on the way out, apply the original sign to the reciprocal */
	return neg ? -recip : recip;
}



/*************************************
 *
 *  Float-to-int conversions
 *
 *************************************/

static inline int32_t float_to_int32(uint32_t data, int fixedbits)
{
	int exponent = ((data >> 23) & 0xff) - 127 - 23 + fixedbits;
	int32_t result = (data & 0x7fffff) | 0x800000;
	if (exponent < 0)
	{
		if (exponent > -32)
			result >>= -exponent;
		else
			result = 0;
	}
	else
	{
		if (exponent < 32)
			result <<= exponent;
		else
			result = 0x7fffffff;
	}
	if (data & 0x80000000)
		result = -result;
	return result;
}


static inline int64_t float_to_int64(uint32_t data, int fixedbits)
{
	int exponent = ((data >> 23) & 0xff) - 127 - 23 + fixedbits;
	int64_t result = (data & 0x7fffff) | 0x800000;
	if (exponent < 0)
	{
		if (exponent > -64)
			result >>= -exponent;
		else
			result = 0;
	}
	else
	{
		if (exponent < 64)
			result <<= exponent;
		else
			result = 0x7fffffffffffffffU;
	}
	if (data & 0x80000000)
		result = -result;
	return result;
}



/*************************************
 *
 *  Rasterizer inlines
 *
 *************************************/

static inline uint32_t normalize_color_path(uint32_t eff_color_path)
{
	/* ignore the subpixel adjust and texture enable flags */
	eff_color_path &= ~((1 << 26) | (1 << 27));

	return eff_color_path;
}


static inline uint32_t normalize_alpha_mode(uint32_t eff_alpha_mode)
{
	/* always ignore alpha ref value */
	eff_alpha_mode &= ~(0xff << 24);

	/* if not doing alpha testing, ignore the alpha function and ref value */
	if (!ALPHAMODE_ALPHATEST(eff_alpha_mode))
		eff_alpha_mode &= ~(7 << 1);

	/* if not doing alpha blending, ignore the source and dest blending factors */
	if (!ALPHAMODE_ALPHABLEND(eff_alpha_mode))
		eff_alpha_mode &= ~((15 << 8) | (15 << 12) | (15 << 16) | (15 << 20));

	return eff_alpha_mode;
}


static inline uint32_t normalize_fog_mode(uint32_t eff_fog_mode)
{
	/* if not doing fogging, ignore all the other fog bits */
	if (!FOGMODE_ENABLE_FOG(eff_fog_mode))
		eff_fog_mode = 0;

	return eff_fog_mode;
}


static inline uint32_t normalize_fbz_mode(uint32_t eff_fbz_mode)
{
	/* ignore the draw buffer */
	eff_fbz_mode &= ~(3 << 14);

	return eff_fbz_mode;
}


static inline uint32_t normalize_tex_mode(uint32_t eff_tex_mode)
{
	/* ignore the NCC table and seq_8_downld flags */
	eff_tex_mode &= ~((1 << 5) | (1 << 31));

	/* classify texture formats into 3 format categories */
	if (TEXMODE_FORMAT(eff_tex_mode) < 8)
		eff_tex_mode = (eff_tex_mode & ~(0xf << 8)) | (0 << 8);
	else if (TEXMODE_FORMAT(eff_tex_mode) >= 10 && TEXMODE_FORMAT(eff_tex_mode) <= 12)
		eff_tex_mode = (eff_tex_mode & ~(0xf << 8)) | (10 << 8);
	else
		eff_tex_mode = (eff_tex_mode & ~(0xf << 8)) | (8 << 8);

	return eff_tex_mode;
}


inline uint32_t voodoo_device::raster_info::compute_hash() const
{
	uint32_t result;

	/* make a hash */
	result = eff_color_path;
	result = (result << 1) | (result >> 31);
	result ^= eff_fbz_mode;
	result = (result << 1) | (result >> 31);
	result ^= eff_alpha_mode;
	result = (result << 1) | (result >> 31);
	result ^= eff_fog_mode;
	result = (result << 1) | (result >> 31);
	result ^= eff_tex_mode_0;
	result = (result << 1) | (result >> 31);
	result ^= eff_tex_mode_1;

	return result % RASTER_HASH_SIZE;
}



/*************************************
 *
 *  Dithering macros
 *
 *************************************/

/* note that these equations and the dither matrixes have
   been confirmed to be exact matches to the real hardware */
#define DITHER_RB(val,dith) ((((val) << 1) - ((val) >> 4) + ((val) >> 7) + (dith)) >> 1)
#define DITHER_G(val,dith)  ((((val) << 2) - ((val) >> 4) + ((val) >> 6) + (dith)) >> 2)

#define DECLARE_DITHER_POINTERS                                                 \
	const uint8_t *dither_lookup = nullptr;                                          \
	const uint8_t *dither4 = nullptr;                                                \
	const uint8_t *dither = nullptr
#define DECLARE_DITHER_POINTERS_NO_DITHER_VAR                                               \
	const uint8_t *dither_lookup = nullptr;
#define COMPUTE_DITHER_POINTERS(FBZMODE, YY, FOGMODE)                           \
do                                                                              \
{                                                                               \
	if (FBZMODE_ENABLE_DITHERING(FBZMODE) || FOGMODE_FOG_DITHER(FOGMODE))        \
		dither4 = &dither_matrix_4x4[((YY) & 3) * 4];                           \
	/* compute the dithering pointers */                                        \
	if (FBZMODE_ENABLE_DITHERING(FBZMODE))                                      \
	{                                                                           \
		if (FBZMODE_DITHER_TYPE(FBZMODE) == 0)                                  \
		{                                                                       \
			dither = &dither_subtract_4x4[((YY) & 3) * 4];                      \
			dither_lookup = &dither4_lookup[(YY & 3) << 11];                    \
		}                                                                       \
		else                                                                    \
		{                                                                       \
			dither = &dither_subtract_2x2[((YY) & 3) * 4];                      \
			dither_lookup = &dither2_lookup[(YY & 3) << 11];                    \
		}                                                                       \
	}                                                                           \
}                                                                               \
while (0)

#define COMPUTE_DITHER_POINTERS_NO_DITHER_VAR(FBZMODE, YY)                                  \
do                                                                              \
{                                                                               \
	/* compute the dithering pointers */                                        \
	if (FBZMODE_ENABLE_DITHERING(FBZMODE))                                      \
	{                                                                           \
		if (FBZMODE_DITHER_TYPE(FBZMODE) == 0)                                  \
		{                                                                       \
			dither_lookup = &dither4_lookup[(YY & 3) << 11];                    \
		}                                                                       \
		else                                                                    \
		{                                                                       \
			dither_lookup = &dither2_lookup[(YY & 3) << 11];                    \
		}                                                                       \
	}                                                                           \
}                                                                               \
while (0)

#define APPLY_DITHER(FBZMODE, XX, DITHER_LOOKUP, RR, GG, BB)                    \
do                                                                              \
{                                                                               \
	/* apply dithering */                                                       \
	if (FBZMODE_ENABLE_DITHERING(FBZMODE))                                      \
	{                                                                           \
		/* look up the dither value from the appropriate matrix */              \
		const uint8_t *dith = &DITHER_LOOKUP[((XX) & 3) << 1];                    \
																				\
		/* apply dithering to R,G,B */                                          \
		(RR) = dith[((RR) << 3) + 0];                                           \
		(GG) = dith[((GG) << 3) + 1];                                           \
		(BB) = dith[((BB) << 3) + 0];                                           \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		(RR) >>= 3;                                                             \
		(GG) >>= 2;                                                             \
		(BB) >>= 3;                                                             \
	}                                                                           \
}                                                                               \
while (0)



/*************************************
 *
 *  Clamping macros
 *
 *************************************/

#define CLAMPED_ARGB(ITERR, ITERG, ITERB, ITERA, FBZCP, RESULT)                 \
do                                                                              \
{                                                                               \
	r = (int32_t)(ITERR) >> 12;                                             \
	g = (int32_t)(ITERG) >> 12;                                             \
	b = (int32_t)(ITERB) >> 12;                                             \
	a = (int32_t)(ITERA) >> 12;                                             \
																				\
	if (FBZCP_RGBZW_CLAMP(FBZCP) == 0)                                          \
	{                                                                           \
		r &= 0xfff;                                                             \
		RESULT.rgb.r = r;                                                       \
		if (r == 0xfff)                                                         \
			RESULT.rgb.r = 0;                                                   \
		else if (r == 0x100)                                                    \
			RESULT.rgb.r = 0xff;                                                \
																				\
		g &= 0xfff;                                                             \
		RESULT.rgb.g = g;                                                       \
		if (g == 0xfff)                                                         \
			RESULT.rgb.g = 0;                                                   \
		else if (g == 0x100)                                                    \
			RESULT.rgb.g = 0xff;                                                \
																				\
		b &= 0xfff;                                                             \
		RESULT.rgb.b = b;                                                       \
		if (b == 0xfff)                                                         \
			RESULT.rgb.b = 0;                                                   \
		else if (b == 0x100)                                                    \
			RESULT.rgb.b = 0xff;                                                \
																				\
		a &= 0xfff;                                                             \
		RESULT.rgb.a = a;                                                       \
		if (a == 0xfff)                                                         \
			RESULT.rgb.a = 0;                                                   \
		else if (a == 0x100)                                                    \
			RESULT.rgb.a = 0xff;                                                \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		RESULT.rgb.r = (r < 0) ? 0 : (r > 0xff) ? 0xff : r;                     \
		RESULT.rgb.g = (g < 0) ? 0 : (g > 0xff) ? 0xff : g;                     \
		RESULT.rgb.b = (b < 0) ? 0 : (b > 0xff) ? 0xff : b;                     \
		RESULT.rgb.a = (a < 0) ? 0 : (a > 0xff) ? 0xff : a;                     \
	}                                                                           \
}                                                                               \
while (0)

static inline rgbaint_t ATTR_FORCE_INLINE clampARGB(const rgbaint_t &iterargb, uint32_t FBZCP)
{
	rgbaint_t result(iterargb);
	//rgbaint_t colorint((int32_t) (itera>>12), (int32_t) (iterr>>12), (int32_t) (iterg>>12), (int32_t) (iterb>>12));
	result.shr_imm(12);

	if (!FBZCP_RGBZW_CLAMP(FBZCP))
	{
		//r &= 0xfff;
		result.and_imm(0xfff);
		//if (r == 0xfff)
		rgbaint_t temp(result);
		temp.cmpeq_imm(0xfff);
		//  result.rgb.r = 0;
		result.andnot_reg(temp);
		//else if (r == 0x100)
		//  result.rgb.r = 0xff;
		temp.set(result);
		temp.cmpeq_imm(0x100);
		result.or_reg(temp);
		// else wrap
		result.and_imm(0xff);
	}
	else
	{
		//return colorint.to_rgba_clamp();
		result.clamp_to_uint8();
	}
	return result;
}

#define CLAMPED_Z(ITERZ, FBZCP, RESULT)                                         \
do                                                                              \
{                                                                               \
	(RESULT) = (int32_t)(ITERZ) >> 12;                                            \
	if (FBZCP_RGBZW_CLAMP(FBZCP) == 0)                                          \
	{                                                                           \
		(RESULT) &= 0xfffff;                                                    \
		if ((RESULT) == 0xfffff)                                                \
			(RESULT) = 0;                                                       \
		else if ((RESULT) == 0x10000)                                           \
			(RESULT) = 0xffff;                                                  \
		else                                                                    \
			(RESULT) &= 0xffff;                                                 \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		CLAMP((RESULT), 0, 0xffff);                                             \
	}                                                                           \
}                                                                               \
while (0)


#define CLAMPED_W(ITERW, FBZCP, RESULT)                                         \
do                                                                              \
{                                                                               \
	(RESULT) = (int16_t)((ITERW) >> 32);                                          \
	if (FBZCP_RGBZW_CLAMP(FBZCP) == 0)                                          \
	{                                                                           \
		(RESULT) &= 0xffff;                                                     \
		if ((RESULT) == 0xffff)                                                 \
			(RESULT) = 0;                                                       \
		else if ((RESULT) == 0x100)                                             \
			(RESULT) = 0xff;                                                    \
		(RESULT) &= 0xff;                                                       \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		CLAMP((RESULT), 0, 0xff);                                               \
	}                                                                           \
}                                                                               \
while (0)



/*************************************
 *
 *  Chroma keying macro
 *
 *************************************/

#define APPLY_CHROMAKEY(VV, STATS, FBZMODE, COLOR)                              \
do                                                                              \
{                                                                               \
	if (FBZMODE_ENABLE_CHROMAKEY(FBZMODE))                                      \
	{                                                                           \
		/* non-range version */                                                 \
		if (!CHROMARANGE_ENABLE((VV)->reg[chromaRange].u))                      \
		{                                                                       \
			if (((COLOR.u ^ (VV)->reg[chromaKey].u) & 0xffffff) == 0)           \
			{                                                                   \
				(STATS)->chroma_fail++;                                         \
				goto skipdrawdepth;                                             \
			}                                                                   \
		}                                                                       \
																				\
		/* tricky range version */                                              \
		else                                                                    \
		{                                                                       \
			int32_t low, high, test;                                              \
			int results = 0;                                                    \
																				\
			/* check blue */                                                    \
			low = (VV)->reg[chromaKey].rgb.b;                                   \
			high = (VV)->reg[chromaRange].rgb.b;                                \
			test = COLOR.rgb.b;                                                 \
			results = (test >= low && test <= high);                            \
			results ^= CHROMARANGE_BLUE_EXCLUSIVE((VV)->reg[chromaRange].u);    \
			results <<= 1;                                                      \
																				\
			/* check green */                                                   \
			low = (VV)->reg[chromaKey].rgb.g;                                   \
			high = (VV)->reg[chromaRange].rgb.g;                                \
			test = COLOR.rgb.g;                                                 \
			results |= (test >= low && test <= high);                           \
			results ^= CHROMARANGE_GREEN_EXCLUSIVE((VV)->reg[chromaRange].u);   \
			results <<= 1;                                                      \
																				\
			/* check red */                                                     \
			low = (VV)->reg[chromaKey].rgb.r;                                   \
			high = (VV)->reg[chromaRange].rgb.r;                                \
			test = COLOR.rgb.r;                                                 \
			results |= (test >= low && test <= high);                           \
			results ^= CHROMARANGE_RED_EXCLUSIVE((VV)->reg[chromaRange].u);     \
																				\
			/* final result */                                                  \
			if (CHROMARANGE_UNION_MODE((VV)->reg[chromaRange].u))               \
			{                                                                   \
				if (results != 0)                                               \
				{                                                               \
					(STATS)->chroma_fail++;                                     \
					goto skipdrawdepth;                                         \
				}                                                               \
			}                                                                   \
			else                                                                \
			{                                                                   \
				if (results == 7)                                               \
				{                                                               \
					(STATS)->chroma_fail++;                                     \
					goto skipdrawdepth;                                         \
				}                                                               \
			}                                                                   \
		}                                                                       \
	}                                                                           \
}                                                                               \
while (0)

inline bool ATTR_FORCE_INLINE voodoo_device::chromaKeyTest(voodoo_device *vd, stats_block *stats, uint32_t fbzModeReg, rgbaint_t rgbaIntColor)
{
	{
		rgb_union color;
		color.u = rgbaIntColor.to_rgba();
		/* non-range version */
		if (!CHROMARANGE_ENABLE(vd->reg[chromaRange].u))
		{
			if (((color.u ^ vd->reg[chromaKey].u) & 0xffffff) == 0)
			{
				stats->chroma_fail++;
				return false;
			}
		}

		/* tricky range version */
		else
		{
			int32_t low, high, test;
			int results;

			/* check blue */
			low = vd->reg[chromaKey].rgb.b;
			high = vd->reg[chromaRange].rgb.b;
			test = color.rgb.b;
			results = (test >= low && test <= high);
			results ^= CHROMARANGE_BLUE_EXCLUSIVE(vd->reg[chromaRange].u);
			results <<= 1;

			/* check green */
			low = vd->reg[chromaKey].rgb.g;
			high = vd->reg[chromaRange].rgb.g;
			test = color.rgb.g;
			results |= (test >= low && test <= high);
			results ^= CHROMARANGE_GREEN_EXCLUSIVE(vd->reg[chromaRange].u);
			results <<= 1;

			/* check red */
			low = vd->reg[chromaKey].rgb.r;
			high = vd->reg[chromaRange].rgb.r;
			test = color.rgb.r;
			results |= (test >= low && test <= high);
			results ^= CHROMARANGE_RED_EXCLUSIVE(vd->reg[chromaRange].u);

			/* final result */
			if (CHROMARANGE_UNION_MODE(vd->reg[chromaRange].u))
			{
				if (results != 0)
				{
					stats->chroma_fail++;
					return false;
				}
			}
			else
			{
				if (results == 7)
				{
					stats->chroma_fail++;
					return false;
				}
			}
		}
	}
	return true;
}



/*************************************
 *
 *  Alpha masking macro
 *
 *************************************/

#define APPLY_ALPHAMASK(VV, STATS, FBZMODE, AA)                                 \
do                                                                              \
{                                                                               \
	if (FBZMODE_ENABLE_ALPHA_MASK(FBZMODE))                                     \
	{                                                                           \
		if (((AA) & 1) == 0)                                                    \
		{                                                                       \
			(STATS)->afunc_fail++;                                              \
			goto skipdrawdepth;                                                 \
		}                                                                       \
	}                                                                           \
}                                                                               \
while (0)

inline bool voodoo_device::alphaMaskTest(stats_block *stats, uint32_t fbzModeReg, uint8_t alpha)
{
	{
		if ((alpha & 1) == 0)
		{
			stats->afunc_fail++;
			return false;
		}
	}
	return true;
}

/*************************************
 *
 *  Alpha testing macro
 *
 *************************************/

#define APPLY_ALPHATEST(VV, STATS, ALPHAMODE, AA)                               \
do                                                                              \
{                                                                               \
	if (ALPHAMODE_ALPHATEST(ALPHAMODE))                                         \
	{                                                                           \
		uint8_t alpharef = (VV)->reg[alphaMode].rgb.a;                            \
		switch (ALPHAMODE_ALPHAFUNCTION(ALPHAMODE))                             \
		{                                                                       \
			case 0:     /* alphaOP = never */                                   \
				(STATS)->afunc_fail++;                                          \
				goto skipdrawdepth;                                             \
																				\
			case 1:     /* alphaOP = less than */                               \
				if ((AA) >= alpharef)                                           \
				{                                                               \
					(STATS)->afunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 2:     /* alphaOP = equal */                                   \
				if ((AA) != alpharef)                                           \
				{                                                               \
					(STATS)->afunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 3:     /* alphaOP = less than or equal */                      \
				if ((AA) > alpharef)                                            \
				{                                                               \
					(STATS)->afunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 4:     /* alphaOP = greater than */                            \
				if ((AA) <= alpharef)                                           \
				{                                                               \
					(STATS)->afunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 5:     /* alphaOP = not equal */                               \
				if ((AA) == alpharef)                                           \
				{                                                               \
					(STATS)->afunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 6:     /* alphaOP = greater than or equal */                   \
				if ((AA) < alpharef)                                            \
				{                                                               \
					(STATS)->afunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 7:     /* alphaOP = always */                                  \
				break;                                                          \
		}                                                                       \
	}                                                                           \
}                                                                               \
while (0)

inline bool ATTR_FORCE_INLINE voodoo_device::alphaTest(uint8_t alpharef, stats_block *stats, uint32_t alphaModeReg, uint8_t alpha)
{
	{
		switch (ALPHAMODE_ALPHAFUNCTION(alphaModeReg))
		{
			case 0:     /* alphaOP = never */
				stats->afunc_fail++;
				return false;

			case 1:     /* alphaOP = less than */
				if (alpha >= alpharef)
				{
					stats->afunc_fail++;
					return false;
				}
				break;

			case 2:     /* alphaOP = equal */
				if (alpha != alpharef)
				{
					stats->afunc_fail++;
					return false;
				}
				break;

			case 3:     /* alphaOP = less than or equal */
				if (alpha > alpharef)
				{
					stats->afunc_fail++;
					return false;
				}
				break;

			case 4:     /* alphaOP = greater than */
				if (alpha <= alpharef)
				{
					stats->afunc_fail++;
					return false;
				}
				break;

			case 5:     /* alphaOP = not equal */
				if (alpha == alpharef)
				{
					stats->afunc_fail++;
					return false;
				}
				break;

			case 6:     /* alphaOP = greater than or equal */
				if (alpha < alpharef)
				{
					stats->afunc_fail++;
					return false;
				}
				break;

			case 7:     /* alphaOP = always */
				break;
		}
	}
	return true;
}


/*************************************
 *
 *  Alpha blending macro
 *
 *************************************/

#define APPLY_ALPHA_BLEND(FBZMODE, ALPHAMODE, XX, DITHER, RR, GG, BB, AA)       \
do                                                                              \
{                                                                               \
	if (ALPHAMODE_ALPHABLEND(ALPHAMODE))                                        \
	{                                                                           \
		int dpix = dest[XX];                                                    \
		int dr, dg, db;                                                         \
		EXTRACT_565_TO_888(dpix, dr, dg, db);                                   \
		int da = FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) ? depth[XX] : 0xff;       \
		int sr = (RR);                                                          \
		int sg = (GG);                                                          \
		int sb = (BB);                                                          \
		int sa = (AA);                                                          \
		int ta;                                                                 \
																				\
		/* apply dither subtraction */                                          \
		if (FBZMODE_ALPHA_DITHER_SUBTRACT(FBZMODE))                             \
		{                                                                       \
			/* look up the dither value from the appropriate matrix */          \
			int dith = DITHER[(XX) & 3];                                        \
																				\
			/* subtract the dither value */                                     \
			dr = ((dr << 1) + 15 - dith) >> 1;                                  \
			dg = ((dg << 2) + 15 - dith) >> 2;                                  \
			db = ((db << 1) + 15 - dith) >> 1;                                  \
		}                                                                       \
																				\
		/* compute source portion */                                            \
		switch (ALPHAMODE_SRCRGBBLEND(ALPHAMODE))                               \
		{                                                                       \
			default:    /* reserved */                                          \
			case 0:     /* AZERO */                                             \
				(RR) = (GG) = (BB) = 0;                                         \
				break;                                                          \
																				\
			case 1:     /* ASRC_ALPHA */                                        \
				(RR) = (sr * (sa + 1)) >> 8;                                    \
				(GG) = (sg * (sa + 1)) >> 8;                                    \
				(BB) = (sb * (sa + 1)) >> 8;                                    \
				break;                                                          \
																				\
			case 2:     /* A_COLOR */                                           \
				(RR) = (sr * (dr + 1)) >> 8;                                    \
				(GG) = (sg * (dg + 1)) >> 8;                                    \
				(BB) = (sb * (db + 1)) >> 8;                                    \
				break;                                                          \
																				\
			case 3:     /* ADST_ALPHA */                                        \
				(RR) = (sr * (da + 1)) >> 8;                                    \
				(GG) = (sg * (da + 1)) >> 8;                                    \
				(BB) = (sb * (da + 1)) >> 8;                                    \
				break;                                                          \
																				\
			case 4:     /* AONE */                                              \
				break;                                                          \
																				\
			case 5:     /* AOMSRC_ALPHA */                                      \
				(RR) = (sr * (0x100 - sa)) >> 8;                                \
				(GG) = (sg * (0x100 - sa)) >> 8;                                \
				(BB) = (sb * (0x100 - sa)) >> 8;                                \
				break;                                                          \
																				\
			case 6:     /* AOM_COLOR */                                         \
				(RR) = (sr * (0x100 - dr)) >> 8;                                \
				(GG) = (sg * (0x100 - dg)) >> 8;                                \
				(BB) = (sb * (0x100 - db)) >> 8;                                \
				break;                                                          \
																				\
			case 7:     /* AOMDST_ALPHA */                                      \
				(RR) = (sr * (0x100 - da)) >> 8;                                \
				(GG) = (sg * (0x100 - da)) >> 8;                                \
				(BB) = (sb * (0x100 - da)) >> 8;                                \
				break;                                                          \
																				\
			case 15:    /* ASATURATE */                                         \
				ta = (sa < (0x100 - da)) ? sa : (0x100 - da);                   \
				(RR) = (sr * (ta + 1)) >> 8;                                    \
				(GG) = (sg * (ta + 1)) >> 8;                                    \
				(BB) = (sb * (ta + 1)) >> 8;                                    \
				break;                                                          \
		}                                                                       \
																				\
		/* add in dest portion */                                               \
		switch (ALPHAMODE_DSTRGBBLEND(ALPHAMODE))                               \
		{                                                                       \
			default:    /* reserved */                                          \
			case 0:     /* AZERO */                                             \
				break;                                                          \
																				\
			case 1:     /* ASRC_ALPHA */                                        \
				(RR) += (dr * (sa + 1)) >> 8;                                   \
				(GG) += (dg * (sa + 1)) >> 8;                                   \
				(BB) += (db * (sa + 1)) >> 8;                                   \
				break;                                                          \
																				\
			case 2:     /* A_COLOR */                                           \
				(RR) += (dr * (sr + 1)) >> 8;                                   \
				(GG) += (dg * (sg + 1)) >> 8;                                   \
				(BB) += (db * (sb + 1)) >> 8;                                   \
				break;                                                          \
																				\
			case 3:     /* ADST_ALPHA */                                        \
				(RR) += (dr * (da + 1)) >> 8;                                   \
				(GG) += (dg * (da + 1)) >> 8;                                   \
				(BB) += (db * (da + 1)) >> 8;                                   \
				break;                                                          \
																				\
			case 4:     /* AONE */                                              \
				(RR) += dr;                                                     \
				(GG) += dg;                                                     \
				(BB) += db;                                                     \
				break;                                                          \
																				\
			case 5:     /* AOMSRC_ALPHA */                                      \
				(RR) += (dr * (0x100 - sa)) >> 8;                               \
				(GG) += (dg * (0x100 - sa)) >> 8;                               \
				(BB) += (db * (0x100 - sa)) >> 8;                               \
				break;                                                          \
																				\
			case 6:     /* AOM_COLOR */                                         \
				(RR) += (dr * (0x100 - sr)) >> 8;                               \
				(GG) += (dg * (0x100 - sg)) >> 8;                               \
				(BB) += (db * (0x100 - sb)) >> 8;                               \
				break;                                                          \
																				\
			case 7:     /* AOMDST_ALPHA */                                      \
				(RR) += (dr * (0x100 - da)) >> 8;                               \
				(GG) += (dg * (0x100 - da)) >> 8;                               \
				(BB) += (db * (0x100 - da)) >> 8;                               \
				break;                                                          \
																				\
			case 15:    /* A_COLORBEFOREFOG */                                  \
				(RR) += (dr * (prefogr + 1)) >> 8;                              \
				(GG) += (dg * (prefogg + 1)) >> 8;                              \
				(BB) += (db * (prefogb + 1)) >> 8;                              \
				break;                                                          \
		}                                                                       \
																				\
		/* blend the source alpha */                                            \
		(AA) = 0;                                                               \
		if (ALPHAMODE_SRCALPHABLEND(ALPHAMODE) == 4)                            \
			(AA) = sa;                                                          \
																				\
		/* blend the dest alpha */                                              \
		if (ALPHAMODE_DSTALPHABLEND(ALPHAMODE) == 4)                            \
			(AA) += da;                                                         \
																				\
		/* clamp */                                                             \
		CLAMP((RR), 0x00, 0xff);                                                \
		CLAMP((GG), 0x00, 0xff);                                                \
		CLAMP((BB), 0x00, 0xff);                                                \
		CLAMP((AA), 0x00, 0xff);                                                \
	}                                                                           \
}                                                                               \
while (0)

static inline void ATTR_FORCE_INLINE alphaBlend(uint32_t FBZMODE, uint32_t ALPHAMODE, int32_t x, const uint8_t *dither, int dpix, uint16_t *depth, rgbaint_t &preFog, rgbaint_t &srcColor, rgb_t *convTable)
{
	{
		//int dpix = dest[XX];
		int dr, dg, db;
		//EXTRACT_565_TO_888(dpix, dr, dg, db);
		rgb_t drgb = convTable[dpix];
		drgb.expand_rgb(dr, dg, db);
		int da = FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) ? depth[x] : 0xff;
		//int sr = (RR);
		//int sg = (GG);
		//int sb = (BB);
		//int sa = (AA);
		int sa = srcColor.get_a();
		int ta;
		int srcAlphaScale, destAlphaScale;
		rgbaint_t srcScale, destScale;

		/* apply dither subtraction */
		if (FBZMODE_ALPHA_DITHER_SUBTRACT(FBZMODE))
		{
			/* look up the dither value from the appropriate matrix */
			int dith = dither[x & 3];

			/* subtract the dither value */
			dr += dith;
			db += dith;
			dg += dith >> 1;
		}

		/* blend the source alpha */
		if (ALPHAMODE_SRCALPHABLEND(ALPHAMODE) == 4)
			srcAlphaScale = 256;
			//(AA) = sa;
		else
			srcAlphaScale = 0;

		/* compute source portion */
		switch (ALPHAMODE_SRCRGBBLEND(ALPHAMODE))
		{
			default:    /* reserved */
			case 0:     /* AZERO */
				srcScale.zero();
				//(RR) = (GG) = (BB) = 0;
				break;

			case 1:     /* ASRC_ALPHA */
				ta = sa + 1;
				srcScale.set_all(ta);
				//(RR) = (sr * (sa + 1)) >> 8;
				//(GG) = (sg * (sa + 1)) >> 8;
				//(BB) = (sb * (sa + 1)) >> 8;
				break;

			case 2:     /* A_COLOR */
				srcScale.set(dr, dr, dg, db);
				srcScale.add_imm(1);
				//(RR) = (sr * (dr + 1)) >> 8;
				//(GG) = (sg * (dg + 1)) >> 8;
				//(BB) = (sb * (db + 1)) >> 8;
				break;

			case 3:     /* ADST_ALPHA */
				ta = da + 1;
				srcScale.set_all(ta);
				//(RR) = (sr * (da + 1)) >> 8;
				//(GG) = (sg * (da + 1)) >> 8;
				//(BB) = (sb * (da + 1)) >> 8;
				break;

			case 4:     /* AONE */
				srcScale.set_all(256);
				break;

			case 5:     /* AOMSRC_ALPHA */
				ta = (0x100 - sa);
				srcScale.set_all(ta);
				//(RR) = (sr * (0x100 - sa)) >> 8;
				//(GG) = (sg * (0x100 - sa)) >> 8;
				//(BB) = (sb * (0x100 - sa)) >> 8;
				break;

			case 6:     /* AOM_COLOR */
				srcScale.set((0x100 - dr), (0x100 - dr), (0x100 - dg), (0x100 - db));
				//(RR) = (sr * (0x100 - dr)) >> 8;
				//(GG) = (sg * (0x100 - dg)) >> 8;
				//(BB) = (sb * (0x100 - db)) >> 8;
				break;

			case 7:     /* AOMDST_ALPHA */
				ta = (0x100 - da);
				srcScale.set_all(ta);
				//(RR) = (sr * (0x100 - da)) >> 8;
				//(GG) = (sg * (0x100 - da)) >> 8;
				//(BB) = (sb * (0x100 - da)) >> 8;
				break;

			case 15:    /* ASATURATE */
				ta = (sa < (0x100 - da)) ? sa : (0x100 - da);
				ta++;
				srcScale.set_all(ta);
				//(RR) = (sr * (ta + 1)) >> 8;
				//(GG) = (sg * (ta + 1)) >> 8;
				//(BB) = (sb * (ta + 1)) >> 8;
				break;
		}
		// Set srcScale alpha
		srcScale.set_a16(srcAlphaScale);

		/* blend the dest alpha */
		if (ALPHAMODE_DSTALPHABLEND(ALPHAMODE) == 4)
			destAlphaScale = 256;
			//(AA) += da;
		else
			destAlphaScale = 0;

		/* add in dest portion */
		switch (ALPHAMODE_DSTRGBBLEND(ALPHAMODE))
		{
			default:    /* reserved */
			case 0:     /* AZERO */
				destScale.zero();
				break;

			case 1:     /* ASRC_ALPHA */
				ta = sa + 1;
				destScale.set_all(ta);
				//(RR) += (dr * (sa + 1)) >> 8;
				//(GG) += (dg * (sa + 1)) >> 8;
				//(BB) += (db * (sa + 1)) >> 8;
				break;

			case 2:     /* A_COLOR */
				destScale.set(srcColor);
				destScale.add_imm(1);
				//(RR) += (dr * (sr + 1)) >> 8;
				//(GG) += (dg * (sg + 1)) >> 8;
				//(BB) += (db * (sb + 1)) >> 8;
				break;

			case 3:     /* ADST_ALPHA */
				ta = da + 1;
				destScale.set_all(ta);
				//(RR) += (dr * (da + 1)) >> 8;
				//(GG) += (dg * (da + 1)) >> 8;
				//(BB) += (db * (da + 1)) >> 8;
				break;

			case 4:     /* AONE */
				destScale.set_all(256);
				//(RR) += dr;
				//(GG) += dg;
				//(BB) += db;
				break;

			case 5:     /* AOMSRC_ALPHA */
				ta = (0x100 - sa);
				destScale.set_all(ta);
				//(RR) += (dr * (0x100 - sa)) >> 8;
				//(GG) += (dg * (0x100 - sa)) >> 8;
				//(BB) += (db * (0x100 - sa)) >> 8;
				break;

			case 6:     /* AOM_COLOR */
				destScale.set_all(0x100);
				destScale.sub(srcColor);
				//destScale.set(destAlphaScale, (0x100 - color.rgb.r), (0x100 - color.rgb.g), (0x100 - color.rgb.b));
				//(RR) += (dr * (0x100 - sr)) >> 8;
				//(GG) += (dg * (0x100 - sg)) >> 8;
				//(BB) += (db * (0x100 - sb)) >> 8;
				break;

			case 7:     /* AOMDST_ALPHA */
				ta = (0x100 - da);
				destScale.set_all(ta);
				//(RR) += (dr * (0x100 - da)) >> 8;
				//(GG) += (dg * (0x100 - da)) >> 8;
				//(BB) += (db * (0x100 - da)) >> 8;
				break;

			case 15:    /* A_COLORBEFOREFOG */
				destScale.set(preFog);
				destScale.add_imm(1);
				//(RR) += (dr * (prefogr + 1)) >> 8;
				//(GG) += (dg * (prefogg + 1)) >> 8;
				//(BB) += (db * (prefogb + 1)) >> 8;
				break;
		}

		// Set destScale alpha
		destScale.set_a16(destAlphaScale);

		// Main blend
		rgbaint_t destColor(da, dr, dg, db);

		srcColor.scale2_add_and_clamp(srcScale, destColor, destScale);
		/* clamp */
		//CLAMP((RR), 0x00, 0xff);
		//CLAMP((GG), 0x00, 0xff);
		//CLAMP((BB), 0x00, 0xff);
		//CLAMP((AA), 0x00, 0xff);
	}
}


/*************************************
 *
 *  Fogging macro
 *
 *************************************/

#define APPLY_FOGGING(VV, FOGMODE, FBZCP, XX, DITHER4, RR, GG, BB, ITERZ, ITERW, ITERAXXX)  \
do                                                                              \
{                                                                               \
	if (FOGMODE_ENABLE_FOG(FOGMODE))                                            \
	{                                                                           \
		rgb_union fogcolor = (VV)->reg[fogColor];                               \
		int32_t fr, fg, fb;                                                       \
																				\
		/* constant fog bypasses everything else */                             \
		if (FOGMODE_FOG_CONSTANT(FOGMODE))                                      \
		{                                                                       \
			fr = fogcolor.rgb.r;                                                \
			fg = fogcolor.rgb.g;                                                \
			fb = fogcolor.rgb.b;                                                \
		}                                                                       \
																				\
		/* non-constant fog comes from several sources */                       \
		else                                                                    \
		{                                                                       \
			int32_t fogblend = 0;                                                 \
																				\
			/* if fog_add is zero, we start with the fog color */               \
			if (FOGMODE_FOG_ADD(FOGMODE) == 0)                                  \
			{                                                                   \
				fr = fogcolor.rgb.r;                                            \
				fg = fogcolor.rgb.g;                                            \
				fb = fogcolor.rgb.b;                                            \
			}                                                                   \
			else                                                                \
				fr = fg = fb = 0;                                               \
																				\
			/* if fog_mult is zero, we subtract the incoming color */           \
			if (FOGMODE_FOG_MULT(FOGMODE) == 0)                                 \
			{                                                                   \
				fr -= (RR);                                                     \
				fg -= (GG);                                                     \
				fb -= (BB);                                                     \
			}                                                                   \
																				\
			/* fog blending mode */                                             \
			switch (FOGMODE_FOG_ZALPHA(FOGMODE))                                \
			{                                                                   \
				case 0:     /* fog table */                                     \
				{                                                               \
					int32_t delta = (VV)->fbi.fogdelta[fogdepth >> 10];             \
					int32_t deltaval;                                             \
																				\
					/* perform the multiply against lower 8 bits of wfloat */   \
					deltaval = (delta & (VV)->fbi.fogdelta_mask) *              \
								((fogdepth >> 2) & 0xff);                         \
																				\
					/* fog zones allow for negating this value */               \
					if (FOGMODE_FOG_ZONES(FOGMODE) && (delta & 2))              \
						deltaval = -deltaval;                                   \
					deltaval >>= 6;                                             \
																				\
					/* apply dither */                                          \
					if (FOGMODE_FOG_DITHER(FOGMODE))                            \
						deltaval += DITHER4[(XX) & 3];                          \
					deltaval >>= 4;                                             \
																				\
					/* add to the blending factor */                            \
					fogblend = (VV)->fbi.fogblend[fogdepth >> 10] + deltaval;     \
					break;                                                      \
				}                                                               \
																				\
				case 1:     /* iterated A */                                    \
					fogblend = ITERAXXX.rgb.a;                                  \
					break;                                                      \
																				\
				case 2:     /* iterated Z */                                    \
					CLAMPED_Z((ITERZ), FBZCP, fogblend);                        \
					fogblend >>= 8;                                             \
					break;                                                      \
																				\
				case 3:     /* iterated W - Voodoo 2 only */                    \
					CLAMPED_W((ITERW), FBZCP, fogblend);                        \
					break;                                                      \
			}                                                                   \
																				\
			/* perform the blend */                                             \
			fogblend++;                                                         \
			fr = (fr * fogblend) >> 8;                                          \
			fg = (fg * fogblend) >> 8;                                          \
			fb = (fb * fogblend) >> 8;                                          \
		}                                                                       \
																				\
		/* if fog_mult is 0, we add this to the original color */               \
		if (FOGMODE_FOG_MULT(FOGMODE) == 0)                                     \
		{                                                                       \
			(RR) += fr;                                                         \
			(GG) += fg;                                                         \
			(BB) += fb;                                                         \
		}                                                                       \
																				\
		/* otherwise this just becomes the new color */                         \
		else                                                                    \
		{                                                                       \
			(RR) = fr;                                                          \
			(GG) = fg;                                                          \
			(BB) = fb;                                                          \
		}                                                                       \
																				\
		/* clamp */                                                             \
		CLAMP((RR), 0x00, 0xff);                                                \
		CLAMP((GG), 0x00, 0xff);                                                \
		CLAMP((BB), 0x00, 0xff);                                                \
	}                                                                           \
}                                                                               \
while (0)

static inline void ATTR_FORCE_INLINE applyFogging(voodoo_device *vd, uint32_t fbzModeReg, uint32_t fogModeReg, uint32_t fbzCpReg,  int32_t x, const uint8_t *dither4, int32_t wFloat,
	rgbaint_t &color, int32_t iterz, int64_t iterw, const rgbaint_t &iterargb)
{
	{
		/* constant fog bypasses everything else */
		rgbaint_t fogColorLocal(vd->reg[fogColor].u);

		if (FOGMODE_FOG_CONSTANT(fogModeReg))
		{
			/* if fog_mult is 0, we add this to the original color */
			if (FOGMODE_FOG_MULT(fogModeReg) == 0)
			{
				fogColorLocal.add(color);
				fogColorLocal.clamp_to_uint8();
				//color += fog;
			}

			/* otherwise this just becomes the new color */
			else
			{
				//color = fogColorLocal;
				//color = fog;
			}
		}
		/* non-constant fog comes from several sources */
		else
		{
			int32_t fogblend = 0;

			/* if fog_add is zero, we start with the fog color */
			if (FOGMODE_FOG_ADD(fogModeReg))
				fogColorLocal.zero();
				//fr = fg = fb = 0;

			/* if fog_mult is zero, we subtract the incoming color */
			if (!FOGMODE_FOG_MULT(fogModeReg))
			{
				// Need to check this, manual states 9 bits
				fogColorLocal.sub(color);
				//fog.rgb -= color.rgb;
				//fr -= (RR);
				//fg -= (GG);
				//fb -= (BB);
			}

			/* fog blending mode */
			switch (FOGMODE_FOG_ZALPHA(fogModeReg))
			{
				case 0:     /* fog table */
				{
					int32_t fogDepth = wFloat;
					/* add the bias for fog selection*/
					if (FBZMODE_ENABLE_DEPTH_BIAS(fbzModeReg))
					{
						fogDepth += (int16_t)vd->reg[zaColor].u;
						CLAMP(fogDepth, 0, 0xffff);
					}
					int32_t delta = vd->fbi.fogdelta[fogDepth >> 10];
					int32_t deltaval;

					/* perform the multiply against lower 8 bits of wfloat */
					deltaval = (delta & vd->fbi.fogdelta_mask) *
								((fogDepth >> 2) & 0xff);

					/* fog zones allow for negating this value */
					if (FOGMODE_FOG_ZONES(fogModeReg) && (delta & 2))
						deltaval = -deltaval;
					deltaval >>= 6;

					/* apply dither */
					if (FOGMODE_FOG_DITHER(fogModeReg))
						deltaval += dither4[x&3];
					deltaval >>= 4;

					/* add to the blending factor */
					fogblend = vd->fbi.fogblend[fogDepth >> 10] + deltaval;
					break;
				}

				case 1:     /* iterated A */
					fogblend = iterargb.get_a();
					break;

				case 2:     /* iterated Z */
					CLAMPED_Z(iterz, fbzCpReg, fogblend);
					fogblend >>= 8;
					break;

				case 3:     /* iterated W - Voodoo 2 only */
					CLAMPED_W(iterw, fbzCpReg, fogblend);
					break;
			}

			/* perform the blend */
			fogblend++;

			//fr = (fr * fogblend) >> 8;
			//fg = (fg * fogblend) >> 8;
			//fb = (fb * fogblend) >> 8;
			/* if fog_mult is 0, we add this to the original color */
			fogColorLocal.scale_imm_and_clamp((int16_t)fogblend);
			if (FOGMODE_FOG_MULT(fogModeReg) == 0)
			{
				fogColorLocal.add(color);
				fogColorLocal.clamp_to_uint8();
				//color += fog;
				//(RR) += fr;
				//(GG) += fg;
				//(BB) += fb;
			}

			/* otherwise this just becomes the new color */
			else
			{
				//color = fog;
				//(RR) = fr;
				//(GG) = fg;
				//(BB) = fb;
			}
		}


		/* clamp */
		//CLAMP((RR), 0x00, 0xff);
		//CLAMP((GG), 0x00, 0xff);
		//CLAMP((BB), 0x00, 0xff);
		fogColorLocal.merge_alpha16(color);
		color.set(fogColorLocal);
	}
}


/*************************************
 *
 *  Texture pipeline macro
 *
 *************************************/

#define TEXTURE_PIPELINE(TT, XX, DITHER4, TEXMODE, COTHER, LOOKUP, LODBASE, ITERS, ITERT, ITERW, RESULT) \
do                                                                              \
{                                                                               \
	int32_t blendr, blendg, blendb, blenda;                                       \
	int32_t tr, tg, tb, ta;                                                       \
	int32_t s, t, lod, ilod;                                                 \
	int32_t smax, tmax;                                                           \
	uint32_t texbase;                                                             \
	rgb_union c_local;                                                          \
																				\
	/* determine the S/T/LOD values for this texture */                         \
	if (TEXMODE_ENABLE_PERSPECTIVE(TEXMODE))                                    \
	{                                                                           \
		if (USE_FAST_RECIP) {                                                     \
			const int32_t oow = fast_reciplog((ITERW), &lod);                         \
			s = ((int64_t)oow * (ITERS)) >> 29;                                       \
			t = ((int64_t)oow * (ITERT)) >> 29;                                       \
		} else {                                                                  \
				multi_reciplog(ITERS, ITERT, ITERW, lod, s, t);                      \
		}                                                                       \
		lod += (LODBASE);                                                       \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		s = (ITERS) >> 14;                                                      \
		t = (ITERT) >> 14;                                                      \
		lod = (LODBASE);                                                        \
	}                                                                           \
																				\
	/* clamp W */                                                               \
	if (TEXMODE_CLAMP_NEG_W(TEXMODE) && (ITERW) < 0)                            \
		s = t = 0;                                                              \
																				\
	/* clamp the LOD */                                                         \
	lod += (TT)->lodbias;                                                       \
	if (TEXMODE_ENABLE_LOD_DITHER(TEXMODE))                                     \
		lod += DITHER4[(XX) & 3] << 4;                                          \
	if (lod < (TT)->lodmin)                                                     \
		lod = (TT)->lodmin;                                                     \
	if (lod > (TT)->lodmax)                                                     \
		lod = (TT)->lodmax;                                                     \
																				\
	/* now the LOD is in range; if we don't own this LOD, take the next one */  \
	ilod = lod >> 8;                                                            \
	if (!(((TT)->lodmask >> ilod) & 1))                                         \
		ilod++;                                                                 \
																				\
	/* fetch the texture base */                                                \
	texbase = (TT)->lodoffset[ilod];                                            \
																				\
	/* compute the maximum s and t values at this LOD */                        \
	smax = (TT)->wmask >> ilod;                                                 \
	tmax = (TT)->hmask >> ilod;                                                 \
																				\
	/* determine whether we are point-sampled or bilinear */                    \
	if ((lod == (TT)->lodmin && !TEXMODE_MAGNIFICATION_FILTER(TEXMODE)) ||      \
		(lod != (TT)->lodmin && !TEXMODE_MINIFICATION_FILTER(TEXMODE)))         \
	{                                                                           \
		/* point sampled */                                                     \
																				\
		uint32_t texel0;                                                          \
																				\
		/* adjust S/T for the LOD and strip off the fractions */                \
		s >>= ilod + 18;                                                        \
		t >>= ilod + 18;                                                        \
																				\
		/* clamp/wrap S/T if necessary */                                       \
		if (TEXMODE_CLAMP_S(TEXMODE))                                           \
			CLAMP(s, 0, smax);                                                  \
		if (TEXMODE_CLAMP_T(TEXMODE))                                           \
			CLAMP(t, 0, tmax);                                                  \
		s &= smax;                                                              \
		t &= tmax;                                                              \
		t *= smax + 1;                                                          \
																				\
		/* fetch texel data */                                                  \
		if (TEXMODE_FORMAT(TEXMODE) < 8)                                        \
		{                                                                       \
			texel0 = *(uint8_t *)&(TT)->ram[(texbase + t + s) & (TT)->mask];      \
			c_local.u = (LOOKUP)[texel0];                                       \
		}                                                                       \
		else                                                                    \
		{                                                                       \
			texel0 = *(uint16_t *)&(TT)->ram[(texbase + 2*(t + s)) & (TT)->mask]; \
			if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12) \
				c_local.u = (LOOKUP)[texel0];                                   \
			else                                                                \
				c_local.u = ((LOOKUP)[texel0 & 0xff] & 0xffffff) |              \
							((texel0 & 0xff00) << 16);                          \
		}                                                                       \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		/* bilinear filtered */                                                 \
																				\
		uint32_t texel0, texel1, texel2, texel3;                                  \
		uint32_t sfrac, tfrac;                                                    \
		int32_t s1, t1;                                                           \
																				\
		/* adjust S/T for the LOD and strip off all but the low 8 bits of */    \
		/* the fraction */                                                      \
		s >>= ilod + 10;                                                        \
		t >>= ilod + 10;                                                        \
																				\
		/* also subtract 1/2 texel so that (0.5,0.5) = a full (0,0) texel */    \
		s -= 0x80;                                                              \
		t -= 0x80;                                                              \
																				\
		/* extract the fractions */                                             \
		sfrac = s & (TT)->bilinear_mask;                                        \
		tfrac = t & (TT)->bilinear_mask;                                        \
																				\
		/* now toss the rest */                                                 \
		s >>= 8;                                                                \
		t >>= 8;                                                                \
		s1 = s + 1;                                                             \
		t1 = t + 1;                                                             \
																				\
		/* clamp/wrap S/T if necessary */                                       \
		if (TEXMODE_CLAMP_S(TEXMODE))                                           \
		{                                                                       \
			CLAMP(s, 0, smax);                                                  \
			CLAMP(s1, 0, smax);                                                 \
		}                                                                       \
		if (TEXMODE_CLAMP_T(TEXMODE))                                           \
		{                                                                       \
			CLAMP(t, 0, tmax);                                                  \
			CLAMP(t1, 0, tmax);                                                 \
		}                                                                       \
		s &= smax;                                                              \
		s1 &= smax;                                                             \
		t &= tmax;                                                              \
		t1 &= tmax;                                                             \
		t *= smax + 1;                                                          \
		t1 *= smax + 1;                                                         \
																				\
		/* fetch texel data */                                                  \
		if (TEXMODE_FORMAT(TEXMODE) < 8)                                        \
		{                                                                       \
			texel0 = *(uint8_t *)&(TT)->ram[(texbase + t + s) & (TT)->mask];      \
			texel1 = *(uint8_t *)&(TT)->ram[(texbase + t + s1) & (TT)->mask];     \
			texel2 = *(uint8_t *)&(TT)->ram[(texbase + t1 + s) & (TT)->mask];     \
			texel3 = *(uint8_t *)&(TT)->ram[(texbase + t1 + s1) & (TT)->mask];    \
			texel0 = (LOOKUP)[texel0];                                          \
			texel1 = (LOOKUP)[texel1];                                          \
			texel2 = (LOOKUP)[texel2];                                          \
			texel3 = (LOOKUP)[texel3];                                          \
		}                                                                       \
		else                                                                    \
		{                                                                       \
			texel0 = *(uint16_t *)&(TT)->ram[(texbase + 2*(t + s)) & (TT)->mask]; \
			texel1 = *(uint16_t *)&(TT)->ram[(texbase + 2*(t + s1)) & (TT)->mask];\
			texel2 = *(uint16_t *)&(TT)->ram[(texbase + 2*(t1 + s)) & (TT)->mask];\
			texel3 = *(uint16_t *)&(TT)->ram[(texbase + 2*(t1 + s1)) & (TT)->mask];\
			if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12) \
			{                                                                   \
				texel0 = (LOOKUP)[texel0];                                      \
				texel1 = (LOOKUP)[texel1];                                      \
				texel2 = (LOOKUP)[texel2];                                      \
				texel3 = (LOOKUP)[texel3];                                      \
			}                                                                   \
			else                                                                \
			{                                                                   \
				texel0 = ((LOOKUP)[texel0 & 0xff] & 0xffffff) |                 \
							((texel0 & 0xff00) << 16);                          \
				texel1 = ((LOOKUP)[texel1 & 0xff] & 0xffffff) |                 \
							((texel1 & 0xff00) << 16);                          \
				texel2 = ((LOOKUP)[texel2 & 0xff] & 0xffffff) |                 \
							((texel2 & 0xff00) << 16);                          \
				texel3 = ((LOOKUP)[texel3 & 0xff] & 0xffffff) |                 \
							((texel3 & 0xff00) << 16);                          \
			}                                                                   \
		}                                                                       \
																				\
		/* weigh in each texel */                                               \
		c_local.u = rgbaint_t::bilinear_filter(texel0, texel1, texel2, texel3, sfrac, tfrac); \
	}                                                                           \
																				\
	/* select zero/other for RGB */                                             \
	if (!TEXMODE_TC_ZERO_OTHER(TEXMODE))                                        \
	{                                                                           \
		tr = COTHER.rgb.r;                                                      \
		tg = COTHER.rgb.g;                                                      \
		tb = COTHER.rgb.b;                                                      \
	}                                                                           \
	else                                                                        \
		tr = tg = tb = 0;                                                       \
																				\
	/* select zero/other for alpha */                                           \
	if (!TEXMODE_TCA_ZERO_OTHER(TEXMODE))                                       \
		ta = COTHER.rgb.a;                                                      \
	else                                                                        \
		ta = 0;                                                                 \
																				\
	/* potentially subtract c_local */                                          \
	if (TEXMODE_TC_SUB_CLOCAL(TEXMODE))                                         \
	{                                                                           \
		tr -= c_local.rgb.r;                                                    \
		tg -= c_local.rgb.g;                                                    \
		tb -= c_local.rgb.b;                                                    \
	}                                                                           \
	if (TEXMODE_TCA_SUB_CLOCAL(TEXMODE))                                        \
		ta -= c_local.rgb.a;                                                    \
																				\
	/* blend RGB */                                                             \
	switch (TEXMODE_TC_MSELECT(TEXMODE))                                        \
	{                                                                           \
		default:    /* reserved */                                              \
		case 0:     /* zero */                                                  \
			blendr = blendg = blendb = 0;                                       \
			break;                                                              \
																				\
		case 1:     /* c_local */                                               \
			blendr = c_local.rgb.r;                                             \
			blendg = c_local.rgb.g;                                             \
			blendb = c_local.rgb.b;                                             \
			break;                                                              \
																				\
		case 2:     /* a_other */                                               \
			blendr = blendg = blendb = COTHER.rgb.a;                            \
			break;                                                              \
																				\
		case 3:     /* a_local */                                               \
			blendr = blendg = blendb = c_local.rgb.a;                           \
			break;                                                              \
																				\
		case 4:     /* LOD (detail factor) */                                   \
			if ((TT)->detailbias <= lod)                                        \
				blendr = blendg = blendb = 0;                                   \
			else                                                                \
			{                                                                   \
				blendr = ((((TT)->detailbias - lod) << (TT)->detailscale) >> 8);\
				if (blendr > (TT)->detailmax)                                   \
					blendr = (TT)->detailmax;                                   \
				blendg = blendb = blendr;                                       \
			}                                                                   \
			break;                                                              \
																				\
		case 5:     /* LOD fraction */                                          \
			blendr = blendg = blendb = lod & 0xff;                              \
			break;                                                              \
	}                                                                           \
																				\
	/* blend alpha */                                                           \
	switch (TEXMODE_TCA_MSELECT(TEXMODE))                                       \
	{                                                                           \
		default:    /* reserved */                                              \
		case 0:     /* zero */                                                  \
			blenda = 0;                                                         \
			break;                                                              \
																				\
		case 1:     /* c_local */                                               \
			blenda = c_local.rgb.a;                                             \
			break;                                                              \
																				\
		case 2:     /* a_other */                                               \
			blenda = COTHER.rgb.a;                                              \
			break;                                                              \
																				\
		case 3:     /* a_local */                                               \
			blenda = c_local.rgb.a;                                             \
			break;                                                              \
																				\
		case 4:     /* LOD (detail factor) */                                   \
			if ((TT)->detailbias <= lod)                                        \
				blenda = 0;                                                     \
			else                                                                \
			{                                                                   \
				blenda = ((((TT)->detailbias - lod) << (TT)->detailscale) >> 8);\
				if (blenda > (TT)->detailmax)                                   \
					blenda = (TT)->detailmax;                                   \
			}                                                                   \
			break;                                                              \
																				\
		case 5:     /* LOD fraction */                                          \
			blenda = lod & 0xff;                                                \
			break;                                                              \
	}                                                                           \
																				\
	/* reverse the RGB blend */                                                 \
	if (!TEXMODE_TC_REVERSE_BLEND(TEXMODE))                                     \
	{                                                                           \
		blendr ^= 0xff;                                                         \
		blendg ^= 0xff;                                                         \
		blendb ^= 0xff;                                                         \
	}                                                                           \
																				\
	/* reverse the alpha blend */                                               \
	if (!TEXMODE_TCA_REVERSE_BLEND(TEXMODE))                                    \
		blenda ^= 0xff;                                                         \
																				\
	/* do the blend */                                                          \
	tr = (tr * (blendr + 1)) >> 8;                                              \
	tg = (tg * (blendg + 1)) >> 8;                                              \
	tb = (tb * (blendb + 1)) >> 8;                                              \
	ta = (ta * (blenda + 1)) >> 8;                                              \
																				\
	/* add clocal or alocal to RGB */                                           \
	switch (TEXMODE_TC_ADD_ACLOCAL(TEXMODE))                                    \
	{                                                                           \
		case 3:     /* reserved */                                              \
		case 0:     /* nothing */                                               \
			break;                                                              \
																				\
		case 1:     /* add c_local */                                           \
			tr += c_local.rgb.r;                                                \
			tg += c_local.rgb.g;                                                \
			tb += c_local.rgb.b;                                                \
			break;                                                              \
																				\
		case 2:     /* add_alocal */                                            \
			tr += c_local.rgb.a;                                                \
			tg += c_local.rgb.a;                                                \
			tb += c_local.rgb.a;                                                \
			break;                                                              \
	}                                                                           \
																				\
	/* add clocal or alocal to alpha */                                         \
	if (TEXMODE_TCA_ADD_ACLOCAL(TEXMODE))                                       \
		ta += c_local.rgb.a;                                                    \
																				\
	/* clamp */                                                                 \
	RESULT.rgb.r = (tr < 0) ? 0 : (tr > 0xff) ? 0xff : tr;                      \
	RESULT.rgb.g = (tg < 0) ? 0 : (tg > 0xff) ? 0xff : tg;                      \
	RESULT.rgb.b = (tb < 0) ? 0 : (tb > 0xff) ? 0xff : tb;                      \
	RESULT.rgb.a = (ta < 0) ? 0 : (ta > 0xff) ? 0xff : ta;                      \
																				\
	/* invert */                                                                \
	if (TEXMODE_TC_INVERT_OUTPUT(TEXMODE))                                      \
		RESULT.u ^= 0x00ffffff;                                                 \
	if (TEXMODE_TCA_INVERT_OUTPUT(TEXMODE))                                     \
		RESULT.rgb.a ^= 0xff;                                                   \
}                                                                               \
while (0)



/*************************************
 *
 *  Pixel pipeline macros
 *
 *************************************/

#define PIXEL_PIPELINE_BEGIN(vd, STATS, XX, YY, FBZCOLORPATH, FBZMODE, ITERZ, ITERW)    \
do                                                                              \
{                                                                               \
	int32_t depthval, wfloat, biasdepth;                                  \
	int32_t r, g, b;                                                           \
																				\
	(STATS)->pixels_in++;                                                       \
																				\
	/* apply clipping */                                                        \
	/* note that for perf reasons, we assume the caller has done clipping */    \
																				\
	/* handle stippling */                                                      \
	if (FBZMODE_ENABLE_STIPPLE(FBZMODE))                                        \
	{                                                                           \
		/* rotate mode */                                                       \
		if (FBZMODE_STIPPLE_PATTERN(FBZMODE) == 0)                              \
		{                                                                       \
			vd->reg[stipple].u = (vd->reg[stipple].u << 1) | (vd->reg[stipple].u >> 31);\
			if ((vd->reg[stipple].u & 0x80000000) == 0)                         \
			{                                                                   \
				vd->stats.total_stippled++;                                     \
				goto skipdrawdepth;                                             \
			}                                                                   \
		}                                                                       \
																				\
		/* pattern mode */                                                      \
		else                                                                    \
		{                                                                       \
			int stipple_index = (((YY) & 3) << 3) | (~(XX) & 7);                \
			if (((vd->reg[stipple].u >> stipple_index) & 1) == 0)               \
			{                                                                   \
				vd->stats.total_stippled++;                                     \
				goto skipdrawdepth;                                             \
			}                                                                   \
		}                                                                       \
	}                                                                           \
																				\
	/* compute "floating point" W value (used for depth and fog) */             \
	if ((ITERW) & 0xffff00000000U)                                              \
		wfloat = 0x0000;                                                        \
	else                                                                        \
	{                                                                           \
		uint32_t temp = (uint32_t)(ITERW);                                      \
		if (!(temp & 0xffff0000))                                               \
			wfloat = 0xffff;                                                    \
		else                                                                    \
		{                                                                       \
			int exp = count_leading_zeros(temp);                                \
			wfloat = ((exp << 12) | ((~temp >> (19 - exp)) & 0xfff)) + 1;       \
		}                                                                       \
	}                                                                           \
																				\
	/* compute depth value (W or Z) for this pixel */                           \
	if (FBZMODE_WBUFFER_SELECT(FBZMODE))                                   \
	{                                                                           \
		if (!FBZMODE_DEPTH_FLOAT_SELECT(FBZMODE))                          \
			depthval = wfloat;                                                      \
		else                                                                        \
		{                                                                           \
			if ((ITERZ) & 0xf0000000)                                               \
				depthval = 0x0000;                                                  \
			else                                                                    \
			{                                                                       \
				uint32_t temp = (ITERZ << 4);                                       \
				if (!(temp & 0xffff0000))                                           \
					depthval = 0xffff;                                              \
				else                                                                \
				{                                                                   \
					int exp = count_leading_zeros(temp);                            \
					depthval = ((exp << 12) | ((~temp >> (19 - exp)) & 0xfff)) + 1; \
				}                                                                   \
			}                                                                       \
		}                                                                           \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		CLAMPED_Z(ITERZ, FBZCOLORPATH, depthval);                               \
	}                                                                           \
	/* add the bias */                                                          \
	biasdepth = depthval;                                                     \
	if (FBZMODE_ENABLE_DEPTH_BIAS(FBZMODE))                                     \
	{                                                                           \
		biasdepth += (int16_t)vd->reg[zaColor].u;                                \
		CLAMP(biasdepth, 0, 0xffff);                                             \
	}


#define DEPTH_TEST(vd, STATS, XX, FBZMODE)    \
do                                                                              \
{                                                                               \
	/* handle depth buffer testing */                                           \
	if (FBZMODE_ENABLE_DEPTHBUF(FBZMODE))                                       \
	{                                                                           \
		int32_t depthsource;                                                      \
																				\
		/* the source depth is either the iterated W/Z+bias or a */             \
		/* constant value */                                                    \
		if (FBZMODE_DEPTH_SOURCE_COMPARE(FBZMODE) == 0)                         \
			depthsource = biasdepth;                                             \
		else                                                                    \
			depthsource = (uint16_t)vd->reg[zaColor].u;                         \
																				\
		/* test against the depth buffer */                                     \
		switch (FBZMODE_DEPTH_FUNCTION(FBZMODE))                                \
		{                                                                       \
			case 0:     /* depthOP = never */                                   \
				(STATS)->zfunc_fail++;                                          \
				goto skipdrawdepth;                                             \
																				\
			case 1:     /* depthOP = less than */                               \
				if (depthsource >= depth[XX])                                   \
				{                                                               \
					(STATS)->zfunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 2:     /* depthOP = equal */                                   \
				if (depthsource != depth[XX])                                   \
				{                                                               \
					(STATS)->zfunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 3:     /* depthOP = less than or equal */                      \
				if (depthsource > depth[XX])                                    \
				{                                                               \
					(STATS)->zfunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 4:     /* depthOP = greater than */                            \
				if (depthsource <= depth[XX])                                   \
				{                                                               \
					(STATS)->zfunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 5:     /* depthOP = not equal */                               \
				if (depthsource == depth[XX])                                   \
				{                                                               \
					(STATS)->zfunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 6:     /* depthOP = greater than or equal */                   \
				if (depthsource < depth[XX])                                    \
				{                                                               \
					(STATS)->zfunc_fail++;                                      \
					goto skipdrawdepth;                                         \
				}                                                               \
				break;                                                          \
																				\
			case 7:     /* depthOP = always */                                  \
				break;                                                          \
		}                                                                       \
	}                                                                       \
}                                                                               \
while (0)

inline bool ATTR_FORCE_INLINE voodoo_device::depthTest(uint16_t zaColorReg, stats_block *stats, int32_t destDepth, uint32_t fbzModeReg, int32_t biasdepth)
{
	/* handle depth buffer testing */
	{
		int32_t depthsource;

		/* the source depth is either the iterated W/Z+bias or a */
		/* constant value */
		if (FBZMODE_DEPTH_SOURCE_COMPARE(fbzModeReg) == 0)
			depthsource = biasdepth;
		else
			depthsource = zaColorReg;

		/* test against the depth buffer */
		switch (FBZMODE_DEPTH_FUNCTION(fbzModeReg))
		{
			case 0:     /* depthOP = never */
				stats->zfunc_fail++;
				return false;

			case 1:     /* depthOP = less than */
				if (depthsource >= destDepth)
				{
					stats->zfunc_fail++;
					return false;
				}
				break;

			case 2:     /* depthOP = equal */
				if (depthsource != destDepth)
				{
					stats->zfunc_fail++;
					return false;
				}
				break;

			case 3:     /* depthOP = less than or equal */
				if (depthsource > destDepth)
				{
					stats->zfunc_fail++;
					return false;
				}
				break;

			case 4:     /* depthOP = greater than */
				if (depthsource <= destDepth)
				{
					stats->zfunc_fail++;
					return false;
				}
				break;

			case 5:     /* depthOP = not equal */
				if (depthsource == destDepth)
				{
					stats->zfunc_fail++;
					return false;
				}
				break;

			case 6:     /* depthOP = greater than or equal */
				if (depthsource < destDepth)
				{
					stats->zfunc_fail++;
					return false;
				}
				break;

			case 7:     /* depthOP = always */
				break;
		}
	}
	return true;
}

#define PIXEL_PIPELINE_END(STATS, DITHER_LOOKUP, XX, dest, depth, FBZMODE) \
																				\
	r = color.get_r(); g = color.get_g(); b = color.get_b();                     \
	/* modify the pixel for debugging purposes */                               \
	MODIFY_PIXEL(VV);                                                           \
																				\
	/* write to framebuffer */                                                  \
	if (FBZMODE_RGB_BUFFER_MASK(FBZMODE))                                       \
	{                                                                           \
		/* apply dithering */                                                   \
		APPLY_DITHER(FBZMODE, XX, DITHER_LOOKUP, r, g, b);                      \
		dest[XX] = (r << 11) | (g << 5) | b;                                    \
	}                                                                           \
																				\
	/* write to aux buffer */                                                   \
	/*if (depth && FBZMODE_AUX_BUFFER_MASK(FBZMODE))*/                              \
	if (FBZMODE_AUX_BUFFER_MASK(FBZMODE))                              \
	{                                                                           \
		if (FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) == 0)                          \
			depth[XX] = biasdepth;                                               \
		else                                                                    \
			depth[XX] = color.get_a();                                          \
	}                                                                           \
																				\
	/* track pixel writes to the frame buffer regardless of mask */             \
	(STATS)->pixels_out++;                                                      \
																				\
skipdrawdepth:                                                                  \
	;                                                                           \
}                                                                               \
while (0)



/*************************************
 *
 *  Colorpath pipeline macro
 *
 *************************************/

/*

    c_other_is_used:

        if (FBZMODE_ENABLE_CHROMAKEY(FBZMODE) ||
            FBZCP_CC_ZERO_OTHER(FBZCOLORPATH) == 0)

    c_local_is_used:

        if (FBZCP_CC_SUB_CLOCAL(FBZCOLORPATH) ||
            FBZCP_CC_MSELECT(FBZCOLORPATH) == 1 ||
            FBZCP_CC_ADD_ACLOCAL(FBZCOLORPATH) == 1)

    NEEDS_ITER_RGB:

        if ((c_other_is_used && FBZCP_CC_RGBSELECT(FBZCOLORPATH) == 0) ||
            (c_local_is_used && (FBZCP_CC_LOCALSELECT_OVERRIDE(FBZCOLORPATH) != 0 || FBZCP_CC_LOCALSELECT(FBZCOLORPATH) == 0))

    NEEDS_ITER_A:

        if ((a_other_is_used && FBZCP_CC_ASELECT(FBZCOLORPATH) == 0) ||
            (a_local_is_used && FBZCP_CCA_LOCALSELECT(FBZCOLORPATH) == 0))

    NEEDS_ITER_Z:

        if (FBZMODE_WBUFFER_SELECT(FBZMODE) == 0 ||
            FBZMODE_DEPTH_FLOAT_SELECT(FBZMODE) != 0 ||
            FBZCP_CCA_LOCALSELECT(FBZCOLORPATH) == 2)


*/

/*
    Expects the following declarations to be outside of this scope:

    int32_t r, g, b, a;
*/
#define COLORPATH_PIPELINE(VV, STATS, FBZCOLORPATH, FBZMODE, ALPHAMODE, TEXELARGB, ITERZ, ITERW, ITERARGB) \
do                                                                              \
{                                                                               \
	int32_t blendr, blendg, blendb, blenda;                                       \
	rgb_union c_other;                                                          \
	rgb_union c_local;                                                          \
																				\
	/* compute c_other */                                                       \
	switch (FBZCP_CC_RGBSELECT(FBZCOLORPATH))                                   \
	{                                                                           \
		case 0:     /* iterated RGB */                                          \
			c_other.u = ITERARGB.u;                                             \
			break;                                                              \
																				\
		case 1:     /* texture RGB */                                           \
			c_other.u = TEXELARGB.u;                                            \
			break;                                                              \
																				\
		case 2:     /* color1 RGB */                                            \
			c_other.u = (VV)->reg[color1].u;                                    \
			break;                                                              \
																				\
		default:    /* reserved - voodoo3 framebufferRGB */                   \
			c_other.u = 0;                                                      \
			break;                                                              \
	}                                                                           \
																				\
	/* handle chroma key */                                                     \
	APPLY_CHROMAKEY(VV, STATS, FBZMODE, c_other);                               \
																				\
	/* compute a_other */                                                       \
	switch (FBZCP_CC_ASELECT(FBZCOLORPATH))                                     \
	{                                                                           \
		case 0:     /* iterated alpha */                                        \
			c_other.rgb.a = ITERARGB.rgb.a;                                     \
			break;                                                              \
																				\
		case 1:     /* texture alpha */                                         \
			c_other.rgb.a = TEXELARGB.rgb.a;                                    \
			break;                                                              \
																				\
		case 2:     /* color1 alpha */                                          \
			c_other.rgb.a = (VV)->reg[color1].rgb.a;                            \
			break;                                                              \
																				\
		default:    /* reserved */                                              \
			c_other.rgb.a = 0;                                                  \
			break;                                                              \
	}                                                                           \
																				\
	/* handle alpha mask */                                                     \
	APPLY_ALPHAMASK(VV, STATS, FBZMODE, c_other.rgb.a);                         \
																				\
	/* compute c_local */                                                       \
	if (FBZCP_CC_LOCALSELECT_OVERRIDE(FBZCOLORPATH) == 0)                       \
	{                                                                           \
		if (FBZCP_CC_LOCALSELECT(FBZCOLORPATH) == 0)    /* iterated RGB */      \
			c_local.u = ITERARGB.u;                                             \
		else                                            /* color0 RGB */        \
			c_local.u = (VV)->reg[color0].u;                                    \
	}                                                                           \
	else                                                                        \
	{                                                                           \
		if (!(TEXELARGB.rgb.a & 0x80))                  /* iterated RGB */      \
			c_local.u = ITERARGB.u;                                             \
		else                                            /* color0 RGB */        \
			c_local.u = (VV)->reg[color0].u;                                    \
	}                                                                           \
																				\
	/* compute a_local */                                                       \
	switch (FBZCP_CCA_LOCALSELECT(FBZCOLORPATH))                                \
	{                                                                           \
		default:                                                                \
		case 0:     /* iterated alpha */                                        \
			c_local.rgb.a = ITERARGB.rgb.a;                                     \
			break;                                                              \
																				\
		case 1:     /* color0 alpha */                                          \
			c_local.rgb.a = (VV)->reg[color0].rgb.a;                            \
			break;                                                              \
																				\
		case 2:     /* clamped iterated Z[27:20] */                             \
		{                                                                       \
			int temp;                                                           \
			CLAMPED_Z(ITERZ, FBZCOLORPATH, temp);                               \
			c_local.rgb.a = (uint8_t)temp;                                        \
			break;                                                              \
		}                                                                       \
																				\
		case 3:     /* clamped iterated W[39:32] */                             \
		{                                                                       \
			int temp;                                                           \
			CLAMPED_W(ITERW, FBZCOLORPATH, temp);           /* Voodoo 2 only */ \
			c_local.rgb.a = (uint8_t)temp;                                        \
			break;                                                              \
		}                                                                       \
	}                                                                           \
																				\
	/* select zero or a_other */                                                \
	if (!FBZCP_CCA_ZERO_OTHER(FBZCOLORPATH))                                \
		a = c_other.rgb.a;                                                      \
	else                                                                        \
		a = 0;                                                                  \
																				\
	/* subtract a_local */                                                      \
	if (FBZCP_CCA_SUB_CLOCAL(FBZCOLORPATH))                                     \
		a -= c_local.rgb.a;                                                     \
																				\
	/* blend alpha */                                                           \
	switch (FBZCP_CCA_MSELECT(FBZCOLORPATH))                                    \
	{                                                                           \
		default:    /* reserved */                                              \
		case 0:     /* 0 */                                                     \
			blenda = 0;                                                         \
			break;                                                              \
																				\
		case 1:     /* a_local */                                               \
			blenda = c_local.rgb.a;                                             \
			break;                                                              \
																				\
		case 2:     /* a_other */                                               \
			blenda = c_other.rgb.a;                                             \
			break;                                                              \
																				\
		case 3:     /* a_local */                                               \
			blenda = c_local.rgb.a;                                             \
			break;                                                              \
																				\
		case 4:     /* texture alpha */                                         \
			blenda = TEXELARGB.rgb.a;                                           \
			break;                                                              \
	}                                                                           \
																				\
	/* reverse the alpha blend */                                               \
	if (!FBZCP_CCA_REVERSE_BLEND(FBZCOLORPATH))                                 \
		blenda ^= 0xff;                                                         \
																				\
	/* do the blend */                                                          \
	a = (a * (blenda + 1)) >> 8;                                                \
																				\
	/* add clocal or alocal to alpha */                                         \
	if (FBZCP_CCA_ADD_ACLOCAL(FBZCOLORPATH))                                    \
		a += c_local.rgb.a;                                                     \
																				\
	/* clamp */                                                                 \
	CLAMP(a, 0x00, 0xff);                                                       \
																				\
	/* invert */                                                                \
	if (FBZCP_CCA_INVERT_OUTPUT(FBZCOLORPATH))                                  \
		a ^= 0xff;                                                              \
																				\
	/* handle alpha test */                                                     \
	APPLY_ALPHATEST(VV, STATS, ALPHAMODE, a);                                   \
																				\
																				\
	/* select zero or c_other */                                                \
	if (FBZCP_CC_ZERO_OTHER(FBZCOLORPATH) == 0)                                 \
	{                                                                           \
		r = c_other.rgb.r;                                                      \
		g = c_other.rgb.g;                                                      \
		b = c_other.rgb.b;                                                      \
	}                                                                           \
	else                                                                        \
		r = g = b = 0;                                                          \
																				\
	/* subtract c_local */                                                      \
	if (FBZCP_CC_SUB_CLOCAL(FBZCOLORPATH))                                      \
	{                                                                           \
		r -= c_local.rgb.r;                                                     \
		g -= c_local.rgb.g;                                                     \
		b -= c_local.rgb.b;                                                     \
	}                                                                           \
																				\
	/* blend RGB */                                                             \
	switch (FBZCP_CC_MSELECT(FBZCOLORPATH))                                     \
	{                                                                           \
		default:    /* reserved */                                              \
		case 0:     /* 0 */                                                     \
			blendr = blendg = blendb = 0;                                       \
			break;                                                              \
																				\
		case 1:     /* c_local */                                               \
			blendr = c_local.rgb.r;                                             \
			blendg = c_local.rgb.g;                                             \
			blendb = c_local.rgb.b;                                             \
			break;                                                              \
																				\
		case 2:     /* a_other */                                               \
			blendr = blendg = blendb = c_other.rgb.a;                           \
			break;                                                              \
																				\
		case 3:     /* a_local */                                               \
			blendr = blendg = blendb = c_local.rgb.a;                           \
			break;                                                              \
																				\
		case 4:     /* texture alpha */                                         \
			blendr = blendg = blendb = TEXELARGB.rgb.a;                         \
			break;                                                              \
																				\
		case 5:     /* texture RGB (Voodoo 2 only) */                           \
			blendr = TEXELARGB.rgb.r;                                           \
			blendg = TEXELARGB.rgb.g;                                           \
			blendb = TEXELARGB.rgb.b;                                           \
			break;                                                              \
	}                                                                           \
																				\
	/* reverse the RGB blend */                                                 \
	if (!FBZCP_CC_REVERSE_BLEND(FBZCOLORPATH))                                  \
	{                                                                           \
		blendr ^= 0xff;                                                         \
		blendg ^= 0xff;                                                         \
		blendb ^= 0xff;                                                         \
	}                                                                           \
																				\
	/* do the blend */                                                          \
	r = (r * (blendr + 1)) >> 8;                                                \
	g = (g * (blendg + 1)) >> 8;                                                \
	b = (b * (blendb + 1)) >> 8;                                                \
																				\
	/* add clocal or alocal to RGB */                                           \
	switch (FBZCP_CC_ADD_ACLOCAL(FBZCOLORPATH))                                 \
	{                                                                           \
		case 3:     /* reserved */                                              \
		case 0:     /* nothing */                                               \
			break;                                                              \
																				\
		case 1:     /* add c_local */                                           \
			r += c_local.rgb.r;                                                 \
			g += c_local.rgb.g;                                                 \
			b += c_local.rgb.b;                                                 \
			break;                                                              \
																				\
		case 2:     /* add_alocal */                                            \
			r += c_local.rgb.a;                                                 \
			g += c_local.rgb.a;                                                 \
			b += c_local.rgb.a;                                                 \
			break;                                                              \
	}                                                                           \
																				\
	/* clamp */                                                                 \
	CLAMP(r, 0x00, 0xff);                                                       \
	CLAMP(g, 0x00, 0xff);                                                       \
	CLAMP(b, 0x00, 0xff);                                                       \
																				\
	/* invert */                                                                \
	if (FBZCP_CC_INVERT_OUTPUT(FBZCOLORPATH))                                   \
	{                                                                           \
		r ^= 0xff;                                                              \
		g ^= 0xff;                                                              \
		b ^= 0xff;                                                              \
	}                                                                           \
}                                                                               \
while (0)

inline bool ATTR_FORCE_INLINE voodoo_device::combineColor(voodoo_device *vd, stats_block *STATS, uint32_t FBZCOLORPATH, uint32_t FBZMODE,
													rgbaint_t TEXELARGB, int32_t ITERZ, int64_t ITERW, rgbaint_t &srcColor)
{
	rgbaint_t c_other;
	rgbaint_t c_local;
	rgbaint_t blend_color, blend_factor;
	rgbaint_t add_val;

	/* compute c_other */
	switch (FBZCP_CC_RGBSELECT(FBZCOLORPATH))
	{
		case 0:     /* iterated RGB */
			c_other.set(srcColor);
			break;

		case 1:     /* texture RGB */
			c_other.set(TEXELARGB);
			break;

		case 2:     /* color1 RGB */
			c_other.set(vd->reg[color1].u);
			break;

		default:    /* reserved - voodoo3 LFB RGB */
			c_other.zero();
			break;
	}

	/* handle chroma key */
	if (FBZMODE_ENABLE_CHROMAKEY(FBZMODE))
		if (!chromaKeyTest(vd, STATS, FBZMODE, c_other))
			return false;
	//APPLY_CHROMAKEY(vd->m_vds, STATS, FBZMODE, c_other);

	/* compute a_other */
	switch (FBZCP_CC_ASELECT(FBZCOLORPATH))
	{
		case 0:     /* iterated alpha */
			c_other.merge_alpha16(srcColor);
			break;

		case 1:     /* texture alpha */
			c_other.merge_alpha16(TEXELARGB);
			break;

		case 2:     /* color1 alpha */
			c_other.set_a16(vd->reg[color1].rgb.a);
			break;

		default:    /* reserved - voodoo3  LFB Alpha*/
			c_other.zero_alpha();
			break;
	}

	/* handle alpha mask */
	if (FBZMODE_ENABLE_ALPHA_MASK(FBZMODE))
		if (!alphaMaskTest(STATS, FBZMODE, c_other.get_a()))
			return false;
	//APPLY_ALPHAMASK(vd->m_vds, STATS, FBZMODE, c_other.rgb.a);


	/* compute c_local */
	if (FBZCP_CC_LOCALSELECT_OVERRIDE(FBZCOLORPATH) == 0)
	{
		if (FBZCP_CC_LOCALSELECT(FBZCOLORPATH) == 0)    /* iterated RGB */
			c_local.set(srcColor);
		else                                            /* color0 RGB */
			c_local.set(vd->reg[color0].u);
	}
	else
	{
		if (!(TEXELARGB.get_a() & 0x80))                  /* iterated RGB */
			c_local.set(srcColor);
		else                                            /* color0 RGB */
			c_local.set(vd->reg[color0].u);
	}

	/* compute a_local */
	switch (FBZCP_CCA_LOCALSELECT(FBZCOLORPATH))
	{
		default:
		case 0:     /* iterated alpha */
			c_local.merge_alpha16(srcColor);
			break;

		case 1:     /* color0 alpha */
			c_local.set_a16(vd->reg[color0].rgb.a);
			break;

		case 2:     /* clamped iterated Z[27:20] */
		{
			int temp;
			CLAMPED_Z(ITERZ, FBZCOLORPATH, temp);
			c_local.set_a16((uint8_t) temp);
			break;
		}

		case 3:     /* clamped iterated W[39:32] */
		{
			int temp;
			CLAMPED_W(ITERW, FBZCOLORPATH, temp);           /* Voodoo 2 only */
			c_local.set_a16((uint8_t) temp);
			break;
		}
	}

	/* select zero or c_other */
	if (FBZCP_CC_ZERO_OTHER(FBZCOLORPATH))
		//r = g = b = 0;
		blend_color.zero();
	else
		blend_color.set(c_other);

	/* select zero or a_other */
	if (FBZCP_CCA_ZERO_OTHER(FBZCOLORPATH))
		blend_color.zero_alpha();
	else
		blend_color.merge_alpha16(c_other);

	/* subtract a/c_local */
	if (FBZCP_CC_SUB_CLOCAL(FBZCOLORPATH) || (FBZCP_CCA_SUB_CLOCAL(FBZCOLORPATH)))
	{
		rgbaint_t sub_val;

		if (!FBZCP_CC_SUB_CLOCAL(FBZCOLORPATH))
			sub_val.zero();
		else
			sub_val.set(c_local);

		if (!FBZCP_CCA_SUB_CLOCAL(FBZCOLORPATH))
			sub_val.zero_alpha();
		else
			sub_val.merge_alpha16(c_local);

		blend_color.sub(sub_val);
	}

	/* blend RGB */
	switch (FBZCP_CC_MSELECT(FBZCOLORPATH))
	{
		default:    /* reserved */
		case 0:     /* 0 */
			blend_factor.zero();
			break;

		case 1:     /* c_local */
			blend_factor.set(c_local);
			break;

		case 2:     /* a_other */
			blend_factor.set(c_other.select_alpha32());
			break;

		case 3:     /* a_local */
			blend_factor.set(c_local.select_alpha32());
			break;

		case 4:     /* texture alpha */
			blend_factor.set(TEXELARGB.select_alpha32());
			break;

		case 5:     /* texture RGB (Voodoo 2 only) */
			blend_factor.set(TEXELARGB);
			break;
	}

	/* blend alpha */
	switch (FBZCP_CCA_MSELECT(FBZCOLORPATH))
	{
		default:    /* reserved */
		case 0:     /* 0 */
			blend_factor.zero_alpha();
			break;

		case 1:     /* a_local */
		case 3:     /* a_local */
			blend_factor.merge_alpha16(c_local);
			break;

		case 2:     /* a_other */
			blend_factor.merge_alpha16(c_other);
			break;

		case 4:     /* texture alpha */
			blend_factor.merge_alpha16(TEXELARGB);
			break;
	}

	/* reverse the RGB blend */
	if (!FBZCP_CC_REVERSE_BLEND(FBZCOLORPATH))
		blend_factor.xor_imm_rgba(0, 0xff, 0xff, 0xff);

	/* reverse the alpha blend */
	if (!FBZCP_CCA_REVERSE_BLEND(FBZCOLORPATH))
		blend_factor.xor_imm_rgba(0xff, 0, 0, 0);

	/* do the blend */
	//color.rgb.a = (color.rgb.a * (blenda + 1)) >> 8;
	//color.rgb.r = (color.rgb.r * (blendr + 1)) >> 8;
	//color.rgb.g = (color.rgb.g * (blendg + 1)) >> 8;
	//color.rgb.b = (color.rgb.b * (blendb + 1)) >> 8;

	/* add clocal or alocal to RGB */
	switch (FBZCP_CC_ADD_ACLOCAL(FBZCOLORPATH))
	{
		case 3:     /* reserved */
		case 0:     /* nothing */
			add_val.zero();
			break;

		case 1:     /* add c_local */
			add_val.set(c_local);
			break;

		case 2:     /* add_alocal */
			add_val.set(c_local.select_alpha32());
			break;
	}

	/* add clocal or alocal to alpha */
	if (!FBZCP_CCA_ADD_ACLOCAL(FBZCOLORPATH))
		add_val.zero_alpha();
	else
		//color.rgb.a += c_local.rgb.a;
		add_val.merge_alpha16(c_local);

	/* clamp */
	//CLAMP(color.rgb.a, 0x00, 0xff);
	//CLAMP(color.rgb.r, 0x00, 0xff);
	//CLAMP(color.rgb.g, 0x00, 0xff);
	//CLAMP(color.rgb.b, 0x00, 0xff);
	blend_factor.add_imm(1);
	blend_color.scale_add_and_clamp(blend_factor, add_val);

	/* invert */
	if (FBZCP_CCA_INVERT_OUTPUT(FBZCOLORPATH))
		blend_color.xor_imm_rgba(0xff, 0, 0, 0);
	/* invert */
	if (FBZCP_CC_INVERT_OUTPUT(FBZCOLORPATH))
		blend_color.xor_imm_rgba(0, 0xff, 0xff, 0xff);

	srcColor.set(blend_color);

	return true;
}



/*************************************
 *
 *  Rasterizer generator macro
 *
 *************************************/

#define RASTERIZER(name, TMUS, FBZCOLORPATH, FBZMODE, ALPHAMODE, FOGMODE, TEXMODE0, TEXMODE1) \
																				\
void voodoo_device::raster_##name(void *destbase, int32_t y, const poly_extent *extent, const void *extradata, int threadid) \
{                                                                               \
	const poly_extra_data *extra = (const poly_extra_data *)extradata;          \
	voodoo_device *vd = extra->device; \
	stats_block *stats = &vd->thread_stats[threadid];                            \
	DECLARE_DITHER_POINTERS;                                                    \
	int32_t startx = extent->startx;                                              \
	int32_t stopx = extent->stopx;                                                \
	rgbaint_t iterargb, iterargbDelta;                                           \
	int32_t iterz;                                                                \
	int64_t iterw;                                                                \
	tmu_state::stw_t iterstw0, iterstw1;                                                     \
	tmu_state::stw_t deltastw0, deltastw1;                                                   \
	uint16_t *depth;                                                              \
	uint16_t *dest;                                                               \
	int32_t dx, dy;                                                               \
	int32_t scry;                                                                 \
	int32_t x;                                                                    \
																				\
	/* determine the screen Y */                                                \
	scry = y;                                                                   \
	if (FBZMODE_Y_ORIGIN(FBZMODE))                                              \
		scry = (vd->fbi.yorigin - y);                                    \
																				\
	/* compute dithering */                                                     \
	COMPUTE_DITHER_POINTERS(FBZMODE, y, FOGMODE);                               \
																				\
	/* apply clipping */                                                        \
	if (FBZMODE_ENABLE_CLIPPING(FBZMODE))                                       \
	{                                                                           \
		int32_t tempclip;                                                         \
																				\
		/* Y clipping buys us the whole scanline */                             \
		if (scry < ((vd->reg[clipLowYHighY].u >> 16) & 0x3ff) ||                 \
			scry >= (vd->reg[clipLowYHighY].u & 0x3ff))                          \
		{                                                                       \
			stats->pixels_in += stopx - startx;                                 \
			stats->clip_fail += stopx - startx;                                 \
			return;                                                             \
		}                                                                       \
																				\
		/* X clipping */                                                        \
		tempclip = vd->reg[clipLeftRight].u & 0x3ff;                             \
		/* Check for start outsize of clipping boundary */                        \
		if (startx >= tempclip)                                                  \
		{                                                                       \
			stats->pixels_in += stopx - startx;                               \
			vd->stats.total_clipped += stopx - startx;                         \
			return;                                               \
		}                                                                       \
		if (stopx > tempclip)                                                  \
		{                                                                       \
			stats->pixels_in += stopx - tempclip;                               \
			vd->stats.total_clipped += stopx - tempclip;                         \
			stopx = tempclip;                                               \
		}                                                                       \
		tempclip = (vd->reg[clipLeftRight].u >> 16) & 0x3ff;                     \
		if (startx < tempclip)                                                  \
		{                                                                       \
			stats->pixels_in += tempclip - startx;                              \
			vd->stats.total_clipped += tempclip - startx;                        \
			startx = tempclip;                                                  \
		}                                                                       \
	}                                                                           \
																				\
	/* get pointers to the target buffer and depth buffer */                    \
	dest = (uint16_t *)destbase + scry * vd->fbi.rowpixels;                        \
	depth = (vd->fbi.auxoffs != ~0) ? ((uint16_t *)(vd->fbi.ram + vd->fbi.auxoffs) + scry * vd->fbi.rowpixels) : nullptr; \
																				\
	/* compute the starting parameters */                                       \
	dx = startx - (extra->ax >> 4);                                             \
	dy = y - (extra->ay >> 4);                                                  \
	int32_t iterr = extra->startr + dy * extra->drdy + dx * extra->drdx;                \
	int32_t iterg = extra->startg + dy * extra->dgdy + dx * extra->dgdx;                \
	int32_t iterb = extra->startb + dy * extra->dbdy + dx * extra->dbdx;                \
	int32_t itera = extra->starta + dy * extra->dady + dx * extra->dadx;                \
	iterargb.set(itera, iterr, iterg, iterb); \
	iterargbDelta.set(extra->dadx, extra->drdx, extra->dgdx, extra->dbdx); \
	iterz = extra->startz + dy * extra->dzdy + dx * extra->dzdx;                \
	iterw = extra->startw + dy * extra->dwdy + dx * extra->dwdx;                \
	if (TMUS >= 1)                                                              \
	{                                                                           \
		iterstw0.set(                                                           \
		extra->starts0 + dy * extra->ds0dy + dx * extra->ds0dx,        \
		extra->startt0 + dy * extra->dt0dy + dx * extra->dt0dx,        \
		extra->startw0 + dy * extra->dw0dy +   dx * extra->dw0dx);     \
		deltastw0.set(extra->ds0dx, extra->dt0dx, extra->dw0dx);       \
	}                                                                           \
	if (TMUS >= 2)                                                              \
	{                                                                           \
		iterstw1.set(                                                           \
		extra->starts1 + dy * extra->ds1dy + dx * extra->ds1dx,        \
		extra->startt1 + dy * extra->dt1dy + dx * extra->dt1dx,        \
		extra->startw1 + dy * extra->dw1dy + dx * extra->dw1dx);       \
		deltastw1.set(extra->ds1dx, extra->dt1dx, extra->dw1dx);       \
	}                                                                           \
	extra->info->hits++;                                                        \
	/* loop in X */                                                             \
	for (x = startx; x < stopx; x++)                                            \
	{                                                                           \
		rgbaint_t texel(0);                                                \
		rgbaint_t color, preFog;                                                \
																				\
		/* pixel pipeline part 1 handles depth setup and stippling */         \
		PIXEL_PIPELINE_BEGIN(vd, stats, x, y, FBZCOLORPATH, FBZMODE, iterz, iterw); \
		/* depth testing */         \
		if (FBZMODE_ENABLE_DEPTHBUF(FBZMODE))                                                  \
			if (!depthTest((uint16_t) vd->reg[zaColor].u, stats, depth[x], FBZMODE, biasdepth)) \
				goto skipdrawdepth; \
																				\
		/* run the texture pipeline on TMU1 to produce a value in texel */      \
		/* note that they set LOD min to 8 to "disable" a TMU */                \
		if (TMUS >= 2 && vd->tmu[1].lodmin < (8 << 8))                    {       \
			int32_t tmp; \
			const rgbaint_t texelZero(0);  \
			texel = vd->tmu[1].genTexture(x, dither4, TEXMODE1, vd->tmu[1].lookup, extra->lodbase1, \
														iterstw1, tmp); \
			texel = vd->tmu[1].combineTexture(TEXMODE1, texel, texelZero, tmp); \
		} \
		/* run the texture pipeline on TMU0 to produce a final */               \
		/* result in texel */                                                   \
		/* note that they set LOD min to 8 to "disable" a TMU */                \
		if (TMUS >= 1 && vd->tmu[0].lodmin < (8 << 8))                           \
		{                                                                   \
			if (!vd->send_config)                                                \
			{                                                                   \
				int32_t lod0; \
				rgbaint_t texelT0;                                                \
				texelT0 = vd->tmu[0].genTexture(x, dither4, TEXMODE0, vd->tmu[0].lookup, extra->lodbase0, \
																iterstw0, lod0); \
				texel = vd->tmu[0].combineTexture(TEXMODE0, texelT0, texel, lod0); \
			}                                                                   \
			else                                                                \
			{                                                                   \
				texel.set(vd->tmu_config);                                              \
			}                                                                   \
		}                                                                   \
																				\
		/* colorpath pipeline selects source colors and does blending */        \
		color = clampARGB(iterargb, FBZCOLORPATH);                                      \
		if (!combineColor(vd, stats, FBZCOLORPATH, FBZMODE, texel, iterz, iterw, color)) \
			goto skipdrawdepth;                                                          \
		/* handle alpha test */                                                          \
		if (ALPHAMODE_ALPHATEST(ALPHAMODE))                                              \
			if (!alphaTest(vd->reg[alphaMode].rgb.a, stats, ALPHAMODE, color.get_a()))   \
				goto skipdrawdepth;                                                      \
																						 \
		/* perform fogging */                                                            \
		preFog.set(color);                                                               \
		if (FOGMODE_ENABLE_FOG(FOGMODE))                                                                         \
			applyFogging(vd, FBZMODE, FOGMODE, FBZCOLORPATH, x, dither4, wfloat, color, iterz, iterw, iterargb); \
																												 \
		/* perform alpha blending */                                                \
		if (ALPHAMODE_ALPHABLEND(ALPHAMODE))                                                            \
			alphaBlend(FBZMODE, ALPHAMODE, x, dither, dest[x], depth, preFog, color, vd->fbi.rgb565); \
																				\
		/* pixel pipeline part 2 handles final output */        \
		PIXEL_PIPELINE_END(stats, dither_lookup, x, dest, depth, FBZMODE);  \
																				\
		/* update the iterated parameters */                                    \
		iterargb += iterargbDelta;                                              \
		iterz += extra->dzdx;                                                   \
		iterw += extra->dwdx;                                                   \
		if (TMUS >= 1)                                                          \
		{                                                                       \
			iterstw0.add(deltastw0);                                            \
		}                                                                       \
		if (TMUS >= 2)                                                          \
		{                                                                       \
			iterstw1.add(deltastw1);                                            \
		}                                                                       \
	}                                                                           \
}


// ******************************************************************************************************************************
// Computes a log2 of a 16.32 value to 2 fractional bits of precision.
// The return value is coded as a 24.8 value.
// The maximum error using a 4 bit lookup from the mantissa is 0.0875, which is less than 1/2 lsb (0.125) for 2 bits of fraction.
// An offset of  +(56 << 8) is added for alignment in multi_reciplog
// ******************************************************************************************************************************
inline int32_t ATTR_FORCE_INLINE voodoo_device::tmu_state::new_log2(double &value, const int &offset)
{
	static const int32_t new_log2_table[16] = {0, 22, 44, 63, 82, 100, 118, 134, 150, 165, 179, 193, 207, 220, 232, 244};
	uint64_t ival = *((uint64_t *)&value);
	// Return 0 if negative
	if (ival & ((uint64_t)1 << 63))
		return 0;
	// We zero the result if negative so don't worry about the sign bit
	int32_t exp = (ival>>52);
	exp -= 1023+32-offset;
	exp <<= 8;
	uint32_t addr = (uint64_t)(ival>>48) & 0xf;
	exp += new_log2_table[addr];
	return exp;
}

inline rgbaint_t ATTR_FORCE_INLINE voodoo_device::tmu_state::genTexture(int32_t x, const uint8_t *dither4, const uint32_t TEXMODE, rgb_t *LOOKUP, int32_t LODBASE, const stw_t &iterstw, int32_t &lod)
{
	rgbaint_t result;
	int32_t s, t, ilod;

	/* determine the S/T/LOD values for this texture */
	lod = (LODBASE);
	if (TEXMODE_ENABLE_PERSPECTIVE(TEXMODE))
	{
		int32_t wLog;
		iterstw.calc_stow(s, t, wLog);
		lod += wLog;
	}
	else
	{
		iterstw.get_st_shiftr(s, t, (14 + 10));
	}

	/* clamp W */
	if (TEXMODE_CLAMP_NEG_W(TEXMODE) && iterstw.is_w_neg())
	{
		s = t = 0;
	}

	/* clamp the LOD */
	lod += lodbias;
	if (TEXMODE_ENABLE_LOD_DITHER(TEXMODE))
		lod += dither4[x&3] << 4;
	CLAMP(lod, lodmin, lodmax);

	/* now the LOD is in range; if we don't own this LOD, take the next one */
	ilod = lod >> 8;
	if (!((lodmask >> ilod) & 1))
		ilod++;

	/* fetch the texture base */
	uint32_t texbase = lodoffset[ilod];

	/* compute the maximum s and t values at this LOD */
	int32_t smax = wmask >> ilod;
	int32_t tmax = hmask >> ilod;

	/* determine whether we are point-sampled or bilinear */
	if ((lod == lodmin && !TEXMODE_MAGNIFICATION_FILTER(TEXMODE)) ||
		(lod != lodmin && !TEXMODE_MINIFICATION_FILTER(TEXMODE)))
	{
		/* point sampled */

		uint32_t texel0;

		/* adjust S/T for the LOD and strip off the fractions */
		s >>= ilod + (18-10);
		t >>= ilod + (18-10);

		/* clamp/wrap S/T if necessary */
		if (TEXMODE_CLAMP_S(TEXMODE))
			CLAMP(s, 0, smax);
		if (TEXMODE_CLAMP_T(TEXMODE))
			CLAMP(t, 0, tmax);
		s &= smax;
		t &= tmax;
		t *= smax + 1;

		/* fetch texel data */
		if (TEXMODE_FORMAT(TEXMODE) < 8)
		{
			texel0 = *(uint8_t *)&ram[(texbase + t + s) & mask];
			result.set((LOOKUP)[texel0]);
		}
		else
		{
			texel0 = *(uint16_t *)&ram[(texbase + 2*(t + s)) & mask];
			if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12)
				result.set((LOOKUP)[texel0]);
			else
				result.set(((LOOKUP)[texel0 & 0xff] & 0xffffff) | ((texel0 & 0xff00) << 16));
		}
	}
	else
	{
		/* bilinear filtered */

		uint32_t texel0, texel1, texel2, texel3;
		uint32_t sfrac, tfrac;
		int32_t s1, t1;

		/* adjust S/T for the LOD and strip off all but the low 8 bits of */
		/* the fraction */
		s >>= ilod; // + (10-10);
		t >>= ilod; // + (10-10);

		/* also subtract 1/2 texel so that (0.5,0.5) = a full (0,0) texel */
		s -= 0x80;
		t -= 0x80;

		/* extract the fractions */
		sfrac = s & bilinear_mask;
		tfrac = t & bilinear_mask;

		/* now toss the rest */
		s >>= 8;
		t >>= 8;
		s1 = s + 1;
		t1 = t + 1;

		/* clamp/wrap S/T if necessary */
		if (TEXMODE_CLAMP_S(TEXMODE))
		{
			if (s < 0) {
				s = 0;
				s1 = 0;
			} else if (s >= smax) {
				s = smax;
				s1 = smax;
			}
			//CLAMP(s, 0, smax);
			//CLAMP(s1, 0, smax);
		} else {
			s &= smax;
			s1 &= smax;
		}

		if (TEXMODE_CLAMP_T(TEXMODE))
		{
			if (t < 0) {
				t = 0;
				t1 = 0;
			} else if (t >= tmax) {
				t = tmax;
				t1 = tmax;
			}
			//CLAMP(t, 0, tmax);
			//CLAMP(t1, 0, tmax);
		} else {
			t &= tmax;
			t1 &= tmax;
		}
		t *= smax + 1;
		t1 *= smax + 1;

		/* fetch texel data */
		if (TEXMODE_FORMAT(TEXMODE) < 8)
		{
			texel0 = *(uint8_t *)&ram[(texbase + t + s) & mask];
			texel1 = *(uint8_t *)&ram[(texbase + t + s1) & mask];
			texel2 = *(uint8_t *)&ram[(texbase + t1 + s) & mask];
			texel3 = *(uint8_t *)&ram[(texbase + t1 + s1) & mask];
			texel0 = (LOOKUP)[texel0];
			texel1 = (LOOKUP)[texel1];
			texel2 = (LOOKUP)[texel2];
			texel3 = (LOOKUP)[texel3];
		}
		else
		{
			texel0 = *(uint16_t *)&ram[(texbase + 2*(t + s)) & mask];
			texel1 = *(uint16_t *)&ram[(texbase + 2*(t + s1)) & mask];
			texel2 = *(uint16_t *)&ram[(texbase + 2*(t1 + s)) & mask];
			texel3 = *(uint16_t *)&ram[(texbase + 2*(t1 + s1)) & mask];
			if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12)
			{
				texel0 = (LOOKUP)[texel0];
				texel1 = (LOOKUP)[texel1];
				texel2 = (LOOKUP)[texel2];
				texel3 = (LOOKUP)[texel3];
			}
			else
			{
				texel0 = ((LOOKUP)[texel0 & 0xff] & 0xffffff) | ((texel0 & 0xff00) << 16);
				texel1 = ((LOOKUP)[texel1 & 0xff] & 0xffffff) | ((texel1 & 0xff00) << 16);
				texel2 = ((LOOKUP)[texel2 & 0xff] & 0xffffff) | ((texel2 & 0xff00) << 16);
				texel3 = ((LOOKUP)[texel3 & 0xff] & 0xffffff) | ((texel3 & 0xff00) << 16);
			}
		}

		/* weigh in each texel */

		result.bilinear_filter_rgbaint(texel0, texel1, texel2, texel3, sfrac, tfrac);
	}
	return result;
}

inline rgbaint_t ATTR_FORCE_INLINE voodoo_device::tmu_state::combineTexture(const uint32_t TEXMODE, const rgbaint_t& c_local, const rgbaint_t& c_other, int32_t lod)
{
	rgbaint_t blend_color, blend_factor;
	rgbaint_t add_val;

	/* select zero/other for RGB */
	if (TEXMODE_TC_ZERO_OTHER(TEXMODE))
		blend_color.zero();
	else
		blend_color.set(c_other);

	/* select zero/other for alpha */
	if (TEXMODE_TCA_ZERO_OTHER(TEXMODE))
		blend_color.zero_alpha();
	else
		blend_color.merge_alpha16(c_other);

	if (TEXMODE_TC_SUB_CLOCAL(TEXMODE) || TEXMODE_TCA_SUB_CLOCAL(TEXMODE))
	{
		rgbaint_t sub_val;

		/* potentially subtract c_local */
		if (!TEXMODE_TC_SUB_CLOCAL(TEXMODE))
			sub_val.zero();
		else
			sub_val.set(c_local);

		if (!TEXMODE_TCA_SUB_CLOCAL(TEXMODE))
			sub_val.zero_alpha();
		else
			sub_val.merge_alpha16(c_local);

		blend_color.sub(sub_val);
	}

	/* blend RGB */
	switch (TEXMODE_TC_MSELECT(TEXMODE))
	{
		default:    /* reserved */
		case 0:     /* zero */
			blend_factor.zero();
			break;

		case 1:     /* c_local */
			blend_factor.set(c_local);
			break;

		case 2:     /* a_other */
			blend_factor.set(c_other.select_alpha32());
			break;

		case 3:     /* a_local */
			blend_factor.set(c_local.select_alpha32());
			break;

		case 4:     /* LOD (detail factor) */
			if (detailbias <= lod)
				blend_factor.zero();
			else
			{
				uint8_t tmp;
				tmp = (((detailbias - lod) << detailscale) >> 8);
				if (tmp > detailmax)
					tmp = detailmax;
				blend_factor.set_all(tmp);
			}
			break;

		case 5:     /* LOD fraction */
			blend_factor.set_all(lod & 0xff);
			break;
	}

	/* blend alpha */
	switch (TEXMODE_TCA_MSELECT(TEXMODE))
	{
		default:    /* reserved */
		case 0:     /* zero */
			blend_factor.zero_alpha();
			break;

		case 1:     /* c_local */
			blend_factor.merge_alpha16(c_local);
			break;

		case 2:     /* a_other */
			blend_factor.merge_alpha16(c_other);
			break;

		case 3:     /* a_local */
			blend_factor.merge_alpha16(c_local);
			break;

		case 4:     /* LOD (detail factor) */
			if (detailbias <= lod)
				blend_factor.zero_alpha();
			else
			{
				uint8_t tmp;
				tmp = (((detailbias - lod) << detailscale) >> 8);
				if (tmp > detailmax)
					tmp = detailmax;
				blend_factor.set_a16(tmp);
			}
			break;

		case 5:     /* LOD fraction */
			blend_factor.set_a16(lod & 0xff);
			break;
	}

	/* reverse the RGB blend */
	if (!TEXMODE_TC_REVERSE_BLEND(TEXMODE))
		blend_factor.xor_imm_rgba(0, 0xff, 0xff, 0xff);

	/* reverse the alpha blend */
	if (!TEXMODE_TCA_REVERSE_BLEND(TEXMODE))
		blend_factor.xor_imm_rgba(0xff, 0, 0, 0);

	/* do the blend */
	//tr = (tr * (blendr + 1)) >> 8;
	//tg = (tg * (blendg + 1)) >> 8;
	//tb = (tb * (blendb + 1)) >> 8;
	//ta = (ta * (blenda + 1)) >> 8;

	/* add clocal or alocal to RGB */
	switch (TEXMODE_TC_ADD_ACLOCAL(TEXMODE))
	{
		case 3:     /* reserved */
		case 0:     /* nothing */
			add_val.zero();
			break;

		case 1:     /* add c_local */
			add_val.set(c_local);
			break;

		case 2:     /* add_alocal */
			add_val.set(c_local.select_alpha32());
			break;
	}

	/* add clocal or alocal to alpha */
	if (!TEXMODE_TCA_ADD_ACLOCAL(TEXMODE))
		add_val.zero_alpha();
	else
		add_val.merge_alpha16(c_local);

	/* clamp */
	//result.rgb.r = (tr < 0) ? 0 : (tr > 0xff) ? 0xff : tr;
	//result.rgb.g = (tg < 0) ? 0 : (tg > 0xff) ? 0xff : tg;
	//result.rgb.b = (tb < 0) ? 0 : (tb > 0xff) ? 0xff : tb;
	//result.rgb.a = (ta < 0) ? 0 : (ta > 0xff) ? 0xff : ta;
	blend_factor.add_imm(1);
	blend_color.scale_add_and_clamp(blend_factor, add_val);

	/* invert */
	if (TEXMODE_TC_INVERT_OUTPUT(TEXMODE))
		blend_color.xor_imm_rgba(0, 0xff, 0xff, 0xff);
	if (TEXMODE_TCA_INVERT_OUTPUT(TEXMODE))
		blend_color.xor_imm_rgba(0xff, 0, 0, 0);
	return blend_color;
}

#endif // MAME_VIDEO_VOODDEFS_IPP