summaryrefslogblamecommitdiffstatshomepage
path: root/src/osd/windows/d3dhlsl.c
blob: 06f9894a026b678caaac1655748f601272e407ce (plain) (tree)
1
2
3
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347

                                                              
                                                  
































































                                                              
                   















                                                              

                                       
                                                                                                                                              

                                                                         















                                                   
                                                                                    
          
                                                                                                                                             

                                                                         















                                                   
                                                                                    
          
                                                                                                                                             

                                                                         















                                                   
                                                                                    
          
                                                                                                                                                                           

                                                                         















                                                   
                                                                                    
          









                                                              
                                                                                  
                                                                                                              









                                                              
                             

                            

                             
                    
                              
                       

                      

                          
                            









                                                              
                             





































































                                                                                                                                                                              
                                                                                                              
         
                                                                     





                                                                                                           






                                                                                               





                                                           

                                                                               

                                                   
                                        
























                                                                                                                         
                                                                                                                
         
                                                                   





                                                                                                           






                                                                                               











                                                                           

                                                                                                          

                                                                       
                                                        




                                                                                                                                                     
                                                                                   



                                                                    
                                                                                        





                                                                                                                            
                                                                                                    






























































                                                                                                                         
                                                                                     













                                                              
















                                                              










                                                              
                                               




                                 





                                                              



                                                       

                 


                                                              













































                                                                                                                                                                                                         
                                                                          


























                                                                                                
                                                            








                                                              
                                                    






















                                                               










                                                                                                   
 

                                                           
















                                                      
                                                                                                     

                                  
                                                   
                 





                                                    
                                


                                                                              


         
 
                                                              









                                                              



                                                             



                                      



                                                         

         
                                                                                                                                        
                                










                                                                                                                                                           
                                                                



                                        

                                           



                                                                                                   

                            
                                                                                            



                                      


                                                                                                 

                             
 
                                                                                               
 
                                                                  
 

                                                                                                                                              
 

                                                                                              
 
                    
         

                                                                                                                                                                         
 

                                          
                 

                                                    
                         

                                                           
 




                                                                     
 

                                                                                       
 

                                                                                       
 

                                                                         
 

                                                                                 
 

                                                                                   
 

                                                                                                   
 

                                                                                                      
 

                                                                                                       
 

                                                                                                       
 

                                                                                                    
 

                                                                                                    
 

                                                                                   
 

                                                                                     
 

                                                                                             
 

                                                                                            
 

                                                                                               
 

                                                                                                           
 

                                                                                                             
 

                                                                                               
 


                                                                                                              
 


                                                                                                                                                
 


                                                                                                                                                
 


                                                                                                                                                                            
 


                                                                                                                                                                            
 


                                                                                                                                            
 


                                                                                                                                            
 


                                                                                                                                            
 

                                                                                     
 


                                                                                                                                
 


                                                                                                                            
 


                                                                                                                            
 


                                                                                                                            
 


                                                                                                                                             
 


                                                                    
 

                                                                             
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                                           
 

                                                                                               











                                                                                       
                         

                 
            
         



































                                                                                                               
 











                                                                               



                                                                               
         
 








                                                                                 
 





                                                              



















































                                                                                                 


 
 





                                                              


                                                          

                                                     

















                                                                                                                                                                               






























                                                                                                                                                                                   

                                                                                                           
 

                                                                    


                                                                   
                                  


                                                             
                                      


                                                                     
                                        


                                                                         
                                      


                                                                     
                                   


                                                               
                                        


                                                                         
                                   


                                                               
                                        


                                                                         
                                        






                                                                                      
                                                                             






                                                                                        
                                                                          






                                                                                                
                                                                              






                                                                                                    
                                                                                






                                                                                                
                                                                              






                                                                                          
                                                                           






                                                                                                    
                                                                                






                                                                                          
                                                                           






                                                                                                    
                                                                                






                                                                                                    
                                                                                


                         

                                   




























                                                                                                










                                                                                            




















                                          

                           




                                                              
                         

                                                              
                            



















                                                                                                                              



                                                              





































































































































































                                                                                                                                      
                               


















                                                                                         
 
                                                                                                                                               
 





                                                                                                                                        

                                                                                               


















                                                                                                                                                    
                                                                                                                                                         

                                                                                               










                                                                              






                                                                        





















                                                                                                                                                                                    











                                                              
                                                                                          


                                           
                                                                                                                      








                                                              










                                                              

                                                                                    




                                                                          
                                                                                                                                        
 
                                       



                                                         

















                                                                                                                                                                                 
 
                                                                                                             










                                                                                                                                              
                                                                                                                  








                                                                                                                                                   
                                                                                                 
                                                                                                           


















                                                                                                                                                                                 
 
                                                                                                     










                                                                                                                                              
                                                                                                                  







                                                                                                                                                   
                                                                                               




                                                               















                                                                                                                                                                       
 
                                                                                                       










                                                                                                                                      
                                                                                                          







                                                                                                                                           
                                                                                         
 








                                                                                                                                        


                                                                      
                                                                                                  







                                                                                                                                      
                                                                                                          





                                                                                                                                           

                                                
                                                                                            
 












                                                                                                                                        


                                                                      
                                                                                             







                                                                                                                                        
                                                                                                          





                                                                                                                                           

                                                      





                                                                           
                                                                                               


                                                                                                      



                                                                                                                                                                         
                                                                                                       


                                                                              
                                                                                                     







                                                                                                                                                
                                                                                                                  







                                                                                                                                                   
                                                                                               


                                                                                                      



                                                                                                                
                                                                                                       


                                                                              
                                                                                                     





                                                                                                                                                
                                                                                                                  











                                                                                                                                                   



                                                                                                      



                                                                                                                                        

                                                                                                     

                                                                                                     
                                                                               
 

                                                                                                                       
 
                                                                                             









                                                                                                                                        
                                                                                                          








                                                                                                                                           

                                                                                        
                                                                               
 
                                                                                                                                              









                                                                                                                                        
                                                                                                          





                                                                                                                                           



                                                                                      


                                                                           
                                                                                               









                                                                                                                                              
                                                                                                                          








                                                                                                                                                   
                                                                                               
 








                                                                                                                                              
                                                                                                                          








                                                                                                                                                   

                                       
 
                                                                               
 

                                                                                              













                                                                                                                              
                                                                                                      












































































































































































































































































































                                                                                                                                                         






                                                                         
                                                                                                          





                                                                                                                                           
                               
 
                                                                                         
                                                                                      









                                                                                                                              


























                                                                                                                                



                                   
      

            



                                                                                                                                                                 


                                                                                              
                                                                                                   


















                                                                                                                                           
                       

                                                              
                          



                                                          
                                                



                                                              
                                         

                                                              
                                                                     
 
                                                                                                                        
 
 
 


                                                              
                                                                                                                                              

                                                                                           
 
                                                                                    



                                    
 









                                                      
 

                                 
 
                                            
 




                                         
 

                    
 
                                                 






                             

                                                     




                                                                 
                                                            

               

                                                                               





                                      



                                                              
                                                                                                                                         
 


                                
         

                                                                              
                 
                                                              
                 
 



                                                                         







                                                                                                       
 

                                                                                              
                                                                                    




                                    









                                                      
 






                                                                                                                              


                                            
                                                                                                         

                          
                                                                                                            




                                            










                                          


                                                              



                                                              

                                                                     

 
 
                                                              


                                                              
                                                           
 


                                                                                      
 





                                                                                                          


                                                          

                            

                                                     

                                               
 



                                                                        
                                                                      








                                          
                                                                        





                                          


                                                                         

                                                                                                                


                                     
                    





                                                              
                                            



                                                          

                            
                               


                                                                                                                                                                          
 

                                          
 













































                                                                                                                                                              



                                                                                 
         
 




                                                 











                                                      


















































                                                              





                                                   























                                                               
                              


 




























                                                                                                        











































                                                                                                                                                                       
                                     







                                                                                                           
                                     




                                                                                                         
                                                  




                                                                                                              
                                                  




                                                                                                              
                                                  




                                                                                                  
                                                  




                                                                                                      
                                                  




                                                                                                      
                                                  




                                                                                                       
                                                  




                                                                                                             
                                                  




                                                                                                              
                                                  




                                                                                                           
                                                  




                                                                                                    
                                                  
                                                                                              



                                                                                                 
                                                  




                                                                                                      
                                                  




                                                                                                      
                                                  
                                                                                              



                                                                                                      
                                                  
                                                                                                 



                                                                                                      
                                                  
                                                                                                 



                                                                                                        
                                                  
                                                                                                 



                                                                                                        
                                                  
                                                                                                 



                                                                                                       
                                                  
                                                                                                 



                                                                                                       
                                                  
                                                                                                 



                                                                                                             
                                                  
                                                                                                        



                                                                                                             
                                                  
                                                                                                        



                                                                                                               
                                                  
                                                                                                        



                                                                                                               
                                                  
                                                                                                        



                                                                                                              
                                                  
                                                                                                        



                                                                                                              
                                                  
                                                                                                        



                                                                                                  
                                                  
                                                                                                  



                                                                                                  
                                                  
                                                                                                  



                                                                                                  
                                                  
                                                                                                  



                                                                                                    
                                                  
                                                                                                  



                                                                                                    
                                                  
                                                                                                  



                                                                                                    
                                                  
                                                                                                  



                                                                                                   
                                                  
                                                                                                  



                                                                                                   
                                                  
                                                                                                  



                                                                                                   
                                                  
                                                                                                  



                                                                                                  
                                                  
                                                                                              



                                                                                                    
                                                  
                                                                                              



                                                                                                   
                                                  
                                                                                              



                                                                                                 
                                                  
                                                                                             



                                                                                                   
                                                  
                                                                                             



                                                                                                  
                                                  
                                                                                             



                                                                                                 
                                                  
                                                                                             



                                                                                                   
                                                  
                                                                                             



                                                                                                  
                                                  
                                                                                             



                                                                                                 
                                                  
                                                                                             



                                                                                                   
                                                  
                                                                                             



                                                                                                  
                                                  
                                                                                             



                                                                                                         
                                                  
                                                                                                



                                                                                                           
                                                  
                                                                                                



                                                                                                          
                                                  
                                                                                                



                                                                                                  
                                                  














                                                                                               



                                           














                                                                                                                                                                              

                                                                                                                                                          




































                                                                                                                                                                          





















                                                                                                                            
                                                                                                             



                                            
                                                                                            






































                                                                                   
                                                                                    





                                                                               

                                                                                                      





























































                                                                                                        
                                
 
//============================================================
//
//  d3dhlsl.c - Win32 Direct3D HLSL implementation
//
//============================================================
//
//  Copyright Aaron Giles
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or
//  without modification, are permitted provided that the
//  following conditions are met:
//
//    * Redistributions of source code must retain the above
//      copyright notice, this list of conditions and the
//      following disclaimer.
//    * Redistributions in binary form must reproduce the
//      above copyright notice, this list of conditions and
//      the following disclaimer in the documentation and/or
//      other materials provided with the distribution.
//    * Neither the name 'MAME' nor the names of its
//      contributors may be used to endorse or promote
//      products derived from this software without specific
//      prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND
//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
//  EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
//  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//  DAMAGE (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
//  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//============================================================

// Useful info:
//  Windows XP/2003 shipped with DirectX 8.1
//  Windows 2000 shipped with DirectX 7a
//  Windows 98SE shipped with DirectX 6.1a
//  Windows 98 shipped with DirectX 5
//  Windows NT shipped with DirectX 3.0a
//  Windows 95 shipped with DirectX 2

// standard windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include <mmsystem.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <math.h>
#undef interface

// MAME headers
#include "emu.h"
#include "render.h"
#include "ui.h"
#include "rendutil.h"
#include "options.h"
#include "emuopts.h"
#include "aviio.h"
#include "png.h"
#include "screen.h"

// MAMEOS headers
#include "d3dintf.h"
#include "winmain.h"
#include "window.h"
#include "config.h"
#include "strconv.h"
#include "d3dcomm.h"
#include "drawd3d.h"



//============================================================
//  GLOBALS
//============================================================

static hlsl_options g_hlsl_presets[4] =
{
	{   // 25% Shadow mask, 50% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation
		true,
		0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f,
		0.03f, 0.03f,
		0.5f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f,
		{ 0.0f, 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 1.0f, 0.0f, 0.0f },
		{ 0.0f, 1.0f, 0.0f },
		{ 0.0f, 0.0f, 1.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 1.0f, 1.0f, 1.0f },
		{ 0.9f, 0.9f, 0.9f },
		{ 0.05f,0.05f,0.05f},
		{ 0.25f,0.25f,0.25f},
		1.2f,
		false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0
	},
	{   // 25% Shadow mask, 0% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation
		true,
		0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f,
		0.03f, 0.03f,
		0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f,
		{ 0.0f, 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 1.0f, 0.0f, 0.0f },
		{ 0.0f, 1.0f, 0.0f },
		{ 0.0f, 0.0f, 1.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 1.0f, 1.0f, 1.0f },
		{ 0.9f, 0.9f, 0.9f },
		{ 0.05f,0.05f,0.05f},
		{ 0.25f,0.25f,0.25f},
		1.2f,
		false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0
	},
	{   // 25% Shadow mask, 0% Scanlines, 0% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation
		true,
		0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f,
		0.0f, 0.0f,
		0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f,
		{ 0.0f, 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 1.0f, 0.0f, 0.0f },
		{ 0.0f, 1.0f, 0.0f },
		{ 0.0f, 0.0f, 1.0f },
		{ 0.0f, 0.0f, 0.0f },
		{ 1.0f, 1.0f, 1.0f },
		{ 0.9f, 0.9f, 0.9f },
		{ 0.05f,0.05f,0.05f},
		{ 0.25f,0.25f,0.25f},
		1.2f,
		false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0
	},
	{   // 25% Shadow mask, 100% Scanlines, 15% Pincushion, 3 defocus, 24-degree Tint Out, 1.5 Exponent, 5% Floor, 70% Phosphor Return, 80% Saturation, Bad Convergence
		true,
		0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f,
		0.15f, 0.15f,
		1.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f,
		{ 3.0f, 3.0f, 3.0f, 3.0f },
		{ 0.5f,-0.33f,0.7f },
		{ 0.0f,-1.0f, 0.5f },
		{ 0.0f, 0.2f, 0.3f },
		{ 0.0f, 0.2f, 0.0f },
		{ 0.8f, 0.2f, 0.0f },
		{ 0.0f, 0.8f, 0.2f},
		{ 0.2f, 0.0f, 0.8f},
		{ 0.0f, 0.0f, 0.0f },
		{ 1.0f, 1.0f, 1.0f },
		{ 1.5f, 1.5f, 1.5f },
		{ 0.05f,0.05f,0.05f},
		{ 0.7f, 0.7f, 0.7f},
		0.8f,
		false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0
	},
};

