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