a7493570ddc423787c5d3373c63b58c58046faa2
[mupen64plus-pandora.git] / source / rice_gles / src / Config.cpp
1 /*
2 Copyright (C) 2003 Rice1964
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18 */
19
20 #include <vector>
21 #include <fstream>
22
23 #include <stdlib.h>
24
25 #define M64P_PLUGIN_PROTOTYPES 1
26 #include "osal_preproc.h"
27 #include "m64p_types.h"
28 #include "m64p_plugin.h"
29 #include "m64p_config.h"
30
31 #include "Config.h"
32 #include "Debugger.h"
33 #include "DeviceBuilder.h"
34 #include "RenderBase.h"
35 #include "TextureManager.h"
36 #include "Video.h"
37
38 #define INI_FILE        "RiceVideoLinux.ini"
39
40 static m64p_handle l_ConfigVideoRice = NULL;
41 static m64p_handle l_ConfigVideoGeneral = NULL;
42
43 static int FindIniEntry(uint32 dwCRC1, uint32 dwCRC2, uint8 nCountryID, char* szName, int PrintInfo); 
44
45 const char *frameBufferSettings[] =
46 {
47 "None (default)",
48 "Hide Framebuffer Effects",
49 "Basic Framebuffer",
50 "Basic & Write Back",
51 "Write Back & Reload",
52 "Write Back Every Frame",
53 "With Emulator",
54 "Basic Framebuffer & With Emulator",
55 "With Emulator Read Only",
56 "With Emulator Write Only",
57 };
58
59 const int resolutions[][2] =
60 {
61 {320, 240},
62 {400, 300},
63 {480, 360},
64 {512, 384},
65 {640, 480},
66 {800, 480},
67 {800, 600},
68 {1024, 768},
69 {1152, 864},
70 {1280, 960},
71 {1400, 1050},
72 {1600, 1200},
73 {1920, 1440},
74 {2048, 1536},
75 };
76 const int numberOfResolutions = sizeof(resolutions)/sizeof(int)/2;
77
78 const char* resolutionsS[] =
79 {
80 "320 x 240",
81 "400 x 300",
82 "480 x 360",
83 "512 x 384",
84 "640 x 480",
85 "800 x 480",
86 "800 x 600",
87 "1024 x 768",
88 "1152 x 864",
89 "1280 x 960",
90 "1400 x 1050",
91 "1600 x 1200",
92 "1920 x 1440",
93 "2048 x 1536"
94 };
95
96 const char *frameBufferWriteBackControlSettings[] =
97 {
98 "Every Frame (default)",
99 "Every 2 Frames",
100 "Every 3 Frames",
101 "Every 4 Frames",
102 "Every 5 Frames",
103 "Every 6 Frames",
104 "Every 7 Frames",
105 "Every 8 Frames",
106 };
107
108 const char *renderToTextureSettings[] =
109 {
110 "None (default)",
111 "Hide Render-to-texture Effects",
112 "Basic Render-to-texture",
113 "Basic & Write Back",
114 "Write Back & Reload",
115 };
116
117 const char *screenUpdateSettings[] =
118 {
119 "At VI origin update",
120 "At VI origin change",
121 "At CI change",
122 "At the 1st CI change",
123 "At the 1st drawing",
124 "Before clear the screen",
125 "At VI origin update after screen is drawn (default)",
126 };
127
128 WindowSettingStruct windowSetting;
129 GlobalOptions options;
130 RomOptions defaultRomOptions;
131 RomOptions currentRomOptions;
132 FrameBufferOptions frameBufferOptions;
133 std::vector<IniSection> IniSections;
134 bool    bIniIsChanged = false;
135 char    szIniFileName[300];
136
137 SettingInfo TextureQualitySettings[] =
138 {
139 {"Default", FORCE_DEFAULT_FILTER},
140 {"32-bit Texture", FORCE_POINT_FILTER},
141 {"16-bit Texture", FORCE_LINEAR_FILTER},
142 };
143
144 SettingInfo ForceTextureFilterSettings[] =
145 {
146 {"N64 Default Texture Filter",  FORCE_DEFAULT_FILTER},
147 {"Force Nearest Filter (faster, low quality)", FORCE_POINT_FILTER},
148 {"Force Linear Filter (slower, better quality)", FORCE_LINEAR_FILTER},
149 };
150
151 SettingInfo TextureEnhancementSettings[] =
152 {
153 {"N64 original texture (No enhancement)", TEXTURE_NO_ENHANCEMENT},
154 {"2x (Double the texture size)", TEXTURE_2X_ENHANCEMENT},
155 {"2xSaI", TEXTURE_2XSAI_ENHANCEMENT},
156 {"hq2x", TEXTURE_HQ2X_ENHANCEMENT},
157 {"lq2x", TEXTURE_LQ2X_ENHANCEMENT},
158 {"hq4x", TEXTURE_HQ4X_ENHANCEMENT},
159 {"Sharpen", TEXTURE_SHARPEN_ENHANCEMENT},
160 {"Sharpen More", TEXTURE_SHARPEN_MORE_ENHANCEMENT},
161 };
162
163 SettingInfo TextureEnhancementControlSettings[] =
164 {
165 {"Normal", TEXTURE_ENHANCEMENT_NORMAL},
166 {"Smooth", TEXTURE_ENHANCEMENT_WITH_SMOOTH_FILTER_1},
167 {"Less smooth", TEXTURE_ENHANCEMENT_WITH_SMOOTH_FILTER_2},
168 {"2xSaI smooth", TEXTURE_ENHANCEMENT_WITH_SMOOTH_FILTER_3},
169 {"Less 2xSaI smooth", TEXTURE_ENHANCEMENT_WITH_SMOOTH_FILTER_4},
170 };
171
172 SettingInfo colorQualitySettings[] =
173 {
174 {"16-bit", TEXTURE_FMT_A4R4G4B4},
175 {"32-bit (def)", TEXTURE_FMT_A8R8G8B8},
176 };
177
178 const char* strDXDeviceDescs[] = { "HAL", "REF" };
179
180 SettingInfo openGLDepthBufferSettings[] =
181 {
182 {"16-bit (def)", 16},
183 {"32-bit", 32},
184 };
185
186 RenderEngineSetting OpenGLRenderSettings[] =
187 {
188 {"To Fit Your Video Card", OGL_DEVICE},
189 {"OpenGL 1.1 (Lowest)",  OGL_1_1_DEVICE},
190 {"OpenGL 1.2/1.3", OGL_1_2_DEVICE},
191 {"OpenGL 1.4", OGL_1_4_DEVICE},
192 {"OpenGL 1.4, the 2nd combiner",  OGL_1_4_V2_DEVICE},
193 {"OpenGL for Nvidia TNT or better", OGL_TNT2_DEVICE},
194 {"OpenGL for Nvidia GeForce or better ", NVIDIA_OGL_DEVICE},
195 {"OpenGL Fragment Program Extension", OGL_FRAGMENT_PROGRAM},
196 };
197
198 SettingInfo OnScreenDisplaySettings[] =
199 {
200 {"Display Nothing", ONSCREEN_DISPLAY_NOTHING},
201 {"Display DList Per Second", ONSCREEN_DISPLAY_DLIST_PER_SECOND},
202 {"Display Frame Per Second", ONSCREEN_DISPLAY_FRAME_PER_SECOND},
203 {"Display Debug Information Only", ONSCREEN_DISPLAY_DEBUG_INFORMATION_ONLY},
204 {"Display Messages From CPU Core Only", ONSCREEN_DISPLAY_TEXT_FROM_CORE_ONLY},
205 {"Display DList Per Second With Core Msgs", ONSCREEN_DISPLAY_DLIST_PER_SECOND_WITH_CORE_MSG},
206 {"Display Frame Per Second With Core Msgs", ONSCREEN_DISPLAY_FRAME_PER_SECOND_WITH_CORE_MSG},
207 {"Display Debug Information With Core Msgs", ONSCREEN_DISPLAY_DEBUG_INFORMATION_WITH_CORE_MSG},
208 };
209
210 const int numberOfOpenGLRenderEngineSettings = sizeof(OpenGLRenderSettings)/sizeof(RenderEngineSetting);
211
212 void GenerateFrameBufferOptions(void)
213 {
214     if( CDeviceBuilder::GetGeneralDeviceType() == OGL_DEVICE )
215     {
216         // OpenGL does not support much yet
217         if( currentRomOptions.N64FrameBufferEmuType != FRM_BUF_NONE )
218             currentRomOptions.N64FrameBufferEmuType = FRM_BUF_IGNORE;
219         if( currentRomOptions.N64RenderToTextureEmuType != TXT_BUF_NONE )
220             currentRomOptions.N64RenderToTextureEmuType = TXT_BUF_IGNORE;
221     }
222
223     frameBufferOptions.bUpdateCIInfo            = false;
224
225     frameBufferOptions.bCheckBackBufs           = false;
226     frameBufferOptions.bWriteBackBufToRDRAM     = false;
227     frameBufferOptions.bLoadBackBufFromRDRAM    = false;
228
229     frameBufferOptions.bIgnore                  = true;
230
231     frameBufferOptions.bSupportRenderTextures           = false;
232     frameBufferOptions.bCheckRenderTextures         = false;
233     frameBufferOptions.bRenderTextureWriteBack          = false;
234     frameBufferOptions.bLoadRDRAMIntoRenderTexture      = false;
235
236     frameBufferOptions.bProcessCPUWrite         = false;
237     frameBufferOptions.bProcessCPURead          = false;
238     frameBufferOptions.bAtEachFrameUpdate       = false;
239     frameBufferOptions.bIgnoreRenderTextureIfHeightUnknown      = false;
240
241     switch( currentRomOptions.N64FrameBufferEmuType )
242     {
243     case FRM_BUF_NONE:
244         break;
245     case FRM_BUF_COMPLETE:
246         frameBufferOptions.bAtEachFrameUpdate       = true;
247         frameBufferOptions.bProcessCPUWrite         = true;
248         frameBufferOptions.bProcessCPURead          = true;
249         frameBufferOptions.bUpdateCIInfo            = true;
250         break;
251     case FRM_BUF_WRITEBACK_AND_RELOAD:
252         frameBufferOptions.bLoadBackBufFromRDRAM    = true;
253     case FRM_BUF_BASIC_AND_WRITEBACK:
254         frameBufferOptions.bWriteBackBufToRDRAM     = true;
255     case FRM_BUF_BASIC:
256         frameBufferOptions.bCheckBackBufs           = true;
257     case FRM_BUF_IGNORE:
258         frameBufferOptions.bUpdateCIInfo            = true;
259         break;
260     case FRM_BUF_BASIC_AND_WITH_EMULATOR:
261         // Banjo Kazooie
262         frameBufferOptions.bCheckBackBufs           = true;
263     case FRM_BUF_WITH_EMULATOR:
264         frameBufferOptions.bUpdateCIInfo            = true;
265         frameBufferOptions.bProcessCPUWrite         = true;
266         frameBufferOptions.bProcessCPURead          = true;
267         break;
268     case FRM_BUF_WITH_EMULATOR_READ_ONLY:
269         frameBufferOptions.bUpdateCIInfo            = true;
270         frameBufferOptions.bProcessCPURead          = true;
271         break;
272     case FRM_BUF_WITH_EMULATOR_WRITE_ONLY:
273         frameBufferOptions.bUpdateCIInfo            = true;
274         frameBufferOptions.bProcessCPUWrite         = true;
275         break;
276     }
277
278     switch( currentRomOptions.N64RenderToTextureEmuType )
279     {
280     case TXT_BUF_NONE:
281         frameBufferOptions.bSupportRenderTextures           = false;
282         break;
283     case TXT_BUF_WRITE_BACK_AND_RELOAD:
284         frameBufferOptions.bLoadRDRAMIntoRenderTexture      = true;
285     case TXT_BUF_WRITE_BACK:
286         frameBufferOptions.bRenderTextureWriteBack          = true;
287     case TXT_BUF_NORMAL:
288         frameBufferOptions.bCheckRenderTextures         = true;
289         frameBufferOptions.bIgnore                  = false;
290     case TXT_BUF_IGNORE:
291         frameBufferOptions.bUpdateCIInfo            = true;
292         frameBufferOptions.bSupportRenderTextures           = true;
293         break;
294     }
295
296     if( currentRomOptions.screenUpdateSetting >= SCREEN_UPDATE_AT_CI_CHANGE )
297     {
298         frameBufferOptions.bUpdateCIInfo = true;
299     }
300 }
301
302 BOOL InitConfiguration(void)
303 {
304     if (ConfigOpenSection("Video-General", &l_ConfigVideoGeneral) != M64ERR_SUCCESS)
305     {
306         DebugMessage(M64MSG_ERROR, "Unable to open Video-General configuration section");
307         return FALSE;
308     }
309     if (ConfigOpenSection("Video-Rice", &l_ConfigVideoRice) != M64ERR_SUCCESS)
310     {
311         DebugMessage(M64MSG_ERROR, "Unable to open Video-Rice configuration section");
312         return FALSE;
313     }
314
315     ConfigSetDefaultBool(l_ConfigVideoGeneral, "Fullscreen", 1, "Use fullscreen mode if True, or windowed mode if False ");
316     ConfigSetDefaultInt(l_ConfigVideoGeneral, "ScreenWidth", 640, "Width of output window or fullscreen width");
317     ConfigSetDefaultInt(l_ConfigVideoGeneral, "ScreenHeight", 480, "Height of output window or fullscreen height");
318     ConfigSetDefaultBool(l_ConfigVideoGeneral, "VerticalSync", 0, "If true, activate the SDL_GL_SWAP_CONTROL attribute");
319
320     ConfigSetDefaultInt(l_ConfigVideoRice, "FrameBufferSetting", FRM_BUF_NONE, "Frame Buffer Emulation (0=ROM default, 1=disable)");
321     ConfigSetDefaultInt(l_ConfigVideoRice, "FrameBufferWriteBackControl", FRM_BUF_WRITEBACK_NORMAL, "Frequency to write back the frame buffer (0=every frame, 1=every other frame, etc)");
322     ConfigSetDefaultInt(l_ConfigVideoRice, "RenderToTexture", TXT_BUF_NONE, "Render-to-texture emulation (0=none, 1=ignore, 2=normal, 3=write back, 4=write back and reload)");
323 #if defined(WIN32)
324     ConfigSetDefaultInt(l_ConfigVideoRice, "ScreenUpdateSetting", SCREEN_UPDATE_AT_1ST_CI_CHANGE, "Control when the screen will be updated (0=ROM default, 1=VI origin update, 2=VI origin change, 3=CI change, 4=first CI change, 5=first primitive draw, 6=before screen clear, 7=after screen drawn)");  // SCREEN_UPDATE_AT_VI_UPDATE_AND_DRAWN
325 #else
326     ConfigSetDefaultInt(l_ConfigVideoRice, "ScreenUpdateSetting", SCREEN_UPDATE_AT_VI_UPDATE, "Control when the screen will be updated (0=ROM default, 1=VI origin update, 2=VI origin change, 3=CI change, 4=first CI change, 5=first primitive draw, 6=before screen clear, 7=after screen drawn)");  // SCREEN_UPDATE_AT_VI_UPDATE_AND_DRAWN
327 #endif
328     ConfigSetDefaultBool(l_ConfigVideoRice, "NormalAlphaBlender", FALSE, "Force to use normal alpha blender");
329     ConfigSetDefaultBool(l_ConfigVideoRice, "FastTextureLoading", FALSE, "Use a faster algorithm to speed up texture loading and CRC computation");
330     ConfigSetDefaultBool(l_ConfigVideoRice, "AccurateTextureMapping", TRUE, "Use different texture coordinate clamping code");
331     ConfigSetDefaultBool(l_ConfigVideoRice, "InN64Resolution", FALSE, "Force emulated frame buffers to be in N64 native resolution");
332     ConfigSetDefaultBool(l_ConfigVideoRice, "SaveVRAM", FALSE, "Try to reduce Video RAM usage (should never be used)");
333     ConfigSetDefaultBool(l_ConfigVideoRice, "DoubleSizeForSmallTxtrBuf", FALSE, "Enable this option to have better render-to-texture quality");
334     ConfigSetDefaultBool(l_ConfigVideoRice, "DefaultCombinerDisable", FALSE, "Force to use normal color combiner");
335
336     ConfigSetDefaultBool(l_ConfigVideoRice, "EnableHacks", TRUE, "Enable game-specific settings from INI file");
337     ConfigSetDefaultBool(l_ConfigVideoRice, "WinFrameMode", FALSE, "If enabled, graphics will be drawn in WinFrame mode instead of solid and texture mode");
338     ConfigSetDefaultBool(l_ConfigVideoRice, "FullTMEMEmulation", FALSE, "N64 Texture Memory Full Emulation (may fix some games, may break others)");
339     ConfigSetDefaultBool(l_ConfigVideoRice, "OpenGLVertexClipper", FALSE, "Enable vertex clipper for fog operations");
340     ConfigSetDefaultBool(l_ConfigVideoRice, "EnableSSE", TRUE, "Enable/Disable SSE optimizations for capable CPUs");
341     ConfigSetDefaultBool(l_ConfigVideoRice, "EnableVertexShader", FALSE, "Use GPU vertex shader");
342     ConfigSetDefaultBool(l_ConfigVideoRice, "SkipFrame", FALSE, "If this option is enabled, the plugin will skip every other frame");
343     ConfigSetDefaultBool(l_ConfigVideoRice, "TexRectOnly", FALSE, "If enabled, texture enhancement will be done only for TxtRect ucode");
344     ConfigSetDefaultBool(l_ConfigVideoRice, "SmallTextureOnly", FALSE, "If enabled, texture enhancement will be done only for textures width+height<=128");
345     ConfigSetDefaultBool(l_ConfigVideoRice, "LoadHiResCRCOnly", TRUE, "Select hi-resolution textures based only on the CRC and ignore format+size information (Glide64 compatibility)");
346     ConfigSetDefaultBool(l_ConfigVideoRice, "LoadHiResTextures", FALSE, "Enable hi-resolution texture file loading");
347     ConfigSetDefaultBool(l_ConfigVideoRice, "DumpTexturesToFiles", FALSE, "Enable texture dumping");
348     ConfigSetDefaultBool(l_ConfigVideoRice, "ShowFPS", FALSE, "Display On-screen FPS");
349
350     ConfigSetDefaultInt(l_ConfigVideoRice, "Mipmapping", 2, "Use Mipmapping? 0=no, 1=nearest, 2=bilinear, 3=trilinear");
351     ConfigSetDefaultInt(l_ConfigVideoRice, "FogMethod", 0, "Enable, Disable or Force fog generation (0=Disable, 1=Enable n64 choose, 2=Force Fog)");
352     ConfigSetDefaultInt(l_ConfigVideoRice, "ForceTextureFilter", 0, "Force to use texture filtering or not (0=auto: n64 choose, 1=force no filtering, 2=force filtering)");
353     ConfigSetDefaultInt(l_ConfigVideoRice, "TextureEnhancement", 0, "Primary texture enhancement filter (0=None, 1=2X, 2=2XSAI, 3=HQ2X, 4=LQ2X, 5=HQ4X, 6=Sharpen, 7=Sharpen More, 8=External, 9=Mirrored)");
354     ConfigSetDefaultInt(l_ConfigVideoRice, "TextureEnhancementControl", 0, "Secondary texture enhancement filter (0 = none, 1-4 = filtered)");
355     ConfigSetDefaultInt(l_ConfigVideoRice, "TextureQuality", TXT_QUALITY_DEFAULT, "Color bit depth to use for textures (0=default, 1=32 bits, 2=16 bits)");
356     ConfigSetDefaultInt(l_ConfigVideoRice, "OpenGLDepthBufferSetting", 16, "Z-buffer depth (only 16 or 32)");
357     ConfigSetDefaultInt(l_ConfigVideoRice, "MultiSampling", 0, "Enable/Disable MultiSampling (0=off, 2,4,8,16=quality)");
358     ConfigSetDefaultInt(l_ConfigVideoRice, "ColorQuality", TEXTURE_FMT_A8R8G8B8, "Color bit depth for rendering window (0=32 bits, 1=16 bits)");
359     ConfigSetDefaultInt(l_ConfigVideoRice, "OpenGLRenderSetting", OGL_DEVICE, "OpenGL level to support (0=auto, 1=OGL_1.1, 2=OGL_1.2, 3=OGL_1.3, 4=OGL_1.4, 5=OGL_1.4_V2, 6=OGL_TNT2, 7=NVIDIA_OGL, 8=OGL_FRAGMENT_PROGRAM)");
360     ConfigSetDefaultInt(l_ConfigVideoRice, "AnisotropicFiltering", 0, "Enable/Disable Anisotropic Filtering for Mipmapping (0=no filtering, 2-16=quality). This is uneffective if Mipmapping is 0. If the given value is to high to be supported by your graphic card, the value will be the highest value your graphic card can support. Better result with Trilinear filtering");
361     return TRUE;
362 }
363
364 bool isMMXSupported() 
365
366     int IsMMXSupported = 0; 
367    
368 #if !defined(__GNUC__) && !defined(NO_ASM)
369     __asm 
370     { 
371         mov eax,1   // CPUID level 1 
372         cpuid       // EDX = feature flag 
373         and edx,0x800000        // test bit 23 of feature flag 
374         mov IsMMXSupported,edx  // != 0 if MMX is supported 
375     } 
376 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
377   return true;
378 #elif !defined(NO_ASM) // GCC assumed
379    asm volatile (
380          "push %%ebx           \n"
381          "mov $1, %%eax        \n"  // CPUID level 1 
382          "cpuid                \n"      // EDX = feature flag 
383          "and $0x800000, %%edx \n"      // test bit 23 of feature flag 
384          "pop %%ebx            \n"
385          : "=d"(IsMMXSupported)
386          :
387          : "memory", "cc", "eax", "ecx"
388          );
389 #endif
390     if (IsMMXSupported != 0) 
391         return true; 
392     else 
393         return false; 
394
395
396 bool isSSESupported() 
397 {
398     int SSESupport = 0;
399
400 // And finally, check the CPUID for Streaming SIMD Extensions support.
401 #if !defined(__GNUC__) && !defined(NO_ASM)
402     _asm
403         {
404             mov      eax, 1          // Put a "1" in eax to tell CPUID to get the feature bits
405             cpuid                    // Perform CPUID (puts processor feature info into EDX)
406             and      edx, 02000000h  // Test bit 25, for Streaming SIMD Extensions existence.
407             mov      SSESupport, edx // SIMD Extensions).  Set return value to 1 to indicate,
408     }
409 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
410   return true;
411 #elif !defined(NO_ASM) // GCC assumed
412    asm volatile (
413          "push %%ebx                       \n"
414          "mov $1, %%eax                    \n"  // Put a "1" in eax to tell CPUID to get the feature bits
415          "cpuid                            \n"  // Perform CPUID (puts processor feature info into EDX)
416          "and       $0x02000000, %%edx     \n"  // Test bit 25, for Streaming SIMD Extensions existence.
417          "pop %%ebx                        \n"
418          : "=d"(SSESupport)
419          :
420          : "memory", "cc", "eax", "ecx"
421          );
422 # endif
423     
424     if (SSESupport != 0) 
425         return true; 
426     else 
427         return false; 
428
429
430 static void ReadConfiguration(void)
431 {
432     windowSetting.bDisplayFullscreen = ConfigGetParamBool(l_ConfigVideoGeneral, "Fullscreen");
433     windowSetting.uDisplayWidth = ConfigGetParamInt(l_ConfigVideoGeneral, "ScreenWidth");
434 #ifdef HAVE_GLES
435         if (windowSetting.uDisplayWidth==800)
436                 windowSetting.uDisplayWidth = 640;      // no strech
437 #endif
438     windowSetting.uDisplayHeight = ConfigGetParamInt(l_ConfigVideoGeneral, "ScreenHeight");
439     windowSetting.bVerticalSync = ConfigGetParamBool(l_ConfigVideoGeneral, "VerticalSync");
440
441     defaultRomOptions.N64FrameBufferEmuType = ConfigGetParamInt(l_ConfigVideoRice, "FrameBufferSetting");
442     defaultRomOptions.N64FrameBufferWriteBackControl = ConfigGetParamInt(l_ConfigVideoRice, "FrameBufferWriteBackControl");
443     defaultRomOptions.N64RenderToTextureEmuType = ConfigGetParamInt(l_ConfigVideoRice, "RenderToTexture");
444     defaultRomOptions.screenUpdateSetting = ConfigGetParamInt(l_ConfigVideoRice, "screenUpdateSetting");
445
446     defaultRomOptions.bNormalBlender = ConfigGetParamBool(l_ConfigVideoRice, "NormalAlphaBlender");
447     defaultRomOptions.bFastTexCRC = ConfigGetParamBool(l_ConfigVideoRice, "FastTextureLoading");
448     defaultRomOptions.bAccurateTextureMapping = ConfigGetParamBool(l_ConfigVideoRice, "AccurateTextureMapping");
449     defaultRomOptions.bInN64Resolution = ConfigGetParamBool(l_ConfigVideoRice, "InN64Resolution");
450     defaultRomOptions.bSaveVRAM = ConfigGetParamBool(l_ConfigVideoRice, "SaveVRAM");
451     defaultRomOptions.bDoubleSizeForSmallTxtrBuf = ConfigGetParamBool(l_ConfigVideoRice, "DoubleSizeForSmallTxtrBuf");
452     defaultRomOptions.bNormalCombiner = ConfigGetParamBool(l_ConfigVideoRice, "DefaultCombinerDisable");
453
454     options.bEnableHacks = ConfigGetParamBool(l_ConfigVideoRice, "EnableHacks");
455     options.bWinFrameMode = ConfigGetParamBool(l_ConfigVideoRice, "WinFrameMode");
456     options.bFullTMEM = ConfigGetParamBool(l_ConfigVideoRice, "FullTMEMEmulation");
457     options.bOGLVertexClipper = ConfigGetParamBool(l_ConfigVideoRice, "OpenGLVertexClipper");
458     options.bEnableSSE = ConfigGetParamBool(l_ConfigVideoRice, "EnableSSE");
459     options.bEnableVertexShader = ConfigGetParamBool(l_ConfigVideoRice, "EnableVertexShader");
460     options.bSkipFrame = ConfigGetParamBool(l_ConfigVideoRice, "SkipFrame");
461     options.bTexRectOnly = ConfigGetParamBool(l_ConfigVideoRice, "TexRectOnly");
462     options.bSmallTextureOnly = ConfigGetParamBool(l_ConfigVideoRice, "SmallTextureOnly");
463     options.bLoadHiResTextures = ConfigGetParamBool(l_ConfigVideoRice, "LoadHiResTextures");
464     options.bLoadHiResCRCOnly = ConfigGetParamBool(l_ConfigVideoRice, "LoadHiResCRCOnly");
465     options.bDumpTexturesToFiles = ConfigGetParamBool(l_ConfigVideoRice, "DumpTexturesToFiles");
466     options.bShowFPS = ConfigGetParamBool(l_ConfigVideoRice, "ShowFPS");
467
468     options.mipmapping = ConfigGetParamInt(l_ConfigVideoRice, "Mipmapping");
469     options.fogMethod = ConfigGetParamInt(l_ConfigVideoRice, "FogMethod");
470     options.forceTextureFilter = ConfigGetParamInt(l_ConfigVideoRice, "ForceTextureFilter");
471     options.textureEnhancement = ConfigGetParamInt(l_ConfigVideoRice, "TextureEnhancement");
472     options.textureEnhancementControl = ConfigGetParamInt(l_ConfigVideoRice, "TextureEnhancementControl");
473     options.textureQuality = ConfigGetParamInt(l_ConfigVideoRice, "TextureQuality");
474     options.OpenglDepthBufferSetting = ConfigGetParamInt(l_ConfigVideoRice, "OpenGLDepthBufferSetting");
475     options.multiSampling = ConfigGetParamInt(l_ConfigVideoRice, "MultiSampling");
476     options.colorQuality = ConfigGetParamInt(l_ConfigVideoRice, "ColorQuality");
477     options.OpenglRenderSetting = ConfigGetParamInt(l_ConfigVideoRice, "OpenGLRenderSetting");
478     options.anisotropicFiltering = ConfigGetParamInt(l_ConfigVideoRice, "AnisotropicFiltering");
479
480     CDeviceBuilder::SelectDeviceType((SupportedDeviceType)options.OpenglRenderSetting);
481
482     status.isMMXSupported = isMMXSupported();
483     status.isSSESupported = isSSESupported();
484     status.isVertexShaderSupported = false;
485
486     status.isSSEEnabled = status.isSSESupported && options.bEnableSSE;
487 #if !defined(NO_ASM)
488     if( status.isSSEEnabled )
489     {
490         ProcessVertexData = ProcessVertexDataSSE;
491         DebugMessage(M64MSG_INFO, "SSE processing enabled.");
492     }
493     else
494 #endif
495     {
496         ProcessVertexData = ProcessVertexDataNoSSE;
497         DebugMessage(M64MSG_INFO, "Disabled SSE processing.");
498     }
499
500     status.isVertexShaderEnabled = status.isVertexShaderSupported && options.bEnableVertexShader;
501     status.bUseHW_T_L = false;
502 }
503     
504 BOOL LoadConfiguration(void)
505 {
506     IniSections.clear();
507     bIniIsChanged = false;
508     strcpy(szIniFileName, INI_FILE);
509
510     if (!ReadIniFile())
511     {
512         DebugMessage(M64MSG_ERROR, "Unable to read ini file from disk");
513         return FALSE;
514     }
515
516     if (l_ConfigVideoGeneral == NULL || l_ConfigVideoRice == NULL)
517     {
518         DebugMessage(M64MSG_ERROR, "Rice Video configuration sections are not open!");
519         return FALSE;
520     }
521     
522     // Read config parameters from core config API and set up internal variables
523     ReadConfiguration();
524
525     return TRUE;
526 }
527
528 void GenerateCurrentRomOptions()
529 {
530     currentRomOptions.N64FrameBufferEmuType     =g_curRomInfo.dwFrameBufferOption;  
531     currentRomOptions.N64FrameBufferWriteBackControl        =defaultRomOptions.N64FrameBufferWriteBackControl;  
532     currentRomOptions.N64RenderToTextureEmuType =g_curRomInfo.dwRenderToTextureOption;  
533     currentRomOptions.screenUpdateSetting       =g_curRomInfo.dwScreenUpdateSetting;
534     currentRomOptions.bNormalCombiner           =g_curRomInfo.dwNormalCombiner;
535     currentRomOptions.bNormalBlender            =g_curRomInfo.dwNormalBlender;
536     currentRomOptions.bFastTexCRC               =g_curRomInfo.dwFastTextureCRC;
537     currentRomOptions.bAccurateTextureMapping   =g_curRomInfo.dwAccurateTextureMapping;
538
539     options.enableHackForGames = NO_HACK_FOR_GAME;
540     if ((strncmp((char*)g_curRomInfo.szGameName, "BANJO TOOIE", 11) == 0))
541     {
542         options.enableHackForGames = HACK_FOR_BANJO_TOOIE;
543     }
544     else if ((strncmp((char*)g_curRomInfo.szGameName, "DR.MARIO", 8) == 0))
545     {
546         options.enableHackForGames = HACK_FOR_DR_MARIO;
547     }
548     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "Pilot", 5) == 0))
549     {
550         options.enableHackForGames = HACK_FOR_PILOT_WINGS;
551     }
552     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "YOSHI", 5) == 0))
553     {
554         options.enableHackForGames = HACK_FOR_YOSHI;
555     }
556     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "NITRO", 5) == 0))
557     {
558         options.enableHackForGames = HACK_FOR_NITRO;
559     }
560     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "TONY HAWK", 9) == 0))
561     {
562         options.enableHackForGames = HACK_FOR_TONYHAWK;
563     }
564     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "THPS", 4) == 0))
565     {
566         options.enableHackForGames = HACK_FOR_TONYHAWK;
567     }
568     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "SPIDERMAN", 9) == 0))
569     {
570         options.enableHackForGames = HACK_FOR_TONYHAWK;
571     }
572     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "NASCAR", 6) == 0))
573     {
574         options.enableHackForGames = HACK_FOR_NASCAR;
575     }
576     else if ((strstr((char*)g_curRomInfo.szGameName, "ZELDA") != 0) && (strstr((char*)g_curRomInfo.szGameName, "MASK") != 0))
577     {
578         options.enableHackForGames = HACK_FOR_ZELDA_MM;
579     }
580     else if ((strstr((char*)g_curRomInfo.szGameName, "ZELDA") != 0))
581     {
582         options.enableHackForGames = HACK_FOR_ZELDA;
583     }
584     else if ((strstr((char*)g_curRomInfo.szGameName, "Ogre") != 0))
585     {
586         options.enableHackForGames = HACK_FOR_OGRE_BATTLE;
587     }
588     else if ((strstr((char*)g_curRomInfo.szGameName, "TWINE") != 0))
589     {
590         options.enableHackForGames = HACK_FOR_TWINE;
591     }
592     else if ((strstr((char*)g_curRomInfo.szGameName, "Squadron") != 0))
593     {
594         options.enableHackForGames = HACK_FOR_ROGUE_SQUADRON;
595     }
596     else if ((strstr((char*)g_curRomInfo.szGameName, "Baseball") != 0) && (strstr((char*)g_curRomInfo.szGameName, "Star") != 0))
597     {
598         options.enableHackForGames = HACK_FOR_ALL_STAR_BASEBALL;
599     }
600     else if ((strstr((char*)g_curRomInfo.szGameName, "Tigger") != 0) && (strstr((char*)g_curRomInfo.szGameName, "Honey") != 0))
601     {
602         options.enableHackForGames = HACK_FOR_TIGER_HONEY_HUNT;
603     }
604     else if ((strstr((char*)g_curRomInfo.szGameName, "Bust") != 0) && (strstr((char*)g_curRomInfo.szGameName, "Move") != 0))
605     {
606         options.enableHackForGames = HACK_FOR_BUST_A_MOVE;
607     }
608     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "MarioTennis",11) == 0))
609     {
610         options.enableHackForGames = HACK_FOR_MARIO_TENNIS;
611     }
612     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "SUPER BOWLING",13) == 0))
613     {
614         options.enableHackForGames = HACK_FOR_SUPER_BOWLING;
615     }
616     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "CONKER",6) == 0))
617     {
618         options.enableHackForGames = HACK_FOR_CONKER;
619     }
620     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "MK_MYTHOLOGIES",14) == 0))
621     {
622         options.enableHackForGames = HACK_REVERSE_Y_COOR;
623     }
624     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "Fighting Force",14) == 0))
625     {
626         options.enableHackForGames = HACK_REVERSE_XY_COOR;
627     }
628     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "GOLDENEYE",9) == 0))
629     {
630         options.enableHackForGames = HACK_FOR_GOLDEN_EYE;
631     }
632     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "F-ZERO",6) == 0))
633     {
634         options.enableHackForGames = HACK_FOR_FZERO;
635     }
636     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "Command&Conquer",15) == 0))
637     {
638         options.enableHackForGames = HACK_FOR_COMMANDCONQUER;
639     }
640     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "READY 2 RUMBLE",14) == 0))
641     {
642         options.enableHackForGames = HACK_FOR_RUMBLE;
643     }
644     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "READY to RUMBLE",15) == 0))
645     {
646         options.enableHackForGames = HACK_FOR_RUMBLE;
647     }
648     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "South Park Rally",16) == 0))
649     {
650         options.enableHackForGames = HACK_FOR_SOUTH_PARK_RALLY;
651     }
652     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "Extreme G 2",11) == 0))
653     {
654         options.enableHackForGames = HACK_FOR_EXTREME_G2;
655     }
656     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "MarioGolf64",11) == 0))
657     {
658         options.enableHackForGames = HACK_FOR_MARIO_GOLF;
659     }
660     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "MLB FEATURING",13) == 0))
661     {
662         options.enableHackForGames = HACK_FOR_MLB;
663     }
664     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "POLARISSNOCROSS",15) == 0))
665     {
666         options.enableHackForGames = HACK_FOR_POLARISSNOCROSS;
667     }
668     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "TOP GEAR RALLY",14) == 0))
669     {
670         options.enableHackForGames = HACK_FOR_TOPGEARRALLY;
671     }
672     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "DUKE NUKEM",10) == 0))
673     {
674         options.enableHackForGames = HACK_FOR_DUKE_NUKEM;
675     }
676     else if ((strncasecmp((char*)g_curRomInfo.szGameName, "MARIOKART64",11) == 0))
677     {
678         options.enableHackForGames = HACK_FOR_MARIO_KART;
679     }
680
681     if (options.enableHackForGames != NO_HACK_FOR_GAME)
682         DebugMessage(M64MSG_INFO, "Enabled hacks for game: '%s'", g_curRomInfo.szGameName);
683
684     if( currentRomOptions.N64FrameBufferEmuType == 0 )      currentRomOptions.N64FrameBufferEmuType = defaultRomOptions.N64FrameBufferEmuType;
685     else currentRomOptions.N64FrameBufferEmuType--;
686     if( currentRomOptions.N64RenderToTextureEmuType == 0 )  currentRomOptions.N64RenderToTextureEmuType = defaultRomOptions.N64RenderToTextureEmuType;
687     else currentRomOptions.N64RenderToTextureEmuType--;
688     if( currentRomOptions.screenUpdateSetting == 0 )        currentRomOptions.screenUpdateSetting = defaultRomOptions.screenUpdateSetting;
689     if( currentRomOptions.bNormalCombiner == 0 )            currentRomOptions.bNormalCombiner = defaultRomOptions.bNormalCombiner;
690     else currentRomOptions.bNormalCombiner--;
691     if( currentRomOptions.bNormalBlender == 0 )             currentRomOptions.bNormalBlender = defaultRomOptions.bNormalBlender;
692     else currentRomOptions.bNormalBlender--;
693     if( currentRomOptions.bFastTexCRC == 0 )                currentRomOptions.bFastTexCRC = defaultRomOptions.bFastTexCRC;
694     else currentRomOptions.bFastTexCRC--;
695     if( currentRomOptions.bAccurateTextureMapping == 0 )    currentRomOptions.bAccurateTextureMapping = defaultRomOptions.bAccurateTextureMapping;
696     else currentRomOptions.bAccurateTextureMapping--;
697
698     options.bUseFullTMEM = ((options.bFullTMEM && (g_curRomInfo.dwFullTMEM == 0)) || g_curRomInfo.dwFullTMEM == 2);
699
700     GenerateFrameBufferOptions();
701
702     if( options.enableHackForGames == HACK_FOR_MARIO_GOLF || options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
703     {
704         frameBufferOptions.bIgnoreRenderTextureIfHeightUnknown = true;
705     }
706 }
707
708 void Ini_GetRomOptions(LPGAMESETTING pGameSetting)
709 {
710     int i;
711
712     i = FindIniEntry(pGameSetting->romheader.dwCRC1,
713                      pGameSetting->romheader.dwCRC2,
714                      pGameSetting->romheader.nCountryID,
715                      (char*)pGameSetting->szGameName, 1);
716
717     pGameSetting->bDisableTextureCRC    = IniSections[i].bDisableTextureCRC;
718     pGameSetting->bDisableCulling       = IniSections[i].bDisableCulling;
719     pGameSetting->bIncTexRectEdge       = IniSections[i].bIncTexRectEdge;
720     pGameSetting->bZHack                = IniSections[i].bZHack;
721     pGameSetting->bTextureScaleHack     = IniSections[i].bTextureScaleHack;
722     pGameSetting->bPrimaryDepthHack     = IniSections[i].bPrimaryDepthHack;
723     pGameSetting->bTexture1Hack         = IniSections[i].bTexture1Hack;
724     pGameSetting->bFastLoadTile         = IniSections[i].bFastLoadTile;
725     pGameSetting->bUseSmallerTexture    = IniSections[i].bUseSmallerTexture;
726
727     pGameSetting->VIWidth               = IniSections[i].VIWidth;
728     pGameSetting->VIHeight              = IniSections[i].VIHeight;
729     pGameSetting->UseCIWidthAndRatio    = IniSections[i].UseCIWidthAndRatio;
730     pGameSetting->dwFullTMEM            = IniSections[i].dwFullTMEM;
731     pGameSetting->bTxtSizeMethod2       = IniSections[i].bTxtSizeMethod2;
732     pGameSetting->bEnableTxtLOD         = IniSections[i].bEnableTxtLOD;
733
734     pGameSetting->dwFastTextureCRC      = IniSections[i].dwFastTextureCRC;
735     pGameSetting->bEmulateClear         = IniSections[i].bEmulateClear;
736     pGameSetting->bForceScreenClear     = IniSections[i].bForceScreenClear;
737     pGameSetting->dwAccurateTextureMapping  = IniSections[i].dwAccurateTextureMapping;
738     pGameSetting->dwNormalBlender       = IniSections[i].dwNormalBlender;
739     pGameSetting->bDisableBlender       = IniSections[i].bDisableBlender;
740     pGameSetting->dwNormalCombiner      = IniSections[i].dwNormalCombiner;
741     pGameSetting->bForceDepthBuffer     = IniSections[i].bForceDepthBuffer;
742     pGameSetting->bDisableObjBG         = IniSections[i].bDisableObjBG;
743     pGameSetting->dwFrameBufferOption   = IniSections[i].dwFrameBufferOption;
744     pGameSetting->dwRenderToTextureOption   = IniSections[i].dwRenderToTextureOption;
745     pGameSetting->dwScreenUpdateSetting = IniSections[i].dwScreenUpdateSetting;
746 }
747
748 void Ini_StoreRomOptions(LPGAMESETTING pGameSetting)
749 {
750     int i;
751
752     i = FindIniEntry(pGameSetting->romheader.dwCRC1,
753                      pGameSetting->romheader.dwCRC2,
754                      pGameSetting->romheader.nCountryID,
755                      (char*)pGameSetting->szGameName, 0);
756
757     if( IniSections[i].bDisableTextureCRC   !=pGameSetting->bDisableTextureCRC )
758     {
759         IniSections[i].bDisableTextureCRC   =pGameSetting->bDisableTextureCRC    ;
760         bIniIsChanged=true;
761     }
762
763     if( IniSections[i].bDisableCulling  !=pGameSetting->bDisableCulling )
764     {
765         IniSections[i].bDisableCulling  =pGameSetting->bDisableCulling   ;
766         bIniIsChanged=true;
767     }
768
769     if( IniSections[i].dwFastTextureCRC !=pGameSetting->dwFastTextureCRC )
770     {
771         IniSections[i].dwFastTextureCRC =pGameSetting->dwFastTextureCRC      ;
772         bIniIsChanged=true;
773     }
774
775     if( IniSections[i].bEmulateClear !=pGameSetting->bEmulateClear )
776     {
777         IniSections[i].bEmulateClear    =pGameSetting->bEmulateClear         ;
778         bIniIsChanged=true;
779     }
780
781     if( IniSections[i].dwNormalBlender      !=pGameSetting->dwNormalBlender )
782     {
783         IniSections[i].dwNormalBlender      =pGameSetting->dwNormalBlender       ;
784         bIniIsChanged=true;
785     }
786
787     if( IniSections[i].bDisableBlender  !=pGameSetting->bDisableBlender )
788     {
789         IniSections[i].bDisableBlender  =pGameSetting->bDisableBlender       ;
790         bIniIsChanged=true;
791     }
792
793     if( IniSections[i].bForceScreenClear    !=pGameSetting->bForceScreenClear )
794     {
795         IniSections[i].bForceScreenClear    =pGameSetting->bForceScreenClear         ;
796         bIniIsChanged=true;
797     }
798     if( IniSections[i].dwAccurateTextureMapping !=pGameSetting->dwAccurateTextureMapping )
799     {
800         IniSections[i].dwAccurateTextureMapping =pGameSetting->dwAccurateTextureMapping      ;
801         bIniIsChanged=true;
802     }
803     if( IniSections[i].dwNormalCombiner !=pGameSetting->dwNormalCombiner )
804     {
805         IniSections[i].dwNormalCombiner =pGameSetting->dwNormalCombiner      ;
806         bIniIsChanged=true;
807     }
808     if( IniSections[i].bForceDepthBuffer    !=pGameSetting->bForceDepthBuffer )
809     {
810         IniSections[i].bForceDepthBuffer    =pGameSetting->bForceDepthBuffer         ;
811         bIniIsChanged=true;
812     }
813     if( IniSections[i].bDisableObjBG    !=pGameSetting->bDisableObjBG )
814     {
815         IniSections[i].bDisableObjBG    =pGameSetting->bDisableObjBG         ;
816         bIniIsChanged=true;
817     }
818     if( IniSections[i].dwFrameBufferOption  !=pGameSetting->dwFrameBufferOption )
819     {
820         IniSections[i].dwFrameBufferOption  =pGameSetting->dwFrameBufferOption       ;
821         bIniIsChanged=true;
822     }
823     if( IniSections[i].dwRenderToTextureOption  !=pGameSetting->dwRenderToTextureOption )
824     {
825         IniSections[i].dwRenderToTextureOption  =pGameSetting->dwRenderToTextureOption       ;
826         bIniIsChanged=true;
827     }
828     if( IniSections[i].dwScreenUpdateSetting    !=pGameSetting->dwScreenUpdateSetting )
829     {
830         IniSections[i].dwScreenUpdateSetting    =pGameSetting->dwScreenUpdateSetting         ;
831         bIniIsChanged=true;
832     }
833     if( IniSections[i].bIncTexRectEdge  != pGameSetting->bIncTexRectEdge )
834     {
835         IniSections[i].bIncTexRectEdge      =pGameSetting->bIncTexRectEdge;
836         bIniIsChanged=true;
837     }
838     if( IniSections[i].bZHack   != pGameSetting->bZHack )
839     {
840         IniSections[i].bZHack       =pGameSetting->bZHack;
841         bIniIsChanged=true;
842     }
843     if( IniSections[i].bTextureScaleHack    != pGameSetting->bTextureScaleHack )
844     {
845         IniSections[i].bTextureScaleHack        =pGameSetting->bTextureScaleHack;
846         bIniIsChanged=true;
847     }
848     if( IniSections[i].bPrimaryDepthHack    != pGameSetting->bPrimaryDepthHack )
849     {
850         IniSections[i].bPrimaryDepthHack        =pGameSetting->bPrimaryDepthHack;
851         bIniIsChanged=true;
852     }
853     if( IniSections[i].bTexture1Hack    != pGameSetting->bTexture1Hack )
854     {
855         IniSections[i].bTexture1Hack        =pGameSetting->bTexture1Hack;
856         bIniIsChanged=true;
857     }
858     if( IniSections[i].bFastLoadTile    != pGameSetting->bFastLoadTile )
859     {
860         IniSections[i].bFastLoadTile    =pGameSetting->bFastLoadTile;
861         bIniIsChanged=true;
862     }
863     if( IniSections[i].bUseSmallerTexture   != pGameSetting->bUseSmallerTexture )
864     {
865         IniSections[i].bUseSmallerTexture   =pGameSetting->bUseSmallerTexture;
866         bIniIsChanged=true;
867     }
868     if( IniSections[i].VIWidth  != pGameSetting->VIWidth )
869     {
870         IniSections[i].VIWidth  =pGameSetting->VIWidth;
871         bIniIsChanged=true;
872     }
873     if( IniSections[i].VIHeight != pGameSetting->VIHeight )
874     {
875         IniSections[i].VIHeight =pGameSetting->VIHeight;
876         bIniIsChanged=true;
877     }
878     if( IniSections[i].UseCIWidthAndRatio   != pGameSetting->UseCIWidthAndRatio )
879     {
880         IniSections[i].UseCIWidthAndRatio   =pGameSetting->UseCIWidthAndRatio;
881         bIniIsChanged=true;
882     }
883     if( IniSections[i].dwFullTMEM   != pGameSetting->dwFullTMEM )
884     {
885         IniSections[i].dwFullTMEM   =pGameSetting->dwFullTMEM;
886         bIniIsChanged=true;
887     }
888     if( IniSections[i].bTxtSizeMethod2  != pGameSetting->bTxtSizeMethod2 )
889     {
890         IniSections[i].bTxtSizeMethod2  =pGameSetting->bTxtSizeMethod2;
891         bIniIsChanged=true;
892     }
893     if( IniSections[i].bEnableTxtLOD    != pGameSetting->bEnableTxtLOD )
894     {
895         IniSections[i].bEnableTxtLOD    =pGameSetting->bEnableTxtLOD;
896         bIniIsChanged=true;
897     }
898
899     if( bIniIsChanged )
900     {
901         WriteIniFile();
902         TRACE0("Rom option is changed and saved");
903     }
904 }
905
906 std::ifstream& getline( std::ifstream &is, char *str );
907
908 char * left(const char * src, int nchars)
909 {
910     static char dst[300];
911     strncpy(dst,src,nchars);
912     dst[nchars]=0;
913     return dst;
914 }
915
916 char * right(const char *src, int nchars)
917 {
918     static char dst[300];
919     int srclen = strlen(src);
920     if (nchars >= srclen)
921     {
922         strcpy(dst, src);
923     }
924     else
925     {
926         strncpy(dst, src + srclen - nchars, nchars);
927         dst[nchars]=0;
928     }
929     return dst;
930 }
931
932 char * tidy(char * s)
933 {
934     char * p = s + strlen(s);
935
936     p--;
937     while (p >= s && (*p == ' ' || *p == 0xa || *p == '\n') )
938     {
939         *p = 0;
940         p--;
941     }
942     return s;
943
944 }
945
946 BOOL ReadIniFile()
947 {
948     std::ifstream inifile;
949     char readinfo[100];
950     const char *ini_filepath = ConfigGetSharedDataFilepath(szIniFileName);
951
952     DebugMessage(M64MSG_VERBOSE, "Reading .ini file: %s", ini_filepath);
953     inifile.open(ini_filepath);
954
955     if (inifile.fail())
956     {
957         return FALSE;
958     }
959
960     while (getline(inifile,readinfo)/*&&sectionno<999*/)
961     {
962         tidy(readinfo);
963
964         if (readinfo[0] == '/')
965             continue;
966
967         if (!strcasecmp(readinfo,"")==0)
968         {
969             if (readinfo[0] == '{') //if a section heading
970             {
971                 section newsection;
972
973                 readinfo[strlen(readinfo)-1]='\0';
974                 strcpy(newsection.crccheck, readinfo+1);
975
976                 newsection.bDisableTextureCRC = FALSE;
977                 newsection.bDisableCulling = FALSE;
978                 newsection.bIncTexRectEdge = FALSE;
979                 newsection.bZHack = FALSE;
980                 newsection.bTextureScaleHack = FALSE;
981                 newsection.bFastLoadTile = FALSE;
982                 newsection.bUseSmallerTexture = FALSE;
983                 newsection.bPrimaryDepthHack = FALSE;
984                 newsection.bTexture1Hack = FALSE;
985                 newsection.bDisableObjBG = FALSE;
986                 newsection.VIWidth = -1;
987                 newsection.VIHeight = -1;
988                 newsection.UseCIWidthAndRatio = NOT_USE_CI_WIDTH_AND_RATIO;
989                 newsection.dwFullTMEM = 0;
990                 newsection.bTxtSizeMethod2 = FALSE;
991                 newsection.bEnableTxtLOD = FALSE;
992
993                 newsection.bEmulateClear = FALSE;
994                 newsection.bForceScreenClear = FALSE;
995                 newsection.bDisableBlender = FALSE;
996                 newsection.bForceDepthBuffer = FALSE;
997                 newsection.dwFastTextureCRC = 0;
998                 newsection.dwAccurateTextureMapping = 0;
999                 newsection.dwNormalBlender = 0;
1000                 newsection.dwNormalCombiner = 0;
1001                 newsection.dwFrameBufferOption = 0;
1002                 newsection.dwRenderToTextureOption = 0;
1003                 newsection.dwScreenUpdateSetting = 0;
1004
1005                 IniSections.push_back(newsection);
1006
1007             }
1008             else
1009             {       
1010                 int sectionno = IniSections.size() - 1;
1011
1012                 if (strcasecmp(left(readinfo,4), "Name")==0)
1013                     strcpy(IniSections[sectionno].name,right(readinfo,strlen(readinfo)-5));
1014
1015                 if (strcasecmp(left(readinfo,17), "DisableTextureCRC")==0)
1016                     IniSections[sectionno].bDisableTextureCRC=true;
1017
1018                 if (strcasecmp(left(readinfo,14), "DisableCulling")==0)
1019                     IniSections[sectionno].bDisableCulling=true;
1020
1021                 if (strcasecmp(left(readinfo,16), "PrimaryDepthHack")==0)
1022                     IniSections[sectionno].bPrimaryDepthHack=true;
1023
1024                 if (strcasecmp(left(readinfo,12), "Texture1Hack")==0)
1025                     IniSections[sectionno].bTexture1Hack=true;
1026
1027                 if (strcasecmp(left(readinfo,12), "FastLoadTile")==0)
1028                     IniSections[sectionno].bFastLoadTile=true;
1029
1030                 if (strcasecmp(left(readinfo,17), "UseSmallerTexture")==0)
1031                     IniSections[sectionno].bUseSmallerTexture=true;
1032
1033                 if (strcasecmp(left(readinfo,14), "IncTexRectEdge")==0)
1034                     IniSections[sectionno].bIncTexRectEdge=true;
1035
1036                 if (strcasecmp(left(readinfo,5), "ZHack")==0)
1037                     IniSections[sectionno].bZHack=true;
1038
1039                 if (strcasecmp(left(readinfo,16), "TexRectScaleHack")==0)
1040                     IniSections[sectionno].bTextureScaleHack=true;
1041
1042                 if (strcasecmp(left(readinfo,7), "VIWidth")==0)
1043                     IniSections[sectionno].VIWidth = strtol(right(readinfo,3),NULL,10);
1044
1045                 if (strcasecmp(left(readinfo,8), "VIHeight")==0)
1046                     IniSections[sectionno].VIHeight = strtol(right(readinfo,3),NULL,10);
1047
1048                 if (strcasecmp(left(readinfo,18), "UseCIWidthAndRatio")==0)
1049                     IniSections[sectionno].UseCIWidthAndRatio = strtol(right(readinfo,1),NULL,10);
1050
1051                 if (strcasecmp(left(readinfo,8), "FullTMEM")==0)
1052                     IniSections[sectionno].dwFullTMEM = strtol(right(readinfo,1),NULL,10);
1053
1054                 if (strcasecmp(left(readinfo,24), "AlternativeTxtSizeMethod")==0)
1055                     IniSections[sectionno].bTxtSizeMethod2 = strtol(right(readinfo,1),NULL,10);
1056
1057                 if (strcasecmp(left(readinfo,12), "EnableTxtLOD")==0)
1058                     IniSections[sectionno].bEnableTxtLOD = strtol(right(readinfo,1),NULL,10);
1059
1060                 if (strcasecmp(left(readinfo,12), "DisableObjBG")==0)
1061                     IniSections[sectionno].bDisableObjBG = strtol(right(readinfo,1),NULL,10);
1062
1063                 if (strcasecmp(left(readinfo,16), "ForceScreenClear")==0)
1064                     IniSections[sectionno].bForceScreenClear = strtol(right(readinfo,1),NULL,10);
1065
1066                 if (strcasecmp(left(readinfo,22), "AccurateTextureMapping")==0)
1067                     IniSections[sectionno].dwAccurateTextureMapping = strtol(right(readinfo,1),NULL,10);
1068
1069                 if (strcasecmp(left(readinfo,14), "FastTextureCRC")==0)
1070                     IniSections[sectionno].dwFastTextureCRC = strtol(right(readinfo,1),NULL,10);
1071
1072                 if (strcasecmp(left(readinfo,12), "EmulateClear")==0)
1073                     IniSections[sectionno].bEmulateClear = strtol(right(readinfo,1),NULL,10);
1074
1075                 if (strcasecmp(left(readinfo,18), "NormalAlphaBlender")==0)
1076                     IniSections[sectionno].dwNormalBlender = strtol(right(readinfo,1),NULL,10);
1077
1078                 if (strcasecmp(left(readinfo,19), "DisableAlphaBlender")==0)
1079                     IniSections[sectionno].bDisableBlender = strtol(right(readinfo,1),NULL,10);
1080
1081                 if (strcasecmp(left(readinfo,19), "NormalColorCombiner")==0)
1082                     IniSections[sectionno].dwNormalCombiner = strtol(right(readinfo,1),NULL,10);
1083
1084                 if (strcasecmp(left(readinfo,16), "ForceDepthBuffer")==0)
1085                     IniSections[sectionno].bForceDepthBuffer = strtol(right(readinfo,1),NULL,10);
1086
1087                 if (strcasecmp(left(readinfo,20), "FrameBufferEmulation")==0)
1088                     IniSections[sectionno].dwFrameBufferOption = strtol(readinfo+21,NULL,10);
1089
1090                 if (strcasecmp(left(readinfo,15), "RenderToTexture")==0)
1091                     IniSections[sectionno].dwRenderToTextureOption = strtol(right(readinfo,1),NULL,10);
1092
1093                 if (strcasecmp(left(readinfo,19), "ScreenUpdateSetting")==0)
1094                     IniSections[sectionno].dwScreenUpdateSetting = strtol(right(readinfo,1),NULL,10);
1095             }
1096         }
1097     }
1098     inifile.close();
1099
1100     return TRUE;
1101 }
1102
1103 //read a line from the ini file
1104 std::ifstream & getline(std::ifstream & is, char *str)
1105 {
1106     char buf[100];
1107
1108     is.getline(buf,100);
1109     strcpy( str,buf);
1110     return is;
1111 }
1112
1113 void WriteIniFile()
1114 {
1115     uint32 i;
1116     FILE * fhIn;
1117     FILE * fhOut;
1118
1119     /* get path to game-hack INI file and read it */
1120     const char *ini_filepath = ConfigGetSharedDataFilepath(szIniFileName);
1121     if (ini_filepath == NULL)
1122         return;
1123     fhIn = fopen(ini_filepath, "r");
1124     if (fhIn == NULL)
1125         return;
1126     fseek(fhIn, 0L, SEEK_END);
1127     long filelen = ftell(fhIn);
1128     fseek(fhIn, 0L, SEEK_SET);
1129     char *chIniData = (char *) malloc(filelen + 1);
1130     if (chIniData == NULL)
1131     {
1132         fclose(fhIn);
1133         return;
1134     }
1135     long bytesread = fread(chIniData, 1, filelen, fhIn);
1136     fclose(fhIn);
1137     if (bytesread != filelen)
1138     {
1139         free(chIniData);
1140         return;
1141     }
1142     chIniData[filelen] = 0;
1143
1144     /* now try to open the file for writing */
1145     fhOut = fopen(ini_filepath, "w");
1146     if (fhOut == NULL)
1147     {
1148         free(chIniData);
1149         return;
1150     }
1151
1152     // Mark all sections and needing to be written
1153     for (i = 0; i < IniSections.size(); i++)
1154     {
1155         IniSections[i].bOutput = false;
1156     }
1157
1158     char *thisline = chIniData;
1159     while ((thisline - chIniData) < filelen)
1160     {
1161         char *nextline = strchr(thisline, '\n');
1162         if (nextline == NULL)
1163             nextline = thisline + strlen(thisline) + 1;
1164         else
1165             nextline++;
1166         if (thisline[0] == '{')
1167         {
1168             BOOL bFound = FALSE;
1169             // Start of section
1170             tidy((char*) thisline);
1171             thisline[strlen(thisline) - 1] = '\0';
1172             for (i = 0; i < IniSections.size(); i++)
1173             {
1174                 if (IniSections[i].bOutput)
1175                     continue;
1176                 if (strcasecmp((char*) thisline + 1, IniSections[i].crccheck) == 0)
1177                 {
1178                     // Output this CRC
1179                     OutputSectionDetails(i, fhOut);
1180                     IniSections[i].bOutput = true;
1181                     bFound = TRUE;
1182                     break;
1183                 }
1184             }
1185             if (!bFound)
1186             {
1187                 // Do what? This should never happen, unless the user
1188                 // replaces the inifile while game is running!
1189             }
1190         }
1191         else if (thisline[0] == '/')
1192         {
1193             // Comment
1194             fputs((char*) thisline, fhOut);
1195         }
1196         thisline = nextline;
1197     }
1198
1199     // Input buffer done-  process any new entries!
1200     for (i = 0; i < IniSections.size(); i++)
1201     {
1202         // Skip any that have not been done.
1203         if (IniSections[i].bOutput)
1204             continue;
1205         // Output this CRC
1206         OutputSectionDetails(i, fhOut);
1207         IniSections[i].bOutput = true;
1208     }
1209
1210     fclose(fhOut);
1211     free(chIniData);
1212
1213     bIniIsChanged = false;
1214 }
1215
1216 void OutputSectionDetails(uint32 i, FILE * fh)
1217 {
1218     fprintf(fh, "{%s}\n", IniSections[i].crccheck);
1219
1220     fprintf(fh, "Name=%s\n", IniSections[i].name);
1221     //fprintf(fh, "UCode=%d\n", IniSections[i].ucode);
1222
1223     // Tri-state variables
1224     if (IniSections[i].dwAccurateTextureMapping != 0)
1225         fprintf(fh, "AccurateTextureMapping=%d\n", IniSections[i].dwAccurateTextureMapping);
1226
1227     if (IniSections[i].dwFastTextureCRC != 0)
1228         fprintf(fh, "FastTextureCRC=%d\n", IniSections[i].dwFastTextureCRC);
1229
1230     if (IniSections[i].dwNormalBlender != 0)
1231         fprintf(fh, "NormalAlphaBlender=%d\n", IniSections[i].dwNormalBlender);
1232
1233     if (IniSections[i].dwNormalCombiner != 0)
1234         fprintf(fh, "NormalColorCombiner=%d\n", IniSections[i].dwNormalCombiner);
1235
1236
1237     // Normal bi-state variables
1238     if (IniSections[i].bDisableTextureCRC)
1239         fprintf(fh, "DisableTextureCRC\n");
1240
1241     if (IniSections[i].bDisableCulling)
1242         fprintf(fh, "DisableCulling\n");
1243
1244     if (IniSections[i].bPrimaryDepthHack)
1245         fprintf(fh, "PrimaryDepthHack\n");
1246
1247     if (IniSections[i].bTexture1Hack)
1248         fprintf(fh, "Texture1Hack\n");
1249
1250     if (IniSections[i].bFastLoadTile)
1251         fprintf(fh, "FastLoadTile\n");
1252
1253     if (IniSections[i].bUseSmallerTexture)
1254         fprintf(fh, "UseSmallerTexture\n");
1255
1256     if (IniSections[i].bIncTexRectEdge)
1257         fprintf(fh, "IncTexRectEdge\n");
1258
1259     if (IniSections[i].bZHack)
1260         fprintf(fh, "ZHack\n");
1261
1262     if (IniSections[i].bTextureScaleHack)
1263         fprintf(fh, "TexRectScaleHack\n");
1264
1265     if (IniSections[i].VIWidth > 0)
1266         fprintf(fh, "VIWidth=%d\n", IniSections[i].VIWidth);
1267
1268     if (IniSections[i].VIHeight > 0)
1269         fprintf(fh, "VIHeight=%d\n", IniSections[i].VIHeight);
1270
1271     if (IniSections[i].UseCIWidthAndRatio > 0)
1272         fprintf(fh, "UseCIWidthAndRatio=%d\n", IniSections[i].UseCIWidthAndRatio);
1273
1274     if (IniSections[i].dwFullTMEM > 0)
1275         fprintf(fh, "FullTMEM=%d\n", IniSections[i].dwFullTMEM);
1276
1277     if (IniSections[i].bTxtSizeMethod2 != FALSE )
1278         fprintf(fh, "AlternativeTxtSizeMethod=%d\n", IniSections[i].bTxtSizeMethod2);
1279
1280     if (IniSections[i].bEnableTxtLOD != FALSE )
1281         fprintf(fh, "EnableTxtLOD=%d\n", IniSections[i].bEnableTxtLOD);
1282
1283     if (IniSections[i].bDisableObjBG != 0 )
1284         fprintf(fh, "DisableObjBG=%d\n", IniSections[i].bDisableObjBG);
1285
1286     if (IniSections[i].bForceScreenClear != 0)
1287         fprintf(fh, "ForceScreenClear=%d\n", IniSections[i].bForceScreenClear);
1288
1289     if (IniSections[i].bEmulateClear != 0)
1290         fprintf(fh, "EmulateClear=%d\n", IniSections[i].bEmulateClear);
1291
1292     if (IniSections[i].bDisableBlender != 0)
1293         fprintf(fh, "DisableAlphaBlender=%d\n", IniSections[i].bDisableBlender);
1294
1295     if (IniSections[i].bForceDepthBuffer != 0)
1296         fprintf(fh, "ForceDepthBuffer=%d\n", IniSections[i].bForceDepthBuffer);
1297
1298     if (IniSections[i].dwFrameBufferOption != 0)
1299         fprintf(fh, "FrameBufferEmulation=%d\n", IniSections[i].dwFrameBufferOption);
1300
1301     if (IniSections[i].dwRenderToTextureOption != 0)
1302         fprintf(fh, "RenderToTexture=%d\n", IniSections[i].dwRenderToTextureOption);
1303
1304     if (IniSections[i].dwScreenUpdateSetting != 0)
1305         fprintf(fh, "ScreenUpdateSetting=%d\n", IniSections[i].dwScreenUpdateSetting);
1306
1307     fprintf(fh, "\n");          // Spacer
1308 }
1309
1310 // Find the entry corresponding to the specified rom. 
1311 // If the rom is not found, a new entry is created
1312 // The resulting value is returned
1313 void __cdecl DebuggerAppendMsg (const char * Message, ...);
1314
1315 static int FindIniEntry(uint32 dwCRC1, uint32 dwCRC2, uint8 nCountryID, char* szName, int PrintInfo)
1316 {
1317     uint32 i;
1318     unsigned char szCRC[50+1];
1319
1320     // Generate the CRC-ID for this rom:
1321     sprintf((char*)szCRC, "%08x%08x-%02x", (unsigned int)dwCRC1, (unsigned int)dwCRC2, nCountryID);
1322
1323     for (i = 0; i < IniSections.size(); i++)
1324     {
1325         if (strcasecmp((char*)szCRC, IniSections[i].crccheck) == 0)
1326         {
1327             if (PrintInfo)
1328                 DebugMessage(M64MSG_INFO, "Found ROM '%s', CRC %s", IniSections[i].name, szCRC);
1329             return i;
1330         }
1331     }
1332
1333     // Add new entry!!!
1334     section newsection;
1335
1336     if (PrintInfo)
1337         DebugMessage(M64MSG_INFO, "ROM (CRC %s) not found in INI file", szCRC);
1338
1339     strcpy(newsection.crccheck, (char*)szCRC);
1340
1341     strncpy(newsection.name, szName, 50);
1342     newsection.bDisableTextureCRC = FALSE;
1343     newsection.bDisableCulling = FALSE;
1344     newsection.bIncTexRectEdge = FALSE;
1345     newsection.bZHack = FALSE;
1346     newsection.bTextureScaleHack = FALSE;
1347     newsection.bFastLoadTile = FALSE;
1348     newsection.bUseSmallerTexture = FALSE;
1349     newsection.bPrimaryDepthHack = FALSE;
1350     newsection.bTexture1Hack = FALSE;
1351     newsection.bDisableObjBG = FALSE;
1352     newsection.VIWidth = -1;
1353     newsection.VIHeight = -1;
1354     newsection.UseCIWidthAndRatio = NOT_USE_CI_WIDTH_AND_RATIO;
1355     newsection.dwFullTMEM = 0;
1356     newsection.bTxtSizeMethod2 = FALSE;
1357     newsection.bEnableTxtLOD = FALSE;
1358
1359     newsection.bEmulateClear = FALSE;
1360     newsection.bForceScreenClear = FALSE;
1361     newsection.bDisableBlender = FALSE;
1362     newsection.bForceDepthBuffer = FALSE;
1363     newsection.dwFastTextureCRC = 0;
1364     newsection.dwAccurateTextureMapping = 0;
1365     newsection.dwNormalBlender = 0;
1366     newsection.dwNormalCombiner = 0;
1367     newsection.dwFrameBufferOption = 0;
1368     newsection.dwRenderToTextureOption = 0;
1369     newsection.dwScreenUpdateSetting = 0;
1370
1371     IniSections.push_back(newsection);
1372
1373     bIniIsChanged = true;               // Flag to indicate we should be updated
1374     return IniSections.size()-1;            // -1 takes into account increment
1375 }
1376
1377 GameSetting g_curRomInfo;
1378
1379 void ROM_GetRomNameFromHeader(unsigned char * szName, ROMHeader * pHdr)
1380 {
1381     unsigned char * p;
1382
1383     memcpy(szName, pHdr->szName, 20);
1384     szName[20] = '\0';
1385
1386     p = szName + (strlen((char*)szName) -1);        // -1 to skip null
1387     while (p >= szName && *p == ' ')
1388     {
1389         *p = 0;
1390         p--;
1391     }
1392 }
1393
1394 uint32 CountryCodeToTVSystem(uint32 countryCode)
1395 {
1396     uint32 system;
1397     switch(countryCode)
1398     {
1399         /* Demo */
1400     case 0:
1401         system = TV_SYSTEM_NTSC;
1402         break;
1403
1404     case '7':
1405         system = TV_SYSTEM_NTSC;
1406         break;
1407
1408     case 0x41:
1409         system = TV_SYSTEM_NTSC;
1410         break;
1411
1412         /* Germany */
1413     case 0x44:
1414         system = TV_SYSTEM_PAL;
1415         break;
1416
1417         /* USA */
1418     case 0x45:
1419         system = TV_SYSTEM_NTSC;
1420         break;
1421
1422         /* France */
1423     case 0x46:
1424         system = TV_SYSTEM_PAL;
1425         break;
1426
1427         /* Italy */
1428     case 'I':
1429         system = TV_SYSTEM_PAL;
1430         break;
1431
1432         /* Japan */
1433     case 0x4A:
1434         system = TV_SYSTEM_NTSC;
1435         break;
1436
1437         /* Europe - PAL */
1438     case 0x50:
1439         system = TV_SYSTEM_PAL;
1440         break;
1441
1442     case 'S':   /* Spain */
1443         system = TV_SYSTEM_PAL;
1444         break;
1445
1446         /* Australia */
1447     case 0x55:
1448         system = TV_SYSTEM_PAL;
1449         break;
1450
1451     case 0x58:
1452         system = TV_SYSTEM_PAL;
1453         break;
1454
1455         /* Australia */
1456     case 0x59:
1457         system = TV_SYSTEM_PAL;
1458         break;
1459
1460     case 0x20:
1461     case 0x21:
1462     case 0x38:
1463     case 0x70:
1464         system = TV_SYSTEM_PAL;
1465         break;
1466
1467         /* ??? */
1468     default:
1469         system = TV_SYSTEM_PAL;
1470         break;
1471     }
1472
1473     return system;
1474 }
1475
1476