static slider_state *g_slider_list;



//============================================================
//  PROTOTYPES
//============================================================

static void get_vector(const char *data, int count, float *out, int report_error);
static file_error open_next(d3d_info *d3d, emu_file &file, const char *templ, const char *extension, int idx);



//============================================================
//  hlsl_info constructor
//============================================================

hlsl_info::hlsl_info()
{
	master_enable = false;
	vector_enable = true;
	prescale_size_x = 1;
	prescale_size_y = 1;
	prescale_force_x = 0;
	prescale_force_y = 0;
	preset = -1;
	shadow_texture = NULL;
	options = NULL;
	paused = true;
	lastidx = -1;
	targethead = NULL;
	cachehead = NULL;
	initialized = false;
}



//============================================================
//  hlsl_info destructor
//============================================================

hlsl_info::~hlsl_info()
{
	global_free(options);
}



//============================================================
//  hlsl_info::window_save
//============================================================

void hlsl_info::window_save()
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_info *d3d = (d3d_info *)window->drawdata;

	HRESULT result = (*d3dintf->device.create_texture)(d3d->device, snap_width, snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &snap_copy_texture);
	if (result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to init system-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result);
		return;
	}
	(*d3dintf->texture.get_surface_level)(snap_copy_texture, 0, &snap_copy_target);

	result = (*d3dintf->device.create_texture)(d3d->device, snap_width, snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &snap_texture);
	if (result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to init video-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result);
		return;
	}
	(*d3dintf->texture.get_surface_level)(snap_texture, 0, &snap_target);

	render_snap = true;
	snap_rendered = false;
}



//============================================================
//  hlsl_info::window_record
//============================================================

void hlsl_info::window_record()
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	windows_options &options = downcast<windows_options &>(window->machine().options());
	const char *filename = options.d3d_hlsl_write();

	if (avi_output_file != NULL)
		end_avi_recording();
	else if (filename[0] != 0)
		begin_avi_recording(filename);
}


//============================================================
//  hlsl_info::avi_update_snap
//============================================================

void hlsl_info::avi_update_snap(d3d_surface *surface)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_info *d3d = (d3d_info *)window->drawdata;

	D3DLOCKED_RECT rect;

	// if we don't have a bitmap, or if it's not the right size, allocate a new one
	if (!avi_snap.valid() || (int)snap_width != avi_snap.width() || (int)snap_height != avi_snap.height())
	{
		avi_snap.allocate((int)snap_width, (int)snap_height);
	}

	// copy the texture
	HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->device, surface, avi_copy_surface);
	if (result != D3D_OK)
	{
		return;
	}

	// lock the texture
	result = (*d3dintf->surface.lock_rect)(avi_copy_surface, &rect, NULL, D3DLOCK_DISCARD);
	if (result != D3D_OK)
	{
		return;
	}

	// loop over Y
	for (int srcy = 0; srcy < (int)snap_height; srcy++)
	{
		DWORD *src = (DWORD *)((BYTE *)rect.pBits + srcy * rect.Pitch);
		UINT32 *dst = &avi_snap.pix32(srcy);

		for(int x = 0; x < snap_width; x++)
			*dst++ = *src++;
	}

	// unlock
	result = (*d3dintf->surface.unlock_rect)(avi_copy_surface);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result);
}



//============================================================
//  hlsl_render_snapshot
//============================================================

void hlsl_info::render_snapshot(d3d_surface *surface)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_info *d3d = (d3d_info *)window->drawdata;

	D3DLOCKED_RECT rect;

	render_snap = false;

	// if we don't have a bitmap, or if it's not the right size, allocate a new one
	if (!avi_snap.valid() || snap_width != (avi_snap.width() / 2) || snap_height != (avi_snap.height() / 2))
	{
		avi_snap.allocate(snap_width / 2, snap_height / 2);
	}

	// copy the texture
	HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->device, surface, snap_copy_target);
	if (result != D3D_OK)
	{
		return;
	}

	// lock the texture
	result = (*d3dintf->surface.lock_rect)(snap_copy_target, &rect, NULL, D3DLOCK_DISCARD);
	if (result != D3D_OK)
	{
		return;
	}

	for(int cy = 0; cy < 2; cy++)
	{
		for(int cx = 0; cx < 2; cx++)
		{
			// loop over Y
			for (int srcy = 0; srcy < snap_height / 2; srcy++)
			{
				int toty = (srcy + cy * (snap_height / 2));
				int totx = cx * (snap_width / 2);
				DWORD *src = (DWORD *)((BYTE *)rect.pBits + toty * rect.Pitch + totx * 4);
				UINT32 *dst = &avi_snap.pix32(srcy);

				for(int x = 0; x < snap_width / 2; x++)
					*dst++ = *src++;
			}

			int idx = cy * 2 + cx;

			emu_file file(window->machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
			file_error filerr = open_next(d3d, file, NULL, "png", idx);
			if (filerr != FILERR_NONE)
				return;

			// add two text entries describing the image
			astring text1(emulator_info::get_appname(), " ", build_version);
			astring text2(window->machine().system().manufacturer, " ", window->machine().system().description);
			png_info pnginfo = { 0 };
			png_add_text(&pnginfo, "Software", text1);
			png_add_text(&pnginfo, "System", text2);

			// now do the actual work
			png_error error = png_write_bitmap(file, &pnginfo, avi_snap, 1 << 24, NULL);
			if (error != PNGERR_NONE)
				mame_printf_error("Error generating PNG for HLSL snapshot: png_error = %d\n", error);

			// free any data allocated
			png_free(&pnginfo);
		}
	}

	// unlock
	result = (*d3dintf->surface.unlock_rect)(snap_copy_target);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result);

	if(snap_texture != NULL)
	{
		(*d3dintf->texture.release)(snap_texture);
		snap_texture = NULL;
	}

	if(snap_target != NULL)
	{
		(*d3dintf->surface.release)(snap_target);
		snap_target = NULL;
	}

	if(snap_copy_texture != NULL)
	{
		(*d3dintf->texture.release)(snap_copy_texture);
		snap_copy_texture = NULL;
	}

	if(snap_copy_target != NULL)
	{
		(*d3dintf->surface.release)(snap_copy_target);
		snap_copy_target = NULL;
	}
}


//============================================================
//  hlsl_info::record_texture
//============================================================

void hlsl_info::record_texture()
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_surface *surface = avi_final_target;

	// ignore if nothing to do
	if (avi_output_file == NULL || surface == NULL)
		return;

	// get the current time
	attotime curtime = window->machine().time();

	avi_update_snap(surface);

	// loop until we hit the right time
	while (avi_next_frame_time <= curtime)
	{
		// handle an AVI recording
		// write the next frame
		avi_error avierr = avi_append_video_frame(avi_output_file, avi_snap);
		if (avierr != AVIERR_NONE)
		{
			end_avi_recording();
			return;
		}

		// advance time
		avi_next_frame_time += avi_frame_period;
		avi_frame++;
	}
}


//============================================================
//  hlsl_info::end_hlsl_avi_recording
//============================================================

void hlsl_info::end_avi_recording()
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	if (avi_output_file != NULL)
		avi_close(avi_output_file);

	avi_output_file = NULL;
	avi_frame = 0;
}


//============================================================
//  hlsl_info::set_texture
//============================================================

void hlsl_info::toggle()
{
	if (master_enable)
	{
		if (initialized)
		{
			delete_resources(false);
		}
		master_enable = !master_enable;
	}
	else
	{
		if (!initialized)
		{
			master_enable = !master_enable;
			bool failed = create_resources(false);
			if (failed)
			{
				master_enable = false;
			}
		}
		else
		{
			master_enable = !master_enable;
		}
	}
}

//============================================================
//  hlsl_info::begin_avi_recording
//============================================================

void hlsl_info::begin_avi_recording(const char *name)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_info *d3d = (d3d_info *)window->drawdata;

	// stop any existing recording
	end_avi_recording();

	// reset the state
	avi_frame = 0;
	avi_next_frame_time = window->machine().time();

	// build up information about this new movie
	avi_movie_info info;
	info.video_format = 0;
	info.video_timescale = 1000 * ((window->machine().primary_screen != NULL) ? ATTOSECONDS_TO_HZ(window->machine().primary_screen->frame_period().attoseconds) : screen_device::DEFAULT_FRAME_RATE);
	info.video_sampletime = 1000;
	info.video_numsamples = 0;
	info.video_width = snap_width;
	info.video_height = snap_height;
	info.video_depth = 24;

	info.audio_format = 0;
	info.audio_timescale = window->machine().sample_rate();
	info.audio_sampletime = 1;
	info.audio_numsamples = 0;
	info.audio_channels = 2;
	info.audio_samplebits = 16;
	info.audio_samplerate = window->machine().sample_rate();

	// create a new temporary movie file
	file_error filerr;
	astring fullpath;
	{
		emu_file tempfile(window->machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
		if (name != NULL)
		{
			filerr = tempfile.open(name);
		}
		else
		{
			filerr = open_next(d3d, tempfile, NULL, "avi", 0);
		}

		// compute the frame time
		{
			avi_frame_period = attotime::from_seconds(1000) / info.video_timescale;
		}

		// if we succeeded, make a copy of the name and create the real file over top
		if (filerr == FILERR_NONE)
		{
			fullpath = tempfile.fullpath();
		}
	}

	if (filerr == FILERR_NONE)
	{
		// create the file and free the string
		avi_error avierr = avi_create(fullpath, &info, &avi_output_file);
		if (avierr != AVIERR_NONE)
		{
			mame_printf_error("Error creating AVI: %s\n", avi_error_string(avierr));
		}
	}
}


//============================================================
//  remove_cache_target - remove an active cache target when
//  refcount hits zero
//============================================================

void hlsl_info::remove_cache_target(d3d_cache_target *cache)
{
	if (cache != NULL)
	{
		if (cache == cachehead)
		{
			cachehead = cachehead->next;
		}

		if (cache->prev != NULL)
		{
			cache->prev->next = cache->next;
		}

		if (cache->next != NULL)
		{
			cache->next->prev = cache->prev;
		}

		global_free(cache);
	}
}


//============================================================
//  remove_render_target - remove an active target
//============================================================

void hlsl_info::remove_render_target(d3d_texture_info *texture)
{
	remove_render_target(find_render_target(texture));
}

void hlsl_info::remove_render_target(int width, int height, UINT32 screen_index, UINT32 page_index)
{
	d3d_render_target *target = find_render_target(width, height, screen_index, page_index);
	if (target != NULL)
	{
		remove_render_target(target);
	}
}

void hlsl_info::remove_render_target(d3d_render_target *rt)
{
	if (rt != NULL)
	{
		if (rt == targethead)
		{
			targethead = targethead->next;
		}

		if (rt->prev != NULL)
		{
			rt->prev->next = rt->next;
		}

		if (rt->next != NULL)
		{
			rt->next->prev = rt->prev;
		}

		d3d_cache_target *cache = find_cache_target(rt->screen_index, rt->width, rt->height);
		if (cache != NULL)
		{
			remove_cache_target(cache);
		}

		int screen_index = rt->screen_index;
		int other_page = 1 - rt->page_index;
		int width = rt->width;
		int height = rt->height;

		global_free(rt);

		// Remove other double-buffered page (if it exists)
		remove_render_target(width, height, screen_index, other_page);
	}
}


//============================================================
//  hlsl_info::set_texture
//============================================================

void hlsl_info::set_texture(d3d_texture_info *texture)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_info *d3d = (d3d_info *)window->drawdata;

	if(texture != NULL)
	{
		if(texture->prev_frame == texture->cur_frame)
		{
			paused = true;
		}
		else
		{
			paused = false;
		}

		texture->prev_frame = texture->cur_frame;
	}

	(*d3dintf->effect.set_texture)(effect, "Diffuse", (texture == NULL) ? d3d->default_texture->d3dfinaltex : texture->d3dfinaltex);
	if (options->yiq_enable)
		(*d3dintf->effect.set_texture)(yiq_encode_effect, "Diffuse", (texture == NULL) ? d3d->default_texture->d3dfinaltex : texture->d3dfinaltex);
	else
		(*d3dintf->effect.set_texture)(color_effect, "Diffuse", (texture == NULL) ? d3d->default_texture->d3dfinaltex : texture->d3dfinaltex);
	(*d3dintf->effect.set_texture)(pincushion_effect, "Diffuse", (texture == NULL) ? d3d->default_texture->d3dfinaltex : texture->d3dfinaltex);
}


//============================================================
//  hlsl_info::init
//============================================================

