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