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