void hlsl_info::init(d3d_base *d3dintf, win_window_info *window)
{
	if (!d3dintf->post_fx_available)
		return;

	g_slider_list = init_slider_list();

	this->d3dintf = d3dintf;
	this->window = window;

	master_enable = downcast<windows_options &>(window->machine().options()).d3d_hlsl_enable();
	prescale_size_x = 1;
	prescale_size_y = 1;
	preset = downcast<windows_options &>(window->machine().options()).d3d_hlsl_preset();
	if (preset < -1 || preset > 3)
	{
		preset = -1;
	}

	snap_width = downcast<windows_options &>(window->machine().options()).d3d_snap_width();
	snap_height = downcast<windows_options &>(window->machine().options()).d3d_snap_height();
	prescale_force_x = 0;
	prescale_force_y = 0;

	windows_options &winoptions = downcast<windows_options &>(window->machine().options());

	options = (hlsl_options*)global_alloc_clear(hlsl_options);

	options->params_dirty = true;
	strcpy(options->shadow_mask_texture, downcast<windows_options &>(window->machine().options()).screen_shadow_mask_texture()); // unsafe

	write_ini = downcast<windows_options &>(window->machine().options()).hlsl_write_ini();
	read_ini = downcast<windows_options &>(window->machine().options()).hlsl_read_ini();

	if(read_ini)
	{
		emu_file ini_file(downcast<windows_options &>(window->machine().options()).screen_post_fx_dir(), OPEN_FLAG_READ | OPEN_FLAG_CREATE_PATHS);
		file_error filerr = open_next((d3d_info*)window->drawdata, ini_file, downcast<windows_options &>(window->machine().options()).hlsl_ini_name(), "ini", 0);

		read_ini = false;
		if (filerr == FILERR_NONE)
		{
			ini_file.seek(0, SEEK_END);
			if (ini_file.tell() >= 1000)
			{
				read_ini = true;
				ini_file.seek(0, SEEK_SET);

				int en = 0;
				char buf[1024];
				ini_file.gets(buf, 1024);
				sscanf(buf, "hlsl_enable %d\n", &en);
				master_enable = en == 1;

				ini_file.gets(buf, 1024);
				sscanf(buf, "hlsl_prescale_x %d\n", &prescale_force_x);

				ini_file.gets(buf, 1024);
				sscanf(buf, "hlsl_prescale_y %d\n", &prescale_force_y);

				ini_file.gets(buf, 1024);
				sscanf(buf, "hlsl_preset %d\n", &preset);

				ini_file.gets(buf, 1024);
				sscanf(buf, "hlsl_snap_width %d\n", &snap_width);

				ini_file.gets(buf, 1024);
				sscanf(buf, "hlsl_snap_height %d\n", &snap_height);

				ini_file.gets(buf, 1024);
				sscanf(buf, "shadow_mask_alpha %f\n", &options->shadow_mask_alpha);

				ini_file.gets(buf, 1024);
				sscanf(buf, "shadow_mask_texture %s\n", options->shadow_mask_texture);

				ini_file.gets(buf, 1024);
				sscanf(buf, "shadow_mask_x_count %d\n", &options->shadow_mask_count_x);

				ini_file.gets(buf, 1024);
				sscanf(buf, "shadow_mask_y_count %d\n", &options->shadow_mask_count_y);

				ini_file.gets(buf, 1024);
				sscanf(buf, "shadow_mask_usize %f\n", &options->shadow_mask_u_size);

				ini_file.gets(buf, 1024);
				sscanf(buf, "shadow_mask_vsize %f\n", &options->shadow_mask_v_size);

				ini_file.gets(buf, 1024);
				sscanf(buf, "curvature %f\n", &options->curvature);

				ini_file.gets(buf, 1024);
				sscanf(buf, "pincushion %f\n", &options->pincushion);

				ini_file.gets(buf, 1024);
				sscanf(buf, "scanline_alpha %f\n", &options->scanline_alpha);

				ini_file.gets(buf, 1024);
				sscanf(buf, "scanline_size %f\n", &options->scanline_scale);

				ini_file.gets(buf, 1024);
				sscanf(buf, "scanline_height %f\n", &options->scanline_height);

				ini_file.gets(buf, 1024);
				sscanf(buf, "scanline_bright_scale %f\n", &options->scanline_bright_scale);

				ini_file.gets(buf, 1024);
				sscanf(buf, "scanline_bright_offset %f\n", &options->scanline_bright_offset);

				ini_file.gets(buf, 1024);
				sscanf(buf, "scanline_jitter %f\n", &options->scanline_offset);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "defocus %f %f\n", &options->defocus[0], &options->defocus[1]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "converge_x %f %f %f\n", &options->converge_x[0], &options->converge_x[1], &options->converge_x[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "converge_y %f %f %f\n", &options->converge_y[0], &options->converge_y[1], &options->converge_y[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "radial_converge_x %f %f %f\n", &options->radial_converge_x[0], &options->radial_converge_x[1], &options->radial_converge_x[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "radial_converge_y %f %f %f\n", &options->radial_converge_y[0], &options->radial_converge_y[1], &options->radial_converge_y[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "red_ratio %f %f %f\n", &options->red_ratio[0], &options->red_ratio[1], &options->red_ratio[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "grn_ratio %f %f %f\n", &options->grn_ratio[0], &options->grn_ratio[1], &options->grn_ratio[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "blu_ratio %f %f %f\n", &options->blu_ratio[0], &options->blu_ratio[1], &options->blu_ratio[2]);

				ini_file.gets(buf, 1024);
				sscanf(buf, "saturation %f\n", &options->saturation);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "offset %f %f %f\n", &options->offset[0], &options->offset[1], &options->offset[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "scale %f %f %f\n", &options->scale[0], &options->scale[1], &options->scale[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "power %f %f %f\n", &options->power[0], &options->power[1], &options->power[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "floor %f %f %f\n", &options->floor[0], &options->floor[1], &options->floor[2]);

				ini_file.gets(buf, 1024);
				for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' ';
				sscanf(buf, "phosphor_life %f %f %f\n", &options->phosphor[0], &options->phosphor[1], &options->phosphor[2]);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_enable %d\n", &en);
				options->yiq_enable = en == 1;

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_cc %f\n", &options->yiq_cc);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_a %f\n", &options->yiq_a);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_b %f\n", &options->yiq_b);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_o %f\n", &options->yiq_o);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_p %f\n", &options->yiq_p);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_n %f\n", &options->yiq_n);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_y %f\n", &options->yiq_y);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_i %f\n", &options->yiq_i);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_q %f\n", &options->yiq_q);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_scan_time %f\n", &options->yiq_scan_time);

				ini_file.gets(buf, 1024);
				sscanf(buf, "yiq_phase_count %d\n", &options->yiq_phase_count);

                ini_file.gets(buf, 1024);
                sscanf(buf, "vector_time_scale %f\n", &options->vector_time_scale);

                ini_file.gets(buf, 1024);
                sscanf(buf, "vector_time_period %f\n", &options->vector_time_period);

                ini_file.gets(buf, 1024);
                sscanf(buf, "vector_length_scale %f\n", &options->vector_length_scale);

                ini_file.gets(buf, 1024);
                sscanf(buf, "vector_length_ratio %f\n", &options->vector_length_ratio);
			}
		}
	}
	else
	{
		prescale_force_x = winoptions.d3d_hlsl_prescale_x();
		prescale_force_y = winoptions.d3d_hlsl_prescale_y();
		if(preset == -1)
		{
			options->shadow_mask_alpha = winoptions.screen_shadow_mask_alpha();
			options->shadow_mask_count_x = winoptions.screen_shadow_mask_count_x();
			options->shadow_mask_count_y = winoptions.screen_shadow_mask_count_y();
			options->shadow_mask_u_size = winoptions.screen_shadow_mask_u_size();
			options->shadow_mask_v_size = winoptions.screen_shadow_mask_v_size();
			options->curvature = winoptions.screen_curvature();
			options->pincushion = winoptions.screen_pincushion();
			options->scanline_alpha = winoptions.screen_scanline_amount();
			options->scanline_scale = winoptions.screen_scanline_scale();
			options->scanline_height = winoptions.screen_scanline_height();
			options->scanline_bright_scale = winoptions.screen_scanline_bright_scale();
			options->scanline_bright_offset = winoptions.screen_scanline_bright_offset();
			options->scanline_offset = winoptions.screen_scanline_offset();
			get_vector(winoptions.screen_defocus(), 2, options->defocus, TRUE);
			get_vector(winoptions.screen_converge_x(), 3, options->converge_x, TRUE);
			get_vector(winoptions.screen_converge_y(), 3, options->converge_y, TRUE);
			get_vector(winoptions.screen_radial_converge_x(), 3, options->radial_converge_x, TRUE);
			get_vector(winoptions.screen_radial_converge_y(), 3, options->radial_converge_y, TRUE);
			get_vector(winoptions.screen_red_ratio(), 3, options->red_ratio, TRUE);
			get_vector(winoptions.screen_grn_ratio(), 3, options->grn_ratio, TRUE);
			get_vector(winoptions.screen_blu_ratio(), 3, options->blu_ratio, TRUE);
			get_vector(winoptions.screen_offset(), 3, options->offset, TRUE);
			get_vector(winoptions.screen_scale(), 3, options->scale, TRUE);
			get_vector(winoptions.screen_power(), 3, options->power, TRUE);
			get_vector(winoptions.screen_floor(), 3, options->floor, TRUE);
			get_vector(winoptions.screen_phosphor(), 3, options->phosphor, TRUE);
			options->saturation = winoptions.screen_saturation();
		}
		else
		{
			options = &g_hlsl_presets[preset];
		}

		options->yiq_enable = winoptions.screen_yiq_enable();
		options->yiq_cc = winoptions.screen_yiq_cc();
		options->yiq_a = winoptions.screen_yiq_a();
		options->yiq_b = winoptions.screen_yiq_b();
		options->yiq_o = winoptions.screen_yiq_o();
		options->yiq_p = winoptions.screen_yiq_p();
		options->yiq_n = winoptions.screen_yiq_n();
		options->yiq_y = winoptions.screen_yiq_y();
		options->yiq_i = winoptions.screen_yiq_i();
		options->yiq_q = winoptions.screen_yiq_q();
		options->yiq_scan_time = winoptions.screen_yiq_scan_time();
		options->yiq_phase_count = winoptions.screen_yiq_phase_count();
        options->vector_time_scale = winoptions.screen_vector_time_scale();
        options->vector_time_period = winoptions.screen_vector_time_period();
        options->vector_length_scale = winoptions.screen_vector_length_scale();
        options->vector_length_ratio = winoptions.screen_vector_length_ratio();
	}

	options->params_dirty = true;
	// experimental: load a PNG to use for vector rendering; it is treated
	// as a brightness map
	emu_file file(window->machine().options().art_path(), OPEN_FLAG_READ);

	render_load_png(shadow_bitmap, file, NULL, options->shadow_mask_texture);
}



//============================================================
//  hlsl_info::init_fsfx_quad
//============================================================

void hlsl_info::init_fsfx_quad(void *vertbuf)
{
    // Called at the start of each frame by the D3D code in order to reserve two triangles
    // that are guaranteed to be at a fixed position so as to simply use D3DPT_TRIANGLELIST, 0, 2
    // instead of having to do bookkeeping about a specific screen quad
    if (!master_enable || !d3dintf->post_fx_available)
        return;

    d3d_info *d3d = (d3d_info *)window->drawdata;

    // get a pointer to the vertex buffer
    fsfx_vertices = (d3d_vertex *)vertbuf;
    if (fsfx_vertices == NULL)
        return;

    // fill in the vertexes clockwise
    fsfx_vertices[0].x = 0.0f;
    fsfx_vertices[0].y = 0.0f;
    fsfx_vertices[1].x = d3d->width;
    fsfx_vertices[1].y = 0.0f;
    fsfx_vertices[2].x = 0.0f;
    fsfx_vertices[2].y = d3d->height;
    fsfx_vertices[3].x = d3d->width;
    fsfx_vertices[3].y = 0.0f;
    fsfx_vertices[4].x = 0.0f;
    fsfx_vertices[4].y = d3d->height;
    fsfx_vertices[5].x = d3d->width;
    fsfx_vertices[5].y = d3d->height;

    fsfx_vertices[0].u0 = 0.0f;
    fsfx_vertices[0].v0 = 0.0f;

    fsfx_vertices[1].u0 = 1.0f;
    fsfx_vertices[1].v0 = 0.0f;

    fsfx_vertices[2].u0 = 0.0f;
    fsfx_vertices[2].v0 = 1.0f;

    fsfx_vertices[3].u0 = 1.0f;
    fsfx_vertices[3].v0 = 0.0f;

    fsfx_vertices[4].u0 = 0.0f;
    fsfx_vertices[4].v0 = 1.0f;

    fsfx_vertices[5].u0 = 1.0f;
    fsfx_vertices[5].v0 = 1.0f;

    // set the color, Z parameters to standard values
    for (int i = 0; i < 6; i++)
    {
        fsfx_vertices[i].z = 0.0f;
        fsfx_vertices[i].rhw = 1.0f;
        fsfx_vertices[i].color = D3DCOLOR_ARGB(255, 255, 255, 255);
    }
}



//============================================================
//  hlsl_info::create_resources
//============================================================

int hlsl_info::create_resources(bool reset)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return 0;

	d3d_info *d3d = (d3d_info *)window->drawdata;

    HRESULT result = (*d3dintf->device.get_render_target)(d3d->device, 0, &backbuffer);
    if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result);

    result = (*d3dintf->device.create_texture)(d3d->device, 4, 4, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &black_texture);
    if (result != D3D_OK)
    {
        mame_printf_verbose("Direct3D: Unable to init video-memory target for black texture (%08x)\n", (UINT32)result);
        return 1;
    }
    (*d3dintf->texture.get_surface_level)(black_texture, 0, &black_surface);
    result = (*d3dintf->device.set_render_target)(d3d->device, 0, black_surface);
    if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
    result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
    if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);
    result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
    if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

	result = (*d3dintf->device.create_texture)(d3d->device, (int)snap_width, (int)snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &avi_copy_texture);
	if (result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to init system-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result);
		return 1;
	}
	(*d3dintf->texture.get_surface_level)(avi_copy_texture, 0, &avi_copy_surface);

	result = (*d3dintf->device.create_texture)(d3d->device, (int)snap_width, (int)snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &avi_final_texture);
	if (result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to init video-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result);
		return 1;
	}
	(*d3dintf->texture.get_surface_level)(avi_final_texture, 0, &avi_final_target);

	// experimental: if we have a shadow bitmap, create a texture for it
	if (shadow_bitmap.valid())
	{
		render_texinfo texture;

		// fake in the basic data so it looks like it came from render.c
		texture.base = shadow_bitmap.raw_pixptr(0);
		texture.rowpixels = shadow_bitmap.rowpixels();
		texture.width = shadow_bitmap.width();
		texture.height = shadow_bitmap.height();
		texture.palette = NULL;
		texture.seqid = 0;

		// now create it
		shadow_texture = texture_create(d3d, &texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
	}

	const char *fx_dir = downcast<windows_options &>(window->machine().options()).screen_post_fx_dir();

	// Replace all this garbage with a proper data-driven system
	char primary_name_cstr[1024];
	sprintf(primary_name_cstr, "%s\\primary.fx", fx_dir);
	TCHAR *primary_name = tstring_from_utf8(primary_name_cstr);

	char post_name_cstr[1024];
	sprintf(post_name_cstr, "%s\\post.fx", fx_dir);
	TCHAR *post_name = tstring_from_utf8(post_name_cstr);

	char prescale_name_cstr[1024];
	sprintf(prescale_name_cstr, "%s\\prescale.fx", fx_dir);
	TCHAR *prescale_name = tstring_from_utf8(prescale_name_cstr);

	char pincushion_name_cstr[1024];
	sprintf(pincushion_name_cstr, "%s\\pincushion.fx", fx_dir);
	TCHAR *pincushion_name = tstring_from_utf8(pincushion_name_cstr);

	char phosphor_name_cstr[1024];
	sprintf(phosphor_name_cstr, "%s\\phosphor.fx", fx_dir);
	TCHAR *phosphor_name = tstring_from_utf8(phosphor_name_cstr);

	char focus_name_cstr[1024];
	sprintf(focus_name_cstr, "%s\\focus.fx", fx_dir);
	TCHAR *focus_name = tstring_from_utf8(focus_name_cstr);

	char deconverge_name_cstr[1024];
	sprintf(deconverge_name_cstr, "%s\\deconverge.fx", fx_dir);
	TCHAR *deconverge_name = tstring_from_utf8(deconverge_name_cstr);

	char color_name_cstr[1024];
	sprintf(color_name_cstr, "%s\\color.fx", fx_dir);
	TCHAR *color_name = tstring_from_utf8(color_name_cstr);

	char yiq_encode_name_cstr[1024];
	sprintf(yiq_encode_name_cstr, "%s\\yiq_encode.fx", fx_dir);
	TCHAR *yiq_encode_name = tstring_from_utf8(yiq_encode_name_cstr);

	char yiq_decode_name_cstr[1024];
	sprintf(yiq_decode_name_cstr, "%s\\yiq_decode.fx", fx_dir);
	TCHAR *yiq_decode_name = tstring_from_utf8(yiq_decode_name_cstr);

	// create the regular shader
	result = (*d3dintf->device.create_effect)(d3d->device, primary_name, &effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load primary.fx\n");
		return 1;
	}

	// create the post-processing shader
	result = (*d3dintf->device.create_effect)(d3d->device, post_name, &post_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load post.fx\n");
		return 1;
	}

	// create the prescaling shader
	result = (*d3dintf->device.create_effect)(d3d->device, prescale_name, &prescale_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load prescale.fx\n");
		return 1;
	}

	// create the pincushion shader
	result = (*d3dintf->device.create_effect)(d3d->device, pincushion_name, &pincushion_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load pincushion.fx\n");
		return 1;
	}

	// create the phosphor shader
	result = (*d3dintf->device.create_effect)(d3d->device, phosphor_name, &phosphor_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load phosphor.fx\n");
		return 1;
	}

	// create the focus shader
	result = (*d3dintf->device.create_effect)(d3d->device, focus_name, &focus_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load focus.fx\n");
		return 1;
	}

	// create the deconvergence shader
	result = (*d3dintf->device.create_effect)(d3d->device, deconverge_name, &deconverge_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load deconverge.fx\n");
		return 1;
	}

	// create the color convolution shader
	result = (*d3dintf->device.create_effect)(d3d->device, color_name, &color_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load color.fx\n");
		return 1;
	}

	// create the YIQ modulation shader
	result = (*d3dintf->device.create_effect)(d3d->device, yiq_encode_name, &yiq_encode_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load yiq_encode.fx\n");
		return 1;
	}

	// create the YIQ demodulation shader
	result = (*d3dintf->device.create_effect)(d3d->device, yiq_decode_name, &yiq_decode_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load yiq_decode.fx\n");
		return 1;
	}

	// create the vector shader
#if HLSL_VECTOR
    char bloom_cstr[1024];
    sprintf(bloom_cstr, "%s\\bloom.fx", fx_dir);
    TCHAR *bloom_name = tstring_from_utf8(bloom_cstr);

    result = (*d3dintf->device.create_effect)(d3d->device, bloom_name, &bloom_effect);
    if(result != D3D_OK)
    {
        mame_printf_verbose("Direct3D: Unable to load bloom.fx\n");
        return 1;
    }
    if (bloom_name)
        osd_free(bloom_name);

    char downsample_cstr[1024];
    sprintf(downsample_cstr, "%s\\downsample.fx", fx_dir);
    TCHAR *downsample_name = tstring_from_utf8(downsample_cstr);

    result = (*d3dintf->device.create_effect)(d3d->device, downsample_name, &downsample_effect);
    if(result != D3D_OK)
    {
        mame_printf_verbose("Direct3D: Unable to load downsample.fx\n");
        return 1;
    }
    if (downsample_name)
        osd_free(downsample_name);

    char vector_cstr[1024];
    sprintf(vector_cstr, "%s\\vector.fx", fx_dir);
    TCHAR *vector_name = tstring_from_utf8(vector_cstr);

	result = (*d3dintf->device.create_effect)(d3d->device, vector_name, &vector_effect);
	if(result != D3D_OK)
	{
		mame_printf_verbose("Direct3D: Unable to load vector.fx\n");
		return 1;
	}
	if (vector_name)
		osd_free(vector_name);
#endif

	if (primary_name)
		osd_free(primary_name);
	if (post_name)
		osd_free(post_name);
	if (prescale_name)
		osd_free(prescale_name);
	if (pincushion_name)
		osd_free(pincushion_name);
	if (phosphor_name)
		osd_free(phosphor_name);
	if (focus_name)
		osd_free(focus_name);
	if (deconverge_name)
		osd_free(deconverge_name);
	if (color_name)
		osd_free(color_name);
	if (yiq_encode_name)
		osd_free(yiq_encode_name);
	if (yiq_decode_name)
		osd_free(yiq_decode_name);

	initialized = true;

	return 0;
}


//============================================================
//  hlsl_info::begin_draw
//============================================================

void hlsl_info::begin_draw()
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_info *d3d = (d3d_info *)window->drawdata;

	curr_effect = effect;

	(*d3dintf->effect.set_technique)(effect, "TestTechnique");
	(*d3dintf->effect.set_technique)(post_effect, "ScanMaskTechnique");
	(*d3dintf->effect.set_technique)(pincushion_effect, "TestTechnique");
	(*d3dintf->effect.set_technique)(phosphor_effect, "TestTechnique");
	(*d3dintf->effect.set_technique)(focus_effect, "TestTechnique");
	(*d3dintf->effect.set_technique)(deconverge_effect, "DeconvergeTechnique");
	(*d3dintf->effect.set_technique)(color_effect, "ColorTechnique");
	(*d3dintf->effect.set_technique)(yiq_encode_effect, "EncodeTechnique");
	(*d3dintf->effect.set_technique)(yiq_decode_effect, "DecodeTechnique");

	HRESULT result = (*d3dintf->device.get_render_target)(d3d->device, 0, &backbuffer);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result);
}


//============================================================
//  hlsl_info::begin_frame
//============================================================

void hlsl_info::begin_frame()
{
	record_texture();

	/*d3d_info *d3d = (d3d_info *)window->drawdata;

	d3d_render_target *rt = find_render_target(d3d->width, d3d->height, 0, 0);
	if (rt == NULL)
	{
		return;
	}

	HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[0]);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
	result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);
	result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);*/
}


//============================================================
//  hlsl_info::blit
//============================================================

void hlsl_info::blit(d3d_surface *dst, d3d_texture *src, d3d_surface *new_dst, D3DPRIMITIVETYPE prim_type,
                     UINT32 prim_index, UINT32 prim_count, int dstw, int dsth)
{
    d3d_info *d3d = (d3d_info *)window->drawdata;

    HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, dst);
    if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

    curr_effect = effect;

    (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", src);

    (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)dstw);
    (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)dsth);
    (*d3dintf->effect.set_float)(curr_effect, "PostPass", 1.0f);
    (*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion);
    (*d3dintf->effect.set_float)(curr_effect, "Brighten", 0.0f);

    unsigned int num_passes = 0;
    (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

    for (UINT pass = 0; pass < num_passes; pass++)
    {
        (*d3dintf->effect.begin_pass)(curr_effect, pass);
        // add the primitives
        HRESULT result = (*d3dintf->device.draw_primitive)(d3d->device, prim_type, prim_index, prim_count);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
        (*d3dintf->effect.end_pass)(curr_effect);
    }

    (*d3dintf->effect.end)(curr_effect);

    if (new_dst)
    {
        HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, new_dst);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
    }
}



//============================================================
//  hlsl_info::blit
//============================================================

void hlsl_info::blit(d3d_surface *dst, d3d_texture *src, d3d_surface *new_dst, D3DPRIMITIVETYPE prim_type,
					 UINT32 prim_index, UINT32 prim_count)
{
	d3d_info *d3d = (d3d_info *)window->drawdata;

	HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, dst);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

	curr_effect = effect;

	d3d_render_target *rt = find_render_target(d3d->width, d3d->height, 0, 0);
	if (rt == NULL)
	{
		return;
	}

	(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", src);

    (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
    (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
    (*d3dintf->effect.set_float)(curr_effect, "ScreenWidth", (float)d3d->width);
    (*d3dintf->effect.set_float)(curr_effect, "ScreenHeight", (float)d3d->height);
	(*d3dintf->effect.set_float)(curr_effect, "PostPass", 1.0f);
	(*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion);
	(*d3dintf->effect.set_float)(curr_effect, "Brighten", 1.0f);

	unsigned int num_passes = 0;
	(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

	for (UINT pass = 0; pass < num_passes; pass++)
	{
		(*d3dintf->effect.begin_pass)(curr_effect, pass);
		// add the primitives
		HRESULT result = (*d3dintf->device.draw_primitive)(d3d->device, prim_type, prim_index, prim_count);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
		(*d3dintf->effect.end_pass)(curr_effect);
	}

	(*d3dintf->effect.end)(curr_effect);

	(*d3dintf->effect.set_float)(curr_effect, "Brighten", 0.0f);

	if (new_dst)
	{
		HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, new_dst);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
	}
}

//============================================================
//  hlsl_info::end_frame
//============================================================

void hlsl_info::end_frame()
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	if(render_snap && snap_rendered)
	{
		render_snapshot(snap_target);
	}

    if (!lines_pending)
        return;

    lines_pending = false;
    /*d3d_info *d3d = (d3d_info *)window->drawdata;

    d3d_render_target *rt = find_render_target(d3d->width, d3d->height, 0, 0);
    if (!rt)
        return;

    blit(backbuffer, rt->texture[0], NULL, vecbuf_type, vecbuf_index, vecbuf_count);*/

	/*d3d_render_target *rt = find_render_target(d3d->width, d3d->height, 0, 0);
	if (rt == NULL)
	{
		return;
	}

	blit(backbuffer, rt->texture[1], NULL, vecbuf_type, vecbuf_index, vecbuf_count);

	HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[1]);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
	result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);
	result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);*/
}


//============================================================
//  hlsl_info::init_effect_info
//============================================================

void hlsl_info::init_effect_info(d3d_poly_info *poly)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	d3d_info *d3d = (d3d_info *)window->drawdata;

	if(PRIMFLAG_GET_TEXSHADE(d3d->last_texture_flags))
	{
		curr_effect = pincushion_effect;
	}
	else if(PRIMFLAG_GET_SCREENTEX(d3d->last_texture_flags) && poly->texture != NULL)
	{
		// Plug in all of the shader settings we're going to need
		// This is extremely slow, but we're not rendering models here,
		// just post-processing.
		curr_effect = post_effect;

		(*d3dintf->effect.set_float)(curr_effect, "ScanlineOffset", (poly->texture->cur_frame == 0) ? 0.0f : options->scanline_offset);

		if(options->params_dirty)
		{
			(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / (poly->texture->ustop - poly->texture->ustart));
			(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / (poly->texture->vstop - poly->texture->vstart));
			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", d3d->height);
			(*d3dintf->effect.set_vector)(curr_effect, "Floor", 3, options->floor);
			(*d3dintf->effect.set_float)(curr_effect, "SnapX", snap_width);
			(*d3dintf->effect.set_float)(curr_effect, "SnapY", snap_height);
			(*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion);
			(*d3dintf->effect.set_float)(curr_effect, "CurvatureAmount", options->curvature);
			(*d3dintf->effect.set_float)(curr_effect, "UseShadow", shadow_texture == NULL ? 0.0f : 1.0f);
			(*d3dintf->effect.set_texture)(curr_effect, "Shadow", shadow_texture == NULL ? NULL : shadow_texture->d3dfinaltex);
			(*d3dintf->effect.set_float)(curr_effect, "ShadowBrightness", options->shadow_mask_alpha);
			(*d3dintf->effect.set_float)(curr_effect, "ShadowMaskSizeX", (float)options->shadow_mask_count_x);
			(*d3dintf->effect.set_float)(curr_effect, "ShadowMaskSizeY", (float)options->shadow_mask_count_y);
			(*d3dintf->effect.set_float)(curr_effect, "ShadowU", options->shadow_mask_u_size);
			(*d3dintf->effect.set_float)(curr_effect, "ShadowV", options->shadow_mask_v_size);
			(*d3dintf->effect.set_float)(curr_effect, "ShadowWidth", shadow_texture == NULL ? 1.0f : (float)shadow_texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "ShadowHeight", shadow_texture == NULL ? 1.0f : (float)shadow_texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "ScanlineAmount", options->scanline_alpha);
			(*d3dintf->effect.set_float)(curr_effect, "ScanlineScale", options->scanline_scale);
			(*d3dintf->effect.set_float)(curr_effect, "ScanlineHeight", options->scanline_height);
			(*d3dintf->effect.set_float)(curr_effect, "ScanlineBrightScale", options->scanline_bright_scale);
			(*d3dintf->effect.set_float)(curr_effect, "ScanlineBrightOffset", options->scanline_bright_offset);
			//(*d3dintf->effect.set_float)(curr_effect, "ScanlineOffset", (poly->texture->cur_frame == 0) ? 0.0f : options->scanline_offset);
			(*d3dintf->effect.set_vector)(curr_effect, "Power", 3, options->power);
		}
	}
	else
	{
		curr_effect = effect;

		(*d3dintf->effect.set_float)(curr_effect, "FixedAlpha", 1.0f);
	}
}


//============================================================
//  hlsl_info::find_render_target
//============================================================

d3d_render_target* hlsl_info::find_render_target(d3d_texture_info *info)
{
	d3d_render_target *curr = targethead;

	UINT32 screen_index_data = (UINT32)info->texinfo.osddata;
	UINT32 screen_index = screen_index_data >> 1;
	UINT32 page_index = screen_index_data & 1;

	while (curr != NULL && (curr->screen_index != screen_index || curr->page_index != page_index || curr->width != info->texinfo.width || curr->height != info->texinfo.height))
	{
		curr = curr->next;
	}

	return curr;
}


//============================================================
//  hlsl_info::find_render_target
//============================================================

d3d_render_target* hlsl_info::find_render_target(int width, int height, UINT32 screen_index, UINT32 page_index)
{
	d3d_render_target *curr = targethead;

	while (curr != NULL && (curr->width != width || curr->height != height || curr->screen_index != screen_index || curr->page_index != page_index))
	{
		curr = curr->next;
	}

	return curr;
}


//============================================================
//  hlsl_info::find_cache_target
//============================================================

d3d_cache_target* hlsl_info::find_cache_target(UINT32 screen_index, int width, int height)
{
	d3d_cache_target *curr = cachehead;

	while (curr != NULL && (curr->screen_index != screen_index || curr->width != width || curr->height != height))
	{
		curr = curr->next;
	}

	return curr;
}


//============================================================
//  hlsl_info::render_quad
//============================================================

void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	UINT num_passes = 0;
	d3d_info *d3d = (d3d_info *)window->drawdata;

	if(PRIMFLAG_GET_SCREENTEX(d3d->last_texture_flags) && poly->texture != NULL)
	{
		d3d_render_target *rt = find_render_target(poly->texture);
		if (rt == NULL)
		{
			return;
		}
		d3d_cache_target *ct = find_cache_target(rt->screen_index, poly->texture->texinfo.width, poly->texture->texinfo.height);

		if(options->yiq_enable)
		{
			/* Convert our signal into YIQ */
			curr_effect = yiq_encode_effect;

			if(options->params_dirty)
			{
				(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
				(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
				(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / (poly->texture->ustop - poly->texture->ustart));
				(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / (poly->texture->vstop - poly->texture->vstart));
				(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
				(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
				(*d3dintf->effect.set_float)(curr_effect, "CCValue", options->yiq_cc);
				(*d3dintf->effect.set_float)(curr_effect, "AValue", options->yiq_a);
				(*d3dintf->effect.set_float)(curr_effect, "BValue", (poly->texture->cur_frame == 2) ? 0.0f : ((float)poly->texture->cur_frame * options->yiq_b));
				(*d3dintf->effect.set_float)(curr_effect, "PValue", options->yiq_p);
				(*d3dintf->effect.set_float)(curr_effect, "NotchHalfWidth", options->yiq_n);
				(*d3dintf->effect.set_float)(curr_effect, "YFreqResponse", options->yiq_y);
				(*d3dintf->effect.set_float)(curr_effect, "IFreqResponse", options->yiq_i);
				(*d3dintf->effect.set_float)(curr_effect, "QFreqResponse", options->yiq_q);
				(*d3dintf->effect.set_float)(curr_effect, "ScanTime", options->yiq_scan_time);
			}

			HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[4]);

			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
			result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

			(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

			for (UINT pass = 0; pass < num_passes; pass++)
			{
				(*d3dintf->effect.begin_pass)(curr_effect, pass);
				// add the primitives
				result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
				if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
				(*d3dintf->effect.end_pass)(curr_effect);
			}

			(*d3dintf->effect.end)(curr_effect);

			/* Convert our signal from YIQ */
			curr_effect = yiq_decode_effect;

			(*d3dintf->effect.set_texture)(curr_effect, "Composite", rt->texture[4]);
			(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", poly->texture->d3dfinaltex);
			if(options->params_dirty)
			{
				(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
				(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
				(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / (poly->texture->ustop - poly->texture->ustart));
				(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / (poly->texture->vstop - poly->texture->vstart));
				(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
				(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
				(*d3dintf->effect.set_float)(curr_effect, "CCValue", options->yiq_cc);
				(*d3dintf->effect.set_float)(curr_effect, "AValue", options->yiq_a);
				(*d3dintf->effect.set_float)(curr_effect, "BValue", (poly->texture->cur_frame == 2) ? 0.0f : ((float)poly->texture->cur_frame * options->yiq_b));
				(*d3dintf->effect.set_float)(curr_effect, "OValue", options->yiq_o);
				(*d3dintf->effect.set_float)(curr_effect, "PValue", options->yiq_p);
				(*d3dintf->effect.set_float)(curr_effect, "NotchHalfWidth", options->yiq_n);
				(*d3dintf->effect.set_float)(curr_effect, "YFreqResponse", options->yiq_y);
				(*d3dintf->effect.set_float)(curr_effect, "IFreqResponse", options->yiq_i);
				(*d3dintf->effect.set_float)(curr_effect, "QFreqResponse", options->yiq_q);
				(*d3dintf->effect.set_float)(curr_effect, "ScanTime", options->yiq_scan_time);
			}

			result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[3]);

			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
			result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

			(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

			for (UINT pass = 0; pass < num_passes; pass++)
			{
				(*d3dintf->effect.begin_pass)(curr_effect, pass);
				// add the primitives
				result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
				if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
				(*d3dintf->effect.end_pass)(curr_effect);
			}

			(*d3dintf->effect.end)(curr_effect);

			curr_effect = color_effect;

			(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[3]);
		}

		curr_effect = color_effect;

		/* Render the initial color-convolution pass */
		if(options->params_dirty)
		{
			(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", options->yiq_enable ? 1.0f : (1.0f / (poly->texture->ustop - poly->texture->ustart)));
			(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", options->yiq_enable ? 1.0f : (1.0f / (poly->texture->vstop - poly->texture->vstart)));
			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
			(*d3dintf->effect.set_float)(curr_effect, "YIQEnable", options->yiq_enable ? 1.0f : 0.0f);
			(*d3dintf->effect.set_vector)(curr_effect, "RedRatios", 3, options->red_ratio);
			(*d3dintf->effect.set_vector)(curr_effect, "GrnRatios", 3, options->grn_ratio);
			(*d3dintf->effect.set_vector)(curr_effect, "BluRatios", 3, options->blu_ratio);
			(*d3dintf->effect.set_vector)(curr_effect, "Offset", 3, options->offset);
			(*d3dintf->effect.set_vector)(curr_effect, "Scale", 3, options->scale);
			(*d3dintf->effect.set_float)(curr_effect, "Saturation", options->saturation);
		}

		HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->smalltarget);

		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
		result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

		(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

		for (UINT pass = 0; pass < num_passes; pass++)
		{
			(*d3dintf->effect.begin_pass)(curr_effect, pass);
			// add the primitives
			result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
			(*d3dintf->effect.end_pass)(curr_effect);
		}

		(*d3dintf->effect.end)(curr_effect);

		/* Pre-scaling pass */
		curr_effect = prescale_effect;
		(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->smalltexture);

		if(options->params_dirty)
		{
			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
			(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / (poly->texture->ustop - poly->texture->ustart));
			(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / (poly->texture->vstop - poly->texture->vstart));
		}

		(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

		result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->prescaletarget);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
		result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

		for (UINT pass = 0; pass < num_passes; pass++)
		{
			(*d3dintf->effect.begin_pass)(curr_effect, pass);
			// add the primitives
			result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
			(*d3dintf->effect.end_pass)(curr_effect);
		}

		(*d3dintf->effect.end)(curr_effect);

		/* Deconverge pass */
		curr_effect = deconverge_effect;
		(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->prescaletexture);

		if(options->params_dirty)
		{
			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
			(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / (poly->texture->ustop - poly->texture->ustart));
			(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / (poly->texture->vstop - poly->texture->vstart));
			(*d3dintf->effect.set_vector)(curr_effect, "ConvergeX", 3, options->converge_x);
			(*d3dintf->effect.set_vector)(curr_effect, "ConvergeY", 3, options->converge_y);
			(*d3dintf->effect.set_vector)(curr_effect, "RadialConvergeX", 3, options->radial_converge_x);
			(*d3dintf->effect.set_vector)(curr_effect, "RadialConvergeY", 3, options->radial_converge_y);
		}

		(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

		result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[2]);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result);
		result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

		for (UINT pass = 0; pass < num_passes; pass++)
		{
			(*d3dintf->effect.begin_pass)(curr_effect, pass);
			// add the primitives
			result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
			(*d3dintf->effect.end_pass)(curr_effect);
		}

		(*d3dintf->effect.end)(curr_effect);

		float defocus_x = options->defocus[0];
		float defocus_y = options->defocus[1];
		bool focus_enable = defocus_x != 0.0f || defocus_y != 0.0f;
		if(focus_enable)
		{
			/* Defocus pass 1 */
			curr_effect = focus_effect;

			(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[2]);

			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
			(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", poly->texture != NULL ? (1.0f / (poly->texture->ustop - poly->texture->ustart)) : 0.0f);
			(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", poly->texture != NULL ? (1.0f / (poly->texture->vstop - poly->texture->vstart)) : 0.0f);
			(*d3dintf->effect.set_vector)(curr_effect, "Defocus", 2, &options->defocus[0]);

			(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

			result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[0]);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result);
			result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

			for (UINT pass = 0; pass < num_passes; pass++)
			{
				(*d3dintf->effect.begin_pass)(curr_effect, pass);
				// add the primitives
				result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
				if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
				(*d3dintf->effect.end_pass)(curr_effect);
			}

			(*d3dintf->effect.end)(curr_effect);

			/* Defocus pass 2 */

			(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[0]);

			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
			(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f);
			(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f);
			(*d3dintf->effect.set_vector)(curr_effect, "Defocus", 2, &options->defocus[1]);

			(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

			result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[1]);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 7\n", (int)result);

			for (UINT pass = 0; pass < num_passes; pass++)
			{
				(*d3dintf->effect.begin_pass)(curr_effect, pass);
				// add the primitives
				result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
				if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
				(*d3dintf->effect.end_pass)(curr_effect);
			}

			(*d3dintf->effect.end)(curr_effect);
		}

		// Simulate phosphorescence. This should happen after the shadow/scanline pass, but since
		// the phosphors are a direct result of the incoming texture, might as well just change the
		// input texture.
		curr_effect = phosphor_effect;

		if(options->params_dirty)
		{
			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
			(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
			(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
			(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / (poly->texture->ustop - poly->texture->ustart));
			(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / (poly->texture->vstop - poly->texture->vstart));
			(*d3dintf->effect.set_vector)(curr_effect, "Phosphor", 3, options->phosphor);
		}
		(*d3dintf->effect.set_float)(curr_effect, "TextureWidth", (float)rt->target_width);
		(*d3dintf->effect.set_float)(curr_effect, "TextureHeight", (float)rt->target_height);
		(*d3dintf->effect.set_float)(curr_effect, "Passthrough", 0.0f);

		(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", focus_enable ? rt->texture[1] : rt->texture[2]);
		(*d3dintf->effect.set_texture)(curr_effect, "LastPass", ct->last_texture);

		result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[0]);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result);
		result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

		(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

		for (UINT pass = 0; pass < num_passes; pass++)
		{
			(*d3dintf->effect.begin_pass)(curr_effect, pass);
			// add the primitives
			result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
			(*d3dintf->effect.end_pass)(curr_effect);
		}

		(*d3dintf->effect.end)(curr_effect);

		/* Pass along our phosphor'd screen */
		curr_effect = phosphor_effect;

		(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[0]);
		(*d3dintf->effect.set_texture)(curr_effect, "LastPass", rt->texture[0]);
		(*d3dintf->effect.set_float)(curr_effect, "Passthrough", 1.0f);

		result = (*d3dintf->device.set_render_target)(d3d->device, 0, ct->last_target); // Avoid changing targets due to page flipping
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 5\n", (int)result);
		result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

		(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

		for (UINT pass = 0; pass < num_passes; pass++)
		{
			(*d3dintf->effect.begin_pass)(curr_effect, pass);
			// add the primitives
			result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
			(*d3dintf->effect.end_pass)(curr_effect);
		}

		(*d3dintf->effect.end)(curr_effect);

        curr_effect = post_effect;
        (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
        (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);

		/* Scanlines and shadow mask, at high res for AVI logging*/
		if(avi_output_file != NULL)
		{
			(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[0]);

			result = (*d3dintf->device.set_render_target)(d3d->device, 0, avi_final_target);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

			(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

			for (UINT pass = 0; pass < num_passes; pass++)
			{
				(*d3dintf->effect.begin_pass)(curr_effect, pass);
				// add the primitives
				result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
				if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
				(*d3dintf->effect.end_pass)(curr_effect);
			}

			(*d3dintf->effect.end)(curr_effect);
		}

		if(render_snap)
		{
			(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[0]);

			result = (*d3dintf->device.set_render_target)(d3d->device, 0, snap_target);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

			(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

			for (UINT pass = 0; pass < num_passes; pass++)
			{
				(*d3dintf->effect.begin_pass)(curr_effect, pass);
				// add the primitives
				result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
				if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
				(*d3dintf->effect.end_pass)(curr_effect);
			}

			(*d3dintf->effect.end)(curr_effect);

			snap_rendered = true;
		}

        /* Scanlines and shadow mask */
        curr_effect = post_effect;

        (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[0]);

        //(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)rt->target_width);
        //(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)rt->target_height);

#if HLSL_VECTOR
        result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[1]);
#else
        result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
#endif
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

        (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

        for (UINT pass = 0; pass < num_passes; pass++)
        {
            (*d3dintf->effect.begin_pass)(curr_effect, pass);
            // add the primitives
            result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
            (*d3dintf->effect.end_pass)(curr_effect);
        }

        (*d3dintf->effect.end)(curr_effect);

#if HLSL_VECTOR
        /* Bloom */
        curr_effect = downsample_effect;

        (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[1]);

        int bloom_size = (rt->target_width < rt->target_height) ? rt->target_width : rt->target_height;
        int bloom_index = 0;
        int bloom_width = rt->target_width;
        int bloom_height = rt->target_height;
        for(; bloom_size >= 2 && bloom_index < 11; bloom_size >>= 1)
        {
            float source_size[2] = { bloom_width, bloom_height };
            float target_size[2] = { bloom_width >> 1, bloom_height >> 1 };
            (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size);
            (*d3dintf->effect.set_vector)(curr_effect, "SourceSize", 2, source_size);

            (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

            (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", (bloom_index == 0) ? rt->texture[1] : ct->bloom_texture[bloom_index - 1]);

            if (ct->bloom_target[bloom_index] == NULL)
            {
                (*d3dintf->effect.end)(curr_effect);
                break;
            }

            HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, ct->bloom_target[bloom_index]);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 7:%d\n", (int)result, bloom_size);
            //result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
            //if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

            for (UINT pass = 0; pass < num_passes; pass++)
            {
                (*d3dintf->effect.begin_pass)(curr_effect, pass);
                // add the primitives
                result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
                if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
                (*d3dintf->effect.end_pass)(curr_effect);
            }

            (*d3dintf->effect.end)(curr_effect);

            bloom_index++;
            bloom_width >>= 1;
            bloom_height >>= 1;
        }

        /* Bloom composite pass*/
        curr_effect = bloom_effect;

        float target_size[2] = { rt->target_width, rt->target_height };
        (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size);

        (*d3dintf->effect.set_texture)(curr_effect, "DiffuseA", rt->texture[1]);
        (*d3dintf->effect.set_float)(curr_effect, "DiffuseScaleA", 1.0f);

        char name[9] = "Diffuse*";
        char scale[14] = "DiffuseScale*";
        for(int index = 1; index < bloom_index; index++)
        {
            name[7] = 'A' + index;
            scale[12] = 'A' + index;
            (*d3dintf->effect.set_texture)(curr_effect, name, ct->bloom_texture[index - 1]);
            (*d3dintf->effect.set_float)(curr_effect, scale, 1.0f);
        }
        for(int index = bloom_index; index < 11; index++)
        {
            name[7] = 'A' + index;
            scale[12] = 'A' + index;
            (*d3dintf->effect.set_texture)(curr_effect, name, black_texture);
            (*d3dintf->effect.set_float)(curr_effect, scale, 0.0f);
        }

        (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

        result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[2]);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 8\n", (int)result);

        for (UINT pass = 0; pass < num_passes; pass++)
        {
            (*d3dintf->effect.begin_pass)(curr_effect, pass);
            // add the primitives
            result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
            (*d3dintf->effect.end_pass)(curr_effect);
        }

        (*d3dintf->effect.end)(curr_effect);

        curr_effect = effect;

        //(*d3dintf->effect.set_float)(curr_effect, "PostPass", 1.0f);

        //blit(backbuffer, ct->last_texture, NULL, poly->type, vertnum, poly->count, d3d->width, d3d->height);

        result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 9\n", (int)result);

        (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[2]);

        (*d3dintf->effect.set_float)(curr_effect, "RawWidth", poly->texture != NULL ? (float)poly->texture->rawwidth : 8.0f);
        (*d3dintf->effect.set_float)(curr_effect, "RawHeight", poly->texture != NULL ? (float)poly->texture->rawheight : 8.0f);
        (*d3dintf->effect.set_float)(curr_effect, "WidthRatio", poly->texture != NULL ? (1.0f / (poly->texture->ustop - poly->texture->ustart)) : 0.0f);
        (*d3dintf->effect.set_float)(curr_effect, "HeightRatio", poly->texture != NULL ? (1.0f / (poly->texture->vstop - poly->texture->vstart)) : 0.0f);
        (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
        (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
        (*d3dintf->effect.set_float)(curr_effect, "PostPass", 0.0f);
        (*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion);

        (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

        for (UINT pass = 0; pass < num_passes; pass++)
        {
            (*d3dintf->effect.begin_pass)(curr_effect, pass);
            // add the primitives
            HRESULT result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
            (*d3dintf->effect.end_pass)(curr_effect);
        }

        (*d3dintf->effect.end)(curr_effect);
#endif

		poly->texture->cur_frame++;
		poly->texture->cur_frame %= options->yiq_phase_count;

		options->params_dirty = false;
	}
#if HLSL_VECTOR
    else if(PRIMFLAG_GET_VECTOR(poly->flags) && vector_enable)
    {
        d3d_render_target *rt = find_render_target(d3d->width, d3d->height, 0, 0);
        if (rt == NULL)
        {
            return;
        }

        lines_pending = true;

        curr_effect = vector_effect;
        //curr_effect = effect;

        if(options->params_dirty)
        {
            (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
            (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
        }

        float time_params[2] = { poly->line_time, options->vector_time_scale };
        float length_params[3] = { poly->line_length, options->vector_length_scale, options->vector_length_ratio };
        (*d3dintf->effect.set_vector)(curr_effect, "TimeParams", 2, time_params);
        (*d3dintf->effect.set_vector)(curr_effect, "LengthParams", 3, length_params);

        (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

        HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[0]);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

        for (UINT pass = 0; pass < num_passes; pass++)
        {
            (*d3dintf->effect.begin_pass)(curr_effect, pass);
            // add the primitives
            HRESULT result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
            (*d3dintf->effect.end_pass)(curr_effect);
        }

        (*d3dintf->effect.end)(curr_effect);
        result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

        curr_effect = effect;

        (*d3dintf->effect.set_float)(curr_effect, "FixedAlpha", 1.0f);
    }
    else if (PRIMFLAG_GET_VECTORBUF(poly->flags) && vector_enable)
    {
        //if (!lines_pending)
            //return;
        //lines_pending = false;

        d3d_info *d3d = (d3d_info *)window->drawdata;

        d3d_render_target *rt = find_render_target(d3d->width, d3d->height, 0, 0);
        if (rt == NULL)
        {
            return;
        }

        /* Bloom */
        curr_effect = downsample_effect;

        (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[0]);

        int bloom_size = (d3d->width < d3d->height) ? d3d->width : d3d->height;
        int bloom_index = 0;
        int bloom_width = d3d->width;
        int bloom_height = d3d->height;
        for(; bloom_size >= 2 && bloom_index < 11; bloom_size >>= 1)
        {
            float source_size[2] = { bloom_width, bloom_height };
            float target_size[2] = { bloom_width >> 1, bloom_height >> 1 };
            (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size);
            (*d3dintf->effect.set_vector)(curr_effect, "SourceSize", 2, source_size);

            (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

            (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", (bloom_index == 0) ? rt->texture[0] : rt->bloom_texture[bloom_index - 1]);

            HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->bloom_target[bloom_index]);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result);
            //result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
            //if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

            for (UINT pass = 0; pass < num_passes; pass++)
            {
                (*d3dintf->effect.begin_pass)(curr_effect, pass);
                // add the primitives
                result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
                if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
                (*d3dintf->effect.end_pass)(curr_effect);
            }

            (*d3dintf->effect.end)(curr_effect);

            bloom_index++;
            bloom_width >>= 1;
            bloom_height >>= 1;
        }

        /* Bloom composite pass*/
        curr_effect = bloom_effect;

        float target_size[2] = { d3d->width, d3d->height };
        (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size);

        (*d3dintf->effect.set_texture)(curr_effect, "DiffuseA", rt->texture[0]);
        (*d3dintf->effect.set_float)(curr_effect, "DiffuseScaleA", 1.0f);

        char name[9] = "Diffuse*";
        char scale[14] = "DiffuseScale*";
        for(int index = 1; index < bloom_index; index++)
        {
            name[7] = 'A' + index;
            scale[12] = 'A' + index;
            (*d3dintf->effect.set_texture)(curr_effect, name, rt->bloom_texture[index - 1]);
            (*d3dintf->effect.set_float)(curr_effect, scale, 1.0f);
        }
        for(int index = bloom_index; index < 11; index++)
        {
            name[7] = 'A' + index;
            scale[12] = 'A' + index;
            (*d3dintf->effect.set_texture)(curr_effect, name, black_texture);
            (*d3dintf->effect.set_float)(curr_effect, scale, 0.0f);
        }

        (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

        HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[1]);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result);
        //result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
        //if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

        for (UINT pass = 0; pass < num_passes; pass++)
        {
            (*d3dintf->effect.begin_pass)(curr_effect, pass);
            // add the primitives
            result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
            (*d3dintf->effect.end_pass)(curr_effect);
        }

        (*d3dintf->effect.end)(curr_effect);

		/* Phosphor */
		curr_effect = phosphor_effect;

		if(options->params_dirty)
		{
			(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
			(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
			(*d3dintf->effect.set_vector)(curr_effect, "Phosphor", 3, options->phosphor);
		}
		(*d3dintf->effect.set_float)(curr_effect, "TextureWidth", (float)d3d->width);
		(*d3dintf->effect.set_float)(curr_effect, "TextureHeight", (float)d3d->height);
		(*d3dintf->effect.set_float)(curr_effect, "Passthrough", 0.0f);

		(*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[1]);
		(*d3dintf->effect.set_texture)(curr_effect, "LastPass", rt->texture[2]);

		result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[0]);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result);
		result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
		if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);

		(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

		for (UINT pass = 0; pass < num_passes; pass++)
		{
			(*d3dintf->effect.begin_pass)(curr_effect, pass);
			// add the primitives
			result = (*d3dintf->device.draw_primitive)(d3d->device, D3DPT_TRIANGLELIST, 0, 2);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
			(*d3dintf->effect.end_pass)(curr_effect);
		}

		(*d3dintf->effect.end)(curr_effect);

        //curr_effect = effect;

        //blit(backbuffer, rt->bloom_texture[5], NULL, poly->type, vertnum, poly->count);
        //blit(rt->target[2], rt->texture[0], NULL, poly->type, vertnum, poly->count);
        blit(backbuffer, rt->texture[0], NULL, poly->type, vertnum, poly->count);
        //blit(backbuffer, rt->texture[0], NULL, poly->type, vertnum, poly->count);

        result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[0]);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
        result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);
        result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

        /*curr_effect = post_effect;

        (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->texture[0]);

        (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
        (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
		(*d3dintf->effect.set_float)(curr_effect, "RawWidth", (float)poly->texture->rawwidth);
		(*d3dintf->effect.set_float)(curr_effect, "RawHeight", (float)poly->texture->rawheight);
		(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / (poly->texture->ustop - poly->texture->ustart));
		(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / (poly->texture->vstop - poly->texture->vstart));

        result = (*d3dintf->device.set_render_target)(d3d->device, 0, rt->target[1]);
        if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

        (*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

        for (UINT pass = 0; pass < num_passes; pass++)
        {
            (*d3dintf->effect.begin_pass)(curr_effect, pass);
            // add the primitives
            result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
            if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
            (*d3dintf->effect.end_pass)(curr_effect);
        }

        (*d3dintf->effect.end)(curr_effect);*/

        vecbuf_type = poly->type;
        vecbuf_index = vertnum;
        vecbuf_count = poly->count;
    }
#endif
	else
	{
		(*d3dintf->effect.set_float)(curr_effect, "RawWidth", poly->texture != NULL ? (float)poly->texture->rawwidth : 8.0f);
		(*d3dintf->effect.set_float)(curr_effect, "RawHeight", poly->texture != NULL ? (float)poly->texture->rawheight : 8.0f);
		(*d3dintf->effect.set_float)(curr_effect, "WidthRatio", poly->texture != NULL ? (1.0f / (poly->texture->ustop - poly->texture->ustart)) : 0.0f);
		(*d3dintf->effect.set_float)(curr_effect, "HeightRatio", poly->texture != NULL ? (1.0f / (poly->texture->vstop - poly->texture->vstart)) : 0.0f);
		(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->width);
		(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->height);
		(*d3dintf->effect.set_float)(curr_effect, "PostPass", 0.0f);
		(*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion);

		(*d3dintf->effect.begin)(curr_effect, &num_passes, 0);

		for (UINT pass = 0; pass < num_passes; pass++)
		{
			(*d3dintf->effect.begin_pass)(curr_effect, pass);
			// add the primitives
			HRESULT result = (*d3dintf->device.draw_primitive)(d3d->device, poly->type, vertnum, poly->count);
			if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
			(*d3dintf->effect.end_pass)(curr_effect);
		}

		(*d3dintf->effect.end)(curr_effect);
	}
}



//============================================================
//  hlsl_info::end_draw
//============================================================

void hlsl_info::end_draw()
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	(*d3dintf->surface.release)(backbuffer);
}


//============================================================
//  hlsl_info::register_prescaled_texture
//============================================================

bool hlsl_info::register_prescaled_texture(d3d_texture_info *texture)
{
	return register_texture(texture, texture->rawwidth, texture->rawheight, texture->xprescale, texture->yprescale);
}


//============================================================
//  hlsl_info::add_cache_target - register a cache target
//============================================================
bool hlsl_info::add_cache_target(d3d_info* d3d, d3d_texture_info* info, int width, int height, int xprescale, int yprescale, int screen_index)
{
	d3d_cache_target* target = (d3d_cache_target*)global_alloc_clear(d3d_cache_target);

	if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale, false))
	{
		global_free(target);
		return false;
	}

	if (info != NULL)
	{
		target->width = info->texinfo.width;
		target->height = info->texinfo.height;
	}
	else
	{
		target->width = d3d->width;
		target->height = d3d->height;
	}

	target->next = cachehead;
	target->prev = NULL;

	target->screen_index = screen_index;

	if (cachehead != NULL)
	{
		cachehead->prev = target;
	}
	cachehead = target;

	return true;
}

d3d_render_target* hlsl_info::get_vector_target()
{
#if HLSL_VECTOR
	if (!vector_enable)
	{
		return false;
	}

	d3d_info *d3d = (d3d_info *)window->drawdata;

	return find_render_target(d3d->width, d3d->height, 0, 0);
#endif
	return NULL;
}

void hlsl_info::create_vector_target(render_primitive *prim)
{
#if HLSL_VECTOR
	d3d_info *d3d = (d3d_info *)window->drawdata;
	if (!add_render_target(d3d, NULL, d3d->width, d3d->height, 1, 1, true))
	{
		vector_enable = false;
	}
#endif
}

//============================================================
//  hlsl_info::add_render_target - register a render target
//============================================================

bool hlsl_info::add_render_target(d3d_info* d3d, d3d_texture_info* info, int width, int height, int xprescale, int yprescale, bool bloom)
{
	UINT32 screen_index = 0;
	UINT32 page_index = 0;
	if (info != NULL)
	{
		d3d_render_target *existing_target = find_render_target(info);
		if (existing_target != NULL)
		{
			remove_render_target(existing_target);
		}

		UINT32 screen_index_data = (UINT32)info->texinfo.osddata;
		screen_index = screen_index_data >> 1;
		page_index = screen_index_data & 1;
	}
	else
	{
		d3d_render_target *existing_target = find_render_target(d3d->width, d3d->height, 0, 0);
		if (existing_target != NULL)
		{
			remove_render_target(existing_target);
		}
	}

	d3d_render_target* target = (d3d_render_target*)global_alloc_clear(d3d_render_target);

	if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale, bloom))
	{
		global_free(target);
		return false;
	}

	if (info != NULL)
	{
		target->width = info->texinfo.width;
		target->height = info->texinfo.height;
	}
	else
	{
		target->width = d3d->width;
		target->height = d3d->height;
	}

	HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, target->target[0]);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
	result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);
	result = (*d3dintf->device.set_render_target)(d3d->device, 0, backbuffer);
	if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);

	target->screen_index = screen_index;
	target->page_index = page_index;

	d3d_cache_target* cache = find_cache_target(target->screen_index, target->width, target->height);
	if (cache == NULL)
	{
		if (!add_cache_target(d3d, info, width, height, xprescale, yprescale, target->screen_index))
		{
			global_free(target);
			return false;
		}
	}

	target->next = targethead;
	target->prev = NULL;

	if (targethead != NULL)
	{
		targethead->prev = target;
	}
	targethead = target;

	return true;
}

//============================================================
//  hlsl_info::enumerate_screens
//============================================================
void hlsl_info::enumerate_screens()
{
	screen_device_iterator iter(window->machine().root_device());
	num_screens = iter.count();
}


//============================================================
//  hlsl_info::register_texture
//============================================================

bool hlsl_info::register_texture(d3d_texture_info *texture)
{
	return register_texture(texture, texture->rawwidth, texture->rawheight, 1, 1);
}


//============================================================
//  hlsl_info::register_texture(d3d_texture_info, int, int, int, int)
//============================================================

bool hlsl_info::register_texture(d3d_texture_info *texture, int width, int height, int xscale, int yscale)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return 0;

	enumerate_screens();

	d3d_info *d3d = (d3d_info *)window->drawdata;

	int hlsl_prescale_x = prescale_force_x;
	int hlsl_prescale_y = prescale_force_y;

	// Find the nearest prescale factor that is over our screen size
	if (hlsl_prescale_x == 0)
	{
		hlsl_prescale_x = 1;
		while (width * xscale * hlsl_prescale_x <= d3d->width)
		{
			hlsl_prescale_x++;
		}
		hlsl_prescale_x--;
	}

	if (hlsl_prescale_y == 0)
	{
		hlsl_prescale_y = 1;
		while (height * yscale * hlsl_prescale_y <= d3d->height)
		{
			hlsl_prescale_y++;
		}
		hlsl_prescale_y--;
	}

	hlsl_prescale_x = ((hlsl_prescale_x == 0) ? 1 : hlsl_prescale_x);
	hlsl_prescale_y = ((hlsl_prescale_y == 0) ? 1 : hlsl_prescale_y);

	if (!add_render_target(d3d, texture, width, height, xscale * hlsl_prescale_x, yscale * hlsl_prescale_y))
		return false;

	options->params_dirty = true;

	return true;
}

//============================================================
//  hlsl_info::delete_resources
//============================================================

void hlsl_info::delete_resources(bool reset)
{
	if (!master_enable || !d3dintf->post_fx_available)
		return;

	initialized = false;

	if(write_ini && !reset)
	{
		emu_file file(downcast<windows_options &>(window->machine().options()).screen_post_fx_dir(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
		file_error filerr = open_next((d3d_info*)window->drawdata, file, downcast<windows_options &>(window->machine().options()).hlsl_ini_name(), "ini", 0);

		if (filerr != FILERR_NONE)
			return;

		file.printf("hlsl_enable            %d\n", master_enable ? 1 : 0);
		file.printf("hlsl_prescale_x        %d\n", prescale_force_x);
		file.printf("hlsl_prescale_y        %d\n", prescale_force_y);
		file.printf("hlsl_preset            %d\n", preset);
		file.printf("hlsl_snap_width        %d\n", snap_width);
		file.printf("hlsl_snap_height       %d\n", snap_height);
		file.printf("shadow_mask_alpha      %f\n", options->shadow_mask_alpha);
		file.printf("shadow_mask_texture    %s\n", options->shadow_mask_texture);
		file.printf("shadow_mask_x_count    %d\n", options->shadow_mask_count_x);
		file.printf("shadow_mask_y_count    %d\n", options->shadow_mask_count_y);
		file.printf("shadow_mask_usize      %f\n", options->shadow_mask_u_size);
		file.printf("shadow_mask_vsize      %f\n", options->shadow_mask_v_size);
		file.printf("curvature              %f\n", options->curvature);
		file.printf("pincushion             %f\n", options->pincushion);
		file.printf("scanline_alpha         %f\n", options->scanline_alpha);
		file.printf("scanline_size          %f\n", options->scanline_scale);
		file.printf("scanline_height        %f\n", options->scanline_height);
		file.printf("scanline_bright_scale  %f\n", options->scanline_bright_scale);
		file.printf("scanline_bright_offset %f\n", options->scanline_bright_offset);
		file.printf("scanline_jitter        %f\n", options->scanline_offset);
		file.printf("defocus                %f,%f\n", options->defocus[0], options->defocus[1]);
		file.printf("converge_x             %f,%f,%f\n", options->converge_x[0], options->converge_x[1], options->converge_x[2]);
		file.printf("converge_y             %f,%f,%f\n", options->converge_y[0], options->converge_y[1], options->converge_y[2]);
		file.printf("radial_converge_x      %f,%f,%f\n", options->radial_converge_x[0], options->radial_converge_x[1], options->radial_converge_x[2]);
		file.printf("radial_converge_y      %f,%f,%f\n", options->radial_converge_y[0], options->radial_converge_y[1], options->radial_converge_y[2]);
		file.printf("red_ratio              %f,%f,%f\n", options->red_ratio[0], options->red_ratio[1], options->red_ratio[2]);
		file.printf("grn_ratio              %f,%f,%f\n", options->grn_ratio[0], options->grn_ratio[1], options->grn_ratio[2]);
		file.printf("blu_ratio              %f,%f,%f\n", options->blu_ratio[0], options->blu_ratio[1], options->blu_ratio[2]);
		file.printf("saturation             %f\n", options->saturation);
		file.printf("offset                 %f,%f,%f\n", options->offset[0], options->offset[1], options->offset[2]);
		file.printf("scale                  %f,%f,%f\n", options->scale[0], options->scale[1], options->scale[2]);
		file.printf("power                  %f,%f,%f\n", options->power[0], options->power[1], options->power[2]);
		file.printf("floor                  %f,%f,%f\n", options->floor[0], options->floor[1], options->floor[2]);
		file.printf("phosphor_life          %f,%f,%f\n", options->phosphor[0], options->phosphor[1], options->phosphor[2]);
		file.printf("yiq_enable             %d\n", options->yiq_enable ? 1 : 0);
		file.printf("yiq_cc                 %f\n", options->yiq_cc);
		file.printf("yiq_a                  %f\n", options->yiq_a);
		file.printf("yiq_b                  %f\n", options->yiq_b);
		file.printf("yiq_o                  %f\n", options->yiq_o);
		file.printf("yiq_p                  %f\n", options->yiq_p);
		file.printf("yiq_n                  %f\n", options->yiq_n);
		file.printf("yiq_y                  %f\n", options->yiq_y);
		file.printf("yiq_i                  %f\n", options->yiq_i);
		file.printf("yiq_q                  %f\n", options->yiq_q);
		file.printf("yiq_scan_time          %f\n", options->yiq_scan_time);
		file.printf("yiq_phase_count        %d\n", options->yiq_phase_count);
        file.printf("vector_time_scale      %f\n", options->vector_time_scale);
        file.printf("vector_time_period     %f\n", options->vector_time_period);
        file.printf("vector_length_scale    %f\n", options->vector_length_scale);
        file.printf("vector_length_ratio    %f\n", options->vector_length_ratio);
	}

	while (targethead != NULL)
	{
		remove_render_target(targethead);
	}

#if HLSL_VECTOR
    if (downsample_effect != NULL)
    {
        (*d3dintf->effect.release)(downsample_effect);
        downsample_effect = NULL;
    }
    if (bloom_effect != NULL)
    {
        (*d3dintf->effect.release)(bloom_effect);
        bloom_effect = NULL;
    }
#endif
	if (effect != NULL)
	{
		(*d3dintf->effect.release)(effect);
		effect = NULL;
	}
	if (post_effect != NULL)
	{
		(*d3dintf->effect.release)(post_effect);
		post_effect = NULL;
	}
	if (prescale_effect != NULL)
	{
		(*d3dintf->effect.release)(prescale_effect);
		prescale_effect = NULL;
	}
	if (pincushion_effect != NULL)
	{
		(*d3dintf->effect.release)(pincushion_effect);
		pincushion_effect = NULL;
	}
	if (phosphor_effect != NULL)
	{
		(*d3dintf->effect.release)(phosphor_effect);
		phosphor_effect = NULL;
	}
	if (focus_effect != NULL)
	{
		(*d3dintf->effect.release)(focus_effect);
		focus_effect = NULL;
	}
	if (deconverge_effect != NULL)
	{
		(*d3dintf->effect.release)(deconverge_effect);
		deconverge_effect = NULL;
	}
	if (color_effect != NULL)
	{
		(*d3dintf->effect.release)(color_effect);
		color_effect = NULL;
	}
	if (yiq_encode_effect != NULL)
	{
		(*d3dintf->effect.release)(yiq_encode_effect);
		yiq_encode_effect = NULL;
	}
	if (yiq_decode_effect != NULL)
	{
		(*d3dintf->effect.release)(yiq_decode_effect);
		yiq_decode_effect = NULL;
	}

    if (black_texture != NULL)
    {
        (*d3dintf->texture.release)(black_texture);
        black_texture = NULL;
    }

	if (avi_copy_texture != NULL)
	{
		(*d3dintf->texture.release)(avi_copy_texture);
		avi_copy_texture = NULL;
	}

	if (avi_copy_surface != NULL)
	{
		(*d3dintf->surface.release)(avi_copy_surface);
		avi_copy_surface = NULL;
	}

	if (avi_final_texture != NULL)
	{
		(*d3dintf->texture.release)(avi_final_texture);
		avi_final_texture = NULL;
	}

	if (avi_final_target != NULL)
	{
		(*d3dintf->surface.release)(avi_final_target);
		avi_final_target = NULL;
	}

	shadow_bitmap.reset();
}


//============================================================
//  get_vector
//============================================================

static void get_vector(const char *data, int count, float *out, int report_error)
{
	if (count > 3)
	{
		if (sscanf(data, "%f,%f,%f,%f", &out[0], &out[1], &out[2], &out[3]) < 4 && report_error)
			mame_printf_error("Illegal quad vector value = %s\n", data);
	}
	else if(count > 2)
	{
		if (sscanf(data, "%f,%f,%f", &out[0], &out[1], &out[2]) < 3 && report_error)
			mame_printf_error("Illegal triple vector value = %s\n", data);
	}
	else if(count > 1)
	{
		if (sscanf(data, "%f,%f", &out[0], &out[1]) < 2 && report_error)
			mame_printf_error("Illegal double vector value = %s\n", data);
	}
	else if(count > 0)
	{
		if (sscanf(data, "%f", &out[0]) < 1 && report_error)
			mame_printf_error("Illegal single vector value = %s\n", data);
	}
}


/*-------------------------------------------------
    slider_alloc - allocate a new slider entry
    currently duplicated from ui.c, this could
    be done in a more ideal way.
-------------------------------------------------*/

static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg)
{
	int size = sizeof(slider_state) + strlen(title);
	slider_state *state = (slider_state *)auto_alloc_array_clear(machine, UINT8, size);

	state->minval = minval;
	state->defval = defval;
	state->maxval = maxval;
	state->incval = incval;
	state->update = update;
	state->arg = arg;
	strcpy(state->description, title);

	return state;
}


//============================================================
//  assorted global slider accessors
//============================================================

static INT32 slider_set(float *option, float scale, const char *fmt, astring *string, INT32 newval)
{
	if (option != NULL && newval != SLIDER_NOCHANGE) *option = (float)newval * scale;
	if (string != NULL) string->printf(fmt, *option);
	return floor(*option / scale + 0.5f);
}

static INT32 slider_shadow_mask_alpha(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	return slider_set(&(((hlsl_options*)arg)->shadow_mask_alpha), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_shadow_mask_x_count(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	hlsl_options *options = (hlsl_options*)arg;
	if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_x = newval;
	if (string != NULL) string->printf("%d", options->shadow_mask_count_x);
	options->params_dirty = true;
	return options->shadow_mask_count_x;
}

static INT32 slider_shadow_mask_y_count(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	hlsl_options *options = (hlsl_options*)arg;
	if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_y = newval;
	if (string != NULL) string->printf("%d", options->shadow_mask_count_y);
	options->params_dirty = true;
	return options->shadow_mask_count_y;
}

static INT32 slider_shadow_mask_usize(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->shadow_mask_u_size), 1.0f / 32.0f, "%2.5f", string, newval);
}

static INT32 slider_shadow_mask_vsize(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->shadow_mask_v_size), 1.0f / 32.0f, "%2.5f", string, newval);
}

static INT32 slider_curvature(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->curvature), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_pincushion(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->pincushion), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_scanline_alpha(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scanline_alpha), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_scanline_scale(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scanline_scale), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_scanline_height(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scanline_height), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_scanline_bright_scale(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scanline_bright_scale), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_scanline_bright_offset(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scanline_bright_offset), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_scanline_offset(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scanline_offset), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_defocus_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->defocus[0]), 0.5f, "%2.1f", string, newval);
}

static INT32 slider_defocus_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->defocus[1]), 0.5f, "%2.1f", string, newval);
}

static INT32 slider_post_defocus_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->defocus[2]), 0.5f, "%2.1f", string, newval);
}

static INT32 slider_post_defocus_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->defocus[3]), 0.5f, "%2.1f", string, newval);
}

static INT32 slider_red_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->converge_x[0]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_red_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->converge_y[0]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_green_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->converge_x[1]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_green_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->converge_y[1]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_blue_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->converge_x[2]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_blue_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->converge_y[2]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_red_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->radial_converge_x[0]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_red_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->radial_converge_y[0]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_green_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->radial_converge_x[1]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_green_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->radial_converge_y[1]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_blue_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->radial_converge_x[2]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_blue_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->radial_converge_y[2]), 0.1f, "%3.1f", string, newval);
}

static INT32 slider_red_from_r(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->red_ratio[0]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_red_from_g(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->red_ratio[1]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_red_from_b(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->red_ratio[2]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_green_from_r(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->grn_ratio[0]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_green_from_g(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->grn_ratio[1]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_green_from_b(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->grn_ratio[2]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_blue_from_r(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->blu_ratio[0]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_blue_from_g(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->blu_ratio[1]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_blue_from_b(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->blu_ratio[2]), 0.005f, "%2.3f", string, newval);
}

static INT32 slider_red_offset(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->offset[0]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_green_offset(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->offset[1]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_blue_offset(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->offset[2]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_red_scale(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scale[0]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_green_scale(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scale[1]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_blue_scale(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->scale[2]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_red_power(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->power[0]), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_green_power(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->power[1]), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_blue_power(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->power[2]), 0.05f, "%2.2f", string, newval);
}

static INT32 slider_red_floor(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->floor[0]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_green_floor(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->floor[1]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_blue_floor(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->floor[2]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_red_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->phosphor[0]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_green_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->phosphor[1]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_blue_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->phosphor[2]), 0.01f, "%2.2f", string, newval);
}

static INT32 slider_saturation(running_machine &machine, void *arg, astring *string, INT32 newval)
{
	((hlsl_options*)arg)->params_dirty = true;
	return slider_set(&(((hlsl_options*)arg)->saturation), 0.01f, "%2.2f", string, newval);
}

//============================================================
//  init_slider_list
//============================================================

slider_state *hlsl_info::init_slider_list()
{
	if (!master_enable || !d3dintf->post_fx_available)
	{
		g_slider_list = NULL;
		return NULL;
	}

	slider_state *listhead = NULL;
	slider_state **tailptr = &listhead;
	astring string;

	*tailptr = slider_alloc(window->machine(), "Shadow Mask Darkness", 0, 0, 100, 1, slider_shadow_mask_alpha, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Shadow Mask X Count", 1, 640, 1024, 1, slider_shadow_mask_x_count, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Shadow Mask Y Count", 1, 480, 1024, 1, slider_shadow_mask_y_count, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Shadow Mask Pixel Count X", 1, 3, 32, 1, slider_shadow_mask_usize, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Shadow Mask Pixel Count Y", 1, 3, 32, 1, slider_shadow_mask_vsize, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Screen Curvature", 0, 0, 100, 1, slider_curvature, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Image Pincushion", 0, 0, 100, 1, slider_pincushion, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Scanline Darkness", 0, 0, 100, 1, slider_scanline_alpha, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Scanline Screen Height", 1, 20, 80, 1, slider_scanline_scale, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Scanline Indiv. Height", 1, 10, 80, 1, slider_scanline_height, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Scanline Brightness", 0, 20, 40, 1, slider_scanline_bright_scale, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Scanline Brightness Overdrive", 0, 12, 20, 1, slider_scanline_bright_offset, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Scanline Jitter", 0, 0, 40, 1, slider_scanline_offset, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Defocus X", 0, 0, 64, 1, slider_defocus_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Defocus Y", 0, 0, 64, 1, slider_defocus_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Phosphor Defocus X", 0, 0, 64, 1, slider_post_defocus_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Phosphor Defocus Y", 0, 0, 64, 1, slider_post_defocus_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Position Offset X", -1500, 0, 1500, 1, slider_red_converge_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Position Offset Y", -1500, 0, 1500, 1, slider_red_converge_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Position Offset X", -1500, 0, 1500, 1, slider_green_converge_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Position Offset Y", -1500, 0, 1500, 1, slider_green_converge_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Position Offset X", -1500, 0, 1500, 1, slider_blue_converge_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Position Offset Y", -1500, 0, 1500, 1, slider_blue_converge_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Convergence X", -1500, 0, 1500, 1, slider_red_radial_converge_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Convergence Y", -1500, 0, 1500, 1, slider_red_radial_converge_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Convergence X", -1500, 0, 1500, 1, slider_green_radial_converge_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Convergence Y", -1500, 0, 1500, 1, slider_green_radial_converge_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Convergence X", -1500, 0, 1500, 1, slider_blue_radial_converge_x, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Convergence Y", -1500, 0, 1500, 1, slider_blue_radial_converge_y, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Output from Red Input", -400, 0, 400, 5, slider_red_from_r, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Output from Green Input", -400, 0, 400, 5, slider_red_from_g, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Output from Blue Input", -400, 0, 400, 5, slider_red_from_b, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Output from Red Input", -400, 0, 400, 5, slider_green_from_r, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Output from Green Input", -400, 0, 400, 5, slider_green_from_g, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Output from Blue Input", -400, 0, 400, 5, slider_green_from_b, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Output from Red Input", -400, 0, 400, 5, slider_blue_from_r, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Output from Green Input", -400, 0, 400, 5, slider_blue_from_g, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Output from Blue Input", -400, 0, 400, 5, slider_blue_from_b, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red DC Offset", -100, 0, 100, 1, slider_red_offset, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green DC Offset", -100, 0, 100, 1, slider_green_offset, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue DC Offset", -100, 0, 100, 1, slider_blue_offset, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Scale", -200, 100, 200, 1, slider_red_scale, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Scale", -200, 100, 200, 1, slider_green_scale, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Scale", -200, 100, 200, 1, slider_blue_scale, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Power", -80, 20, 80, 1, slider_red_power, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Power", -80, 20, 80, 1, slider_green_power, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Power", -80, 20, 80, 1, slider_blue_power, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Floor", 0, 0, 100, 1, slider_red_floor, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Floor", 0, 0, 100, 1, slider_green_floor, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Floor", 0, 0, 100, 1, slider_blue_floor, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Red Phosphor Life", 0, 0, 100, 1, slider_red_phosphor_life, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Green Phosphor Life", 0, 0, 100, 1, slider_green_phosphor_life, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Blue Phosphor Life", 0, 0, 100, 1, slider_blue_phosphor_life, (void*)options); tailptr = &(*tailptr)->next;
	*tailptr = slider_alloc(window->machine(), "Saturation", 0, 100, 400, 1, slider_saturation, (void*)options); tailptr = &(*tailptr)->next;

	return listhead;
}

//============================================================
//  get_slider_list
//============================================================

void *windows_osd_interface::get_slider_list()
{
	return (void*)g_slider_list;
}



// NOTE: The function below is taken directly from src/emu/video.c and should likely be moved into a global helper function.
//-------------------------------------------------
//  open_next - open the next non-existing file of
//  type filetype according to our numbering
//  scheme
//-------------------------------------------------

static file_error open_next(d3d_info *d3d, emu_file &file, const char *templ, const char *extension, int idx)
{
	UINT32 origflags = file.openflags();

	// handle defaults
	const char *snapname = templ ? templ : d3d->window->machine().options().snap_name();

	if (snapname == NULL || snapname[0] == 0)
		snapname = "%g/%i";
	astring snapstr(snapname);

	// strip any extension in the provided name
	int index = snapstr.rchr(0, '.');
	if (index != -1)
		snapstr.substr(0, index);

	// handle %d in the template (for image devices)
	astring snapdev("%d_");
	int pos = snapstr.find(0, snapdev);

	if (pos != -1)
	{
		// if more %d are found, revert to default and ignore them all
		if (snapstr.find(pos + 3, snapdev) != -1)
			snapstr.cpy("%g/%i");
		// else if there is a single %d, try to create the correct snapname
		else
		{
			int name_found = 0;

			// find length of the device name
			int end1 = snapstr.find(pos + 3, "/");
			int end2 = snapstr.find(pos + 3, "%");
			int end = -1;

			if ((end1 != -1) && (end2 != -1))
				end = MIN(end1, end2);
			else if (end1 != -1)
				end = end1;
			else if (end2 != -1)
				end = end2;
			else
				end = snapstr.len();

			if (end - pos < 3)
				fatalerror("Something very wrong is going on!!!\n");

			// copy the device name to an astring
			astring snapdevname;
			snapdevname.cpysubstr(snapstr, pos + 3, end - pos - 3);

			// verify that there is such a device for this system
			image_interface_iterator iter(d3d->window->machine().root_device());
			for (device_image_interface *image = iter.first(); image != NULL; iter.next())
			{
				// get the device name
				astring tempdevname(image->brief_instance_name());

				if (snapdevname.cmp(tempdevname) == 0)
				{
					// verify that such a device has an image mounted
					if (image->basename() != NULL)
					{
						astring filename(image->basename());

						// strip extension
						filename.substr(0, filename.rchr(0, '.'));

						// setup snapname and remove the %d_
						snapstr.replace(0, snapdevname, filename);
						snapstr.del(pos, 3);

						name_found = 1;
					}
				}
			}

			// or fallback to default
			if (name_found == 0)
				snapstr.cpy("%g/%i");
		}
	}

	// add our own index
	// add our own extension
	snapstr.cat(".").cat(extension);

	// substitute path and gamename up front
	snapstr.replace(0, "/", PATH_SEPARATOR);
	snapstr.replace(0, "%g", d3d->window->machine().basename());

	// determine if the template has an index; if not, we always use the same name
	astring fname;
	if (snapstr.find(0, "%i") == -1)
		fname.cpy(snapstr);

	// otherwise, we scan for the next available filename
	else
	{
		// try until we succeed
		astring seqtext;
		file.set_openflags(OPEN_FLAG_READ);
		for (int seq = 0; ; seq++)
		{
			// build up the filename
			fname.cpy(snapstr).replace(0, "%i", seqtext.format("%04d_%d", seq, idx).cstr());

			// try to open the file; stop when we fail
			file_error filerr = file.open(fname);
			if (filerr != FILERR_NONE)
				break;
		}
	}

	// create the final file
	file.set_openflags(origflags);
	return file.open(fname);
}