Some attempts to speedup Rice when using FB
[mupen64plus-pandora.git] / source / gles2rice / src / RSP_Parser.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 <algorithm>
21 #include <SDL.h>
22
23 #include "ConvertImage.h"
24 #include "GraphicsContext.h"
25 #include "Render.h"
26 #include "RenderTexture.h"
27 #include "Video.h"
28 #include "ucode.h"
29 #include <time.h>
30
31 //////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////
33 //                    uCode Config                      //
34 //////////////////////////////////////////////////////////
35 //////////////////////////////////////////////////////////
36 #define MAX_UCODE_INFO  16
37 UcodeInfo ucodeInfo[MAX_UCODE_INFO];
38
39 RDPInstruction LoadedUcodeMap[256];
40 char* LoadedUcodeNameMap[256];
41
42 OSTask *g_pOSTask = NULL;
43 UcodeInfo lastUcodeInfo;
44 UcodeInfo UsedUcodes[MAX_UCODE_INFO];
45 const uint32 maxUsedUcodes = sizeof(UsedUcodes)/sizeof(UcodeInfo);
46
47 //////////////////////////////////////////////////////////
48 //////////////////////////////////////////////////////////
49 //                     Ucodes                           //
50 //////////////////////////////////////////////////////////
51 //////////////////////////////////////////////////////////
52
53 UcodeMap *ucodeMaps[] = 
54 {
55     &ucodeMap0,             // ucode 0 - Mario
56     &ucodeMap1,             // ucode 1 - GBI1
57     NULL,                   // ucode 2 - Golden Eye
58     &ucodeMap3,             // ucode 3 - S2DEX GBI2
59     NULL,                   // ucode 4 - Wave Racer
60     &ucodeMap5,             // ucode 5 - BGI2
61     NULL,                   // ucode 6 - DKR
62     &ucodeMap7,             // ucode 7 - S2DEX
63     NULL,                   // ucode 8 - ucode 0 with sprite2D, for Demo Puzzle Master 64
64     NULL,                   // ucode 9 - Perfect Dark
65     NULL,                   // ucode 10 - Conker
66     NULL,                   // ucode 11 - Gemini
67     NULL,                   // ucode 12 - Silicon Valley, Spacestation
68     NULL,                   // ucode 13 - modified ucode S2DEX
69     NULL,                   // ucode 14 - OgreBattle Background
70     NULL,                   // ucode 15 - ucode 0 with sprite2D
71     NULL,                   // ucode 16 - Star War, Shadow of Empire
72     NULL,                   // ucode 17 - Star Wars - Rogue Squadron, 
73     NULL,                   // ucode 18 - World Driver Championship
74     NULL,                   // ucode 19 - Last Legion UX
75     &ucodeMap1,             // ucode 20 - ZSortp
76 };
77
78 uint32 vertexMultVals[] =
79 {
80     10, // ucode 0 - Mario
81     2,  // ucode 1 - GBI1
82     10, // ucode 2 - Golden Eye
83     2,  // ucode 3 - S2DEX GBI2
84     5,  // ucode 4 - Wave Racer
85     2,  // ucode 5 - BGI2
86     10, // ucode 6 - DKR
87     2,  // ucode 7 - S2DEX
88     10, // ucode 8 - ucode 0 with sprite2D, for Demo Puzzle Master 64
89     10, // ucode 9 - Perfect Dark
90     2,  // ucode 10 - Conker
91     10, // ucode 11 - Gemini
92     2,  // ucode 12 - Silicon Valley, Spacestation
93     2,  // ucode 13 - modified ucode S2DEX
94     2,  // ucode 14 - OgreBattle Background
95     10, // ucode 15 - ucode 0 with sprite2D
96     5,  // ucode 16 - Star War, Shadow of Empire
97
98     2,  // ucode 17 - Star Wars - Rogue Squadron, 
99     2,  // ucode 18 - World Driver Championship, check me here
100     2,  // ucode 19 - Last Legion UX, check me here
101     2,  // ucode 20 - ZSortp
102 };
103
104 unsigned char gLastMicrocodeString[ 300 ] = "";
105
106 //*****************************************************************************
107 //
108 //*****************************************************************************
109 static UcodeData g_UcodeData[] = 
110 {
111     //crc_size, crc_800;
112
113     {0, 0x150c3ce8, 0x150c3ce8, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Super Mario 64
114     {4, 0x2b94276f, 0x2b94276f, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Wave Race 64 (v1.0)
115     {16,0xb1870454, 0xb1870454, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Star Wars - Shadows of the Empire (v1.0), 
116     {0, 0x51671ae4, 0x51671ae4, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Pilot Wings 64, 
117     {0, 0x67b5ac55, 0x67b5ac55, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Wibble, 
118     {0, 0x64dc8104, 0x64dc8104, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Dark Rift, 
119     {0, 0x309f363d, 0x309f363d, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Killer Instinct Gold, 
120     {0, 0xfcb57e57, 0xfcb57e57, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Blast Corps, 
121     {0, 0xb420f35a, 0xb420f35a, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Blast Corps, 
122     {0, 0x6e26c1df, 0x7c98e9c2, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, 
123     {2, 0xc02ac7bc, 0xc02ac7bc, (unsigned char*)"RSP SW Version: 2.0G, 09-30-96",}, // GoldenEye 007, 
124     {0, 0xe5fee3bc, 0xe5fee3bc, (unsigned char*)"RSP SW Version: 2.0G, 09-30-96",}, // Aero Fighters Assault, 
125     {8, 0xe4bb5ad8, 0x80129845, (unsigned char*)"RSP SW Version: 2.0G, 09-30-96",}, // Puzzle Master 64, 
126     {0, 0x72109ec6, 0x72109ec6, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Duke Nukem 64, 
127     {0, 0xf24a9a04, 0xf24a9a04, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Tetrisphere, 
128     {15,0x700de42e, 0x700de42e, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Wipeout 64 (uses GBI1 too!), 
129     {15,0x1b304a74, 0x1b304a74, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Flying Dragon, 
130     {15,0xe4bb5ad8, 0xa7b2f704, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Silicon Valley, 
131     {15,0xe4bb5ad8, 0x88202781, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Glover, 
132     {0, 0xe466b5bd, 0xe466b5bd, (unsigned char*)"Unknown 0xe466b5bd, 0xe466b5bd",}, // Dark Rift, 
133     {9, 0x7064a163, 0x7064a163, (unsigned char*)"Unknown 0x7064a163, 0x7064a163",}, // Perfect Dark (v1.0), 
134     {0, 0x6522df69, 0x71bd078d, (unsigned char*)"Unknown 0x6522df69, 0x71bd078d",}, // Tetris 
135     {0, 0x6522df69, 0x1b0c23a8, (unsigned char*)"Unknown 0x6522df69, 0x1b0c23a8",}, // Pachinko Nichi 
136
137     // GBI1
138     
139     {1, 0x45ca328e, 0x45ca328e, (unsigned char*)"RSP Gfx ucode F3DLX         0.95 Yoshitaka Yasumoto Nintendo.",},    // Mario Kart 64, 
140     {1, 0x98e3b909, 0x98e3b909, (unsigned char*)"RSP Gfx ucode F3DEX         0.95 Yoshitaka Yasumoto Nintendo.",},    // Mario Kart 64
141     {1, 0x5d446090, 0x5d446090, (unsigned char*)"RSP Gfx ucode F3DLP.Rej     0.96 Yoshitaka Yasumoto Nintendo.",0,1}, // Jikkyou J. League Perfect Striker, 
142     {1, 0x244f5ca3, 0x244f5ca3, (unsigned char*)"RSP Gfx ucode F3DEX         1.00 Yoshitaka Yasumoto Nintendo.",},    // F-1 Pole Position 64, 
143     {1, 0x6a022585, 0x6a022585, (unsigned char*)"RSP Gfx ucode F3DEX.NoN     1.00 Yoshitaka Yasumoto Nintendo.",1},   // Turok - The Dinosaur Hunter (v1.0), 
144     {1, 0x150706be, 0x150706be, (unsigned char*)"RSP Gfx ucode F3DLX.NoN     1.00 Yoshitaka Yasumoto Nintendo.",1},   // Extreme-G, 
145     {1, 0x503f2c53, 0x503f2c53, (unsigned char*)"RSP Gfx ucode F3DEX.NoN     1.21 Yoshitaka Yasumoto Nintendo.",1},   // Bomberman 64, 
146     {1, 0xc705c37c, 0xc705c37c, (unsigned char*)"RSP Gfx ucode F3DLX         1.21 Yoshitaka Yasumoto Nintendo.",},    // Fighting Force 64, Wipeout 64
147     {1, 0xa2146075, 0xa2146075, (unsigned char*)"RSP Gfx ucode F3DLX.NoN     1.21 Yoshitaka Yasumoto Nintendo.",1},   // San Francisco Rush - Extreme Racing, 
148     {1, 0xb65aa2da, 0xb65aa2da, (unsigned char*)"RSP Gfx ucode L3DEX         1.21 Yoshitaka Yasumoto Nintendo.",},    // Wipeout 64, 
149     {1, 0x0c8e5ec9, 0x0c8e5ec9, (unsigned char*)"RSP Gfx ucode F3DEX         1.21 Yoshitaka Yasumoto Nintendo.",},    // 
150     {1, 0xe30795f2, 0xa53df3c4, (unsigned char*)"RSP Gfx ucode F3DLP.Rej     1.21 Yoshitaka Yasumoto Nintendo.",0,1},
151
152     {1, 0xaebeda7d, 0xaebeda7d, (unsigned char*)"RSP Gfx ucode F3DLX.Rej     1.21 Yoshitaka Yasumoto Nintendo.",0,1}, // Jikkyou World Soccer 3, 
153     {1, 0x0c8e5ec9, 0x0c8e5ec9, (unsigned char*)"RSP Gfx ucode F3DEX         1.23 Yoshitaka Yasumoto Nintendo" ,},    // Wave Race 64 (Rev. 2) - Shindou Rumble Edition (JAP) 
154     {1, 0xc705c37c, 0xc705c37c, (unsigned char*)"RSP Gfx ucode F3DLX         1.23 Yoshitaka Yasumoto Nintendo.",},    // GT
155     {1, 0x2a61350d, 0x2a61350d, (unsigned char*)"RSP Gfx ucode F3DLX         1.23 Yoshitaka Yasumoto Nintendo.",},    // Toy Story2
156     {1, 0x0c8e5ec9, 0x0c8e5ec9, (unsigned char*)"RSP Gfx ucode F3DEX         1.23 Yoshitaka Yasumoto Nintendo.",},    // Wave Race 64 Shindou Edition
157     {12,0xfc6529aa, 0xfc6529aa, (unsigned char*)"RSP Gfx ucode F3DEX         1.23 Yoshitaka Yasumoto Nintendo.",},    // Superman - The Animated Series, 
158     {1, 0xa56cf996, 0xa56cf996, (unsigned char*)"RSP Gfx ucode L3DEX         1.23 Yoshitaka Yasumoto Nintendo.",},    // Flying Dragon, 
159     {1, 0xcc83b43f, 0xcc83b43f, (unsigned char*)"RSP Gfx ucode F3DEX.NoN     1.23 Yoshitaka Yasumoto Nintendo.",1},   // AeroGauge, 
160     {1, 0xca8927a0, 0xca8927a0, (unsigned char*)"RSP Gfx ucode F3DLX.Rej     1.23 Yoshitaka Yasumoto Nintendo.",0,1}, // Puzzle Bobble 64, 
161     {1, 0x25689c75, 0xbe481ae8, (unsigned char*)"RSP Gfx ucode F3DLP.Rej     1.23 Yoshitaka Yasumoto Nintendo.",0,1},
162     {1, 0xd2d747b7, 0xd2d747b7, (unsigned char*)"RSP Gfx ucode F3DLX.NoN     1.23 Yoshitaka Yasumoto Nintendo.",1},   // Penny Racers, 
163     {1, 0xa849c858, 0x5bd32b5a, (unsigned char*)"RSP Gfx ucode F3DTEX/A      1.23 Yoshitaka Yasumoto Nintendo.",},    // Tamagotchi 
164
165     {7, 0xecd8b772, 0xecd8b772, (unsigned char*)"RSP Gfx ucode S2DEX  1.06 Yoshitaka Yasumoto Nintendo.",},           // Yoshi's Story, 
166     {7, 0xf59132f5, 0xf59132f5, (unsigned char*)"RSP Gfx ucode S2DEX  1.07 Yoshitaka Yasumoto Nintendo.",},           // Bakuretsu Muteki Bangaioh, 
167     {7, 0x961dd811, 0x961dd811, (unsigned char*)"RSP Gfx ucode S2DEX  1.03 Yoshitaka Yasumoto Nintendo.",},           // GT
168
169     {5, 0x3e083afa, 0x722f97cc, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   fifo 2.03  Yoshitaka Yasumoto 1998 Nintendo.",1},    // F-Zero X, 
170     {5, 0xa8050bd1, 0xa8050bd1, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.03  Yoshitaka Yasumoto 1998 Nintendo.",},     // F-Zero X, 
171     {5, 0x4e8055f0, 0x4e8055f0, (unsigned char*)"RSP Gfx ucode F3DLX.Rej   fifo 2.03  Yoshitaka Yasumoto 1998 Nintendo.",0,1},  // F-Zero X, 
172     {5, 0xabf001f5, 0xabf001f5, (unsigned char*)"RSP Gfx ucode F3DFLX.Rej  fifo 2.03F Yoshitaka Yasumoto 1998 Nintendo.",0,1},  // F-Zero X, 
173     {5, 0xadb4b686, 0xadb4b686, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.04  Yoshitaka Yasumoto 1998 Nintendo.",},     // Top Gear Rally 2, 
174     {5, 0x779e2a9b, 0x779e2a9b, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   fifo 2.04  Yoshitaka Yasumoto 1998 Nintendo.",1},    // California Speed, 
175     {5, 0xa8cb3e09, 0xa8cb3e09, (unsigned char*)"RSP Gfx ucode L3DEX       fifo 2.04  Yoshitaka Yasumoto 1998 Nintendo.",},     // In-Fisherman Bass Hunter 64, 
176     {5, 0x2a1341d6, 0x2a1341d6, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.04H Yoshitaka Yasumoto 1998 Nintendo.",},     // Kirby 64 - The Crystal Shards, 
177     {5, 0x3e083afa, 0x89a8e0ed, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   fifo 2.05  Yoshitaka Yasumoto 1998 Nintendo.",1},    // Carmageddon 64 (uncensored), 
178     {5, 0x4964b75d, 0x4964b75d, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   fifo 2.05  Yoshitaka Yasumoto 1998 Nintendo.",1}, 
179     {5, 0x39e3e95a, 0x39e3e95a, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.05  Yoshitaka Yasumoto 1998 Nintendo."},      // Knife Edge - Nose Gunner, 
180     {5, 0xd2913522, 0xd2913522, (unsigned char*)"RSP Gfx ucode F3DAM       fifo 2.05  Yoshitaka Yasumoto 1998 Nintendo."},      // Hey You, Pikachu!, 
181     {5, 0x3e083afa, 0xc998443f, (unsigned char*)"RSP Gfx ucode F3DEX       xbus 2.05  Yoshitaka Yasumoto 1998 Nintendo."},      //Triple play
182     {5, 0xf4184a7d, 0xf4184a7d, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.06  Yoshitaka Yasumoto 1998 Nintendo.",},     // Hey You, Pikachu!, 
183     {5, 0x595a88de, 0x595a88de, (unsigned char*)"RSP Gfx ucode F3DEX.Rej   fifo 2.06  Yoshitaka Yasumoto 1998 Nintendo.",0,1},  // Bio Hazard 2, 
184     {5, 0x0259f764, 0x0259f764, (unsigned char*)"RSP Gfx ucode F3DLX.Rej   fifo 2.06  Yoshitaka Yasumoto 1998 Nintendo.",0,1},  // Mario Party, 
185     {5, 0xe1a5477a, 0xe1a5477a, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   xbus 2.06  Yoshitaka Yasumoto 1998 Nintendo.",1},    // Command & Conquer, 
186     {5, 0x4cfa0a19, 0x4cfa0a19, (unsigned char*)"RSP Gfx ucode F3DZEX.NoN  fifo 2.06H Yoshitaka Yasumoto 1998 Nintendo.",1},    // The Legend of Zelda - Ocarina of Time (v1.0), 
187     {5, 0x2cbd9514, 0x5f40b9f5, (unsigned char*)"RSP Gfx ucode F3DZEX.NoN  fifo 2.06H Yoshitaka Yasumoto 1998 Nintendo.",1}, 
188
189     {5, 0x3e083afa, 0x882680f4, (unsigned char*)"RSP Gfx ucode L3DEX       fifo 2.07  Yoshitaka Yasumoto 1998 Nintendo."},      // Polaris Sno
190
191     {5, 0xdeb1cac0, 0xdeb1cac0, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   fifo 2.07  Yoshitaka Yasumoto 1998 Nintendo.",1},    // Knockout Kings 2000, 
192     {5, 0xf4184a7d, 0xf4184a7d, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.07  Yoshitaka Yasumoto 1998 Nintendo.",},     // Xena Warrior Princess - Talisman of Fate, Army Men - Air Combat, Destruction Derby
193     {5, 0x4b013e60, 0x4b013e60, (unsigned char*)"RSP Gfx ucode F3DEX       xbus 2.07  Yoshitaka Yasumoto 1998 Nintendo.",},     // Lode Runner 3-D, 
194     {5, 0xd1a63836, 0xd1a63836, (unsigned char*)"RSP Gfx ucode L3DEX       fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // Hey You, Pikachu!, 
195     {5, 0x97193667, 0x97193667, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // Top Gear Hyper-Bike, 
196     {5, 0x92149ba8, 0x92149ba8, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.08  Yoshitaka Yasumoto/Kawasedo 1999.",},     // Paper Mario, 
197     {5, 0xae0fb88f, 0xae0fb88f, (unsigned char*)"RSP Gfx ucode F3DEX       xbus 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // WWF WrestleMania 2000, 
198     {5, 0xc572f368, 0xc572f368, (unsigned char*)"RSP Gfx ucode F3DLX.Rej   xbus 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // WWF No Mercy, 
199     {5, 0x3e083afa, 0x74252492, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   xbus 2.08  Yoshitaka Yasumoto 1999 Nintendo.",1}, 
200
201     {5, 0x9c2edb70, 0xea98e740, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",1},    // LEGO Racers, 
202     {5, 0x79e004a6, 0x79e004a6, (unsigned char*)"RSP Gfx ucode F3DLX.Rej   fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",0,1},  // Mario Party 2, 
203     {5, 0xaa6ab3ca, 0xaa6ab3ca, (unsigned char*)"RSP Gfx ucode F3DEX.Rej   fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",0,1},  // V-Rally Edition 99, 
204     {5, 0x2c597e0f, 0x2c597e0f, (unsigned char*)"RSP Gfx ucode F3DEX       fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // Cruis'n Exotica,
205     {10, 0x4e5f3e3b, 0x4e5f3e3b,(unsigned char*)"RSP Gfx ucode F3DEXBG.NoN fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",1},    // Conker The Bad Fur Day 
206     {5, 0x61f31862, 0x61f31862, (unsigned char*)"RSP Gfx ucode F3DEX.NoN   fifo 2.08H Yoshitaka Yasumoto 1999 Nintendo.",1},    // Pokemon Snap, 
207     {5, 0x005f5b71, 0x005f5b71, (unsigned char*)"RSP Gfx ucode F3DZEX.NoN  fifo 2.08I Yoshitaka Yasumoto/Kawasedo 1999.",1},    // The Legend of Zelda 2 - Majora's Mask, 
208
209     {3, 0x41839d1e, 0x41839d1e, (unsigned char*)"RSP Gfx ucode S2DEX       fifo 2.05  Yoshitaka Yasumoto 1998 Nintendo.",},     // Chou Snobow Kids, 
210     {3, 0x2cbd9514, 0xc639dbb9, (unsigned char*)"RSP Gfx ucode S2DEX       xbus 2.06  Yoshitaka Yasumoto 1998 Nintendo.",},
211     {3, 0xec89e273, 0xec89e273, (unsigned char*)"RSP Gfx ucode S2DEX       fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // V-Rally Edition 99, 
212     {3, 0x9429b7d6, 0x9429b7d6, (unsigned char*)"RSP Gfx ucode S2DEX       xbus 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // Star Craft, 
213     //{14,0x5a72397b, 0xec89e273, "RSP Gfx ucode S2DEX       fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},                   // OgreBattle Background, 
214     {3, 0x2cbd9514, 0xec89e273, (unsigned char*)"RSP Gfx ucode S2DEX       fifo 2.08  Yoshitaka Yasumoto 1999 Nintendo.",},     // Zelda MM, 
215
216     {6, 0x6aef74f8, 0x6aef74f8, (unsigned char*)"Unknown 0x6aef74f8, 0x6aef74f8",}, // Diddy Kong Racing (v1.0), 
217     {6, 0x4c4eead8, 0x4c4eead8, (unsigned char*)"Unknown 0x4c4eead8, 0x4c4eead8",}, // Diddy Kong Racing (v1.1), 
218
219     {1, 0xed421e9a, 0xed421e9a, (unsigned char*)"Unknown 0xed421e9a, 0xed421e9a",}, // Kuiki Uhabi Suigo, 
220     {5, 0x37751932, 0x55c0fd25, (unsigned char*)"Unknown 0x37751932, 0x55c0fd25",}, // Bio Hazard 2, 
221     {11,0xbe0b83e7, 0xbe0b83e7,(unsigned char*)"Unknown 0xbe0b83e7, 0xbe0b83e7",},  // Jet Force Gemini, 
222
223     {17, 0x02e882cf, 0x2ad17281, (unsigned char*)"Unknown 0x02e882cf, 0x2ad17281",}, // Indiana Jones, 
224     {17, 0x1f7d9118, 0xdab2199b, (unsigned char*)"Unknown 0x1f7d9118, 0xdab2199b",}, // Battle Naboo, 
225     {17, 0x74583614, 0x74583614, (unsigned char*)"Unknown 0x74583614, 0x74583614",}, // Star Wars - Rogue Squadron, 
226     {17, 0xe37e2f49, 0x1eb63fd8, (unsigned char*)"Unknown 0xe37e2f49, 0x1eb63fd8",}, // Star Wars - Rogue Squadron, 
227     {17, 0x8ce1af3d, 0xb2760ea2, (unsigned char*)"Unknown 0x8ce1af3d, 0xb2760ea2",}, // Star Wars - Rogue Squadron, 
228
229     {18, 0x7b685972, 0x57b8095a, (unsigned char*)"Unknown 0x7b685972, 0x57b8095a",}, // World Driver Championship
230     {18, 0xe92dbb9b, 0x57b8095a, (unsigned char*)"Unknown 0xe92dbb9b, 0x57b8095a",}, // World Driver Championship
231     {18, 0xe6c9acc1, 0x65f80845, (unsigned char*)"Unknown 0xe6c9acc1, 0x65f80845",}, // World Driver Championship
232     {18, 0x6522df69, 0x720b88a0, (unsigned char*)"Unknown 0x6522df69, 0x720b88a0",}, // World Driver Championship
233     {18, 0x6522df69, 0xf1e8ba9e, (unsigned char*)"Unknown 0x6522df69, 0xf1e8ba9e",}, // World Driver Championship
234
235     {19, 0xa486bed3, 0xa486bed3, (unsigned char*)"Unknown 0xa486bed3, 0xa486bed3",}, // Last Legion UX, 
236     {19, 0x6b519381, 0xfebacfd8, (unsigned char*)"Unknown in Toukan Road",}, // I don't know which ucode
237
238     {20, 0x6d2a01b1, 0x6d2a01b1, (unsigned char*)"RSP Gfx ucode ZSortp 0.33 Yoshitaka Yasumoto Nintendo.",}, // Mia Hamm Soccer 64, 
239 };
240
241 FiddledVtx * g_pVtxBase=NULL;
242
243 SetImgInfo g_TI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 };
244 SetImgInfo g_CI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 };
245 SetImgInfo g_ZI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 };
246 RenderTextureInfo g_ZI_saves[2];
247
248 DListStack  gDlistStack[MAX_DL_STACK_SIZE];
249 int     gDlistStackPointer= -1;
250
251 TMEMLoadMapInfo g_tmemLoadAddrMap[0x200];   // Totally 4KB TMEM
252 TMEMLoadMapInfo g_tmemInfo0;                // Info for Tmem=0
253 TMEMLoadMapInfo g_tmemInfo1;                // Info for Tmem=0x100
254
255 const char *pszImgSize[4] = {"4", "8", "16", "32"};
256 const char *textluttype[4] = {"RGB16", "I16?", "RGBA16", "IA16"};
257 uint16  g_wRDPTlut[0x200];
258 uint32  g_dwRDPPalCrc[16];
259
260 #include "FrameBuffer.h"
261 #include "RSP_GBI0.h"
262 #include "RSP_GBI1.h"
263 #include "RSP_GBI2.h"
264 #include "RSP_GBI2_ext.h"
265 #include "RSP_GBI_Others.h"
266 #include "RSP_GBI_Sprite2D.h"
267 #include "RDP_Texture.h"
268
269 //////////////////////////////////////////////////////////
270 //////////////////////////////////////////////////////////
271 //                  Init and Reset                      //
272 //////////////////////////////////////////////////////////
273 //////////////////////////////////////////////////////////
274
275 void DLParser_Init()
276 {
277     int i;
278
279     status.gRDPTime = 0;
280     status.gDlistCount = 0;
281     status.gUcodeCount = 0;
282     status.frameReadByCPU = FALSE;
283     status.frameWriteByCPU = FALSE;
284     status.SPCycleCount = 0;
285     status.DPCycleCount = 0;
286     status.bN64IsDrawingTextureBuffer = false;
287     status.bDirectWriteIntoRDRAM = false;
288     status.bHandleN64RenderTexture = false;
289
290     status.bUcodeIsKnown = FALSE;
291     status.lastPurgeTimeTime = status.gRDPTime;
292
293     status.curRenderBuffer = 0;
294     status.curDisplayBuffer = 0;
295     status.curVIOriginReg = 0;
296
297     status.primitiveType = PRIM_TRI1;
298
299     status.lastPurgeTimeTime = 0;       // Time textures were last purged
300
301     status.UseLargerTile[0] = false;
302     status.LargerTileRealLeft[0] = status.LargerTileRealLeft[1] = 0;
303     memset(&g_ZI_saves, 0, sizeof(RenderTextureInfo)*2);
304
305     for( i=0; i<8; i++ )
306     {
307         memset(&gRDP.tiles[i], 0, sizeof(Tile));
308     }
309     memset(g_tmemLoadAddrMap, 0, sizeof(g_tmemLoadAddrMap));
310
311     for( i=0; i<MAX_UCODE_INFO; i++ )
312     {
313         memset(&ucodeInfo[i], 0, sizeof(UcodeInfo));
314     }
315
316     status.bUseModifiedUcodeMap = false;
317     status.ucodeHasBeenSet = false;
318     status.bAllowLoadFromTMEM = true;
319     
320     char name[200];
321     strcpy(name, (char*)g_curRomInfo.szGameName);
322
323     memset(&lastUcodeInfo, 0, sizeof(UcodeInfo));
324     memset(&UsedUcodes, 0, sizeof(UsedUcodes));
325     memset(&g_TmemFlag, 0, sizeof(g_TmemFlag));
326     memset(&g_RecentCIInfo, 0, sizeof(RecentCIInfo)*5);
327     memset(&g_RecentVIOriginInfo, 0, sizeof(RecentViOriginInfo)*5);
328     memset(&g_ZI_saves, 0, sizeof(RenderTextureInfo)*2);
329     memset(&g_ZI, 0, sizeof(SetImgInfo));
330     memset(&g_CI, 0, sizeof(SetImgInfo));
331     memset(&g_TI, 0, sizeof(SetImgInfo));
332
333     status.UseLargerTile[0] = status.UseLargerTile[1] = false;
334     status.LargerTileRealLeft[0] = status.LargerTileRealLeft[1] = 0;
335 }
336
337
338 void RDP_GFX_Reset()
339 {
340     gDlistStackPointer=-1;
341     status.bUcodeIsKnown = FALSE;
342     gTextureManager.RecycleAllTextures();
343 }
344
345
346 void RDP_Cleanup()
347 {
348     if( status.bHandleN64RenderTexture )
349     {
350         g_pFrameBufferManager->CloseRenderTexture(false);
351     }
352 }
353
354 void RDP_SetUcodeMap(int ucode)
355 {
356     status.bUseModifiedUcodeMap = false;
357     switch( ucode )
358     {
359     case 0: // Mario and demos
360         break;
361     case 1: // F3DEX GBI1
362     case 20:
363         break;
364     case 2: // Golden Eye
365         memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap));
366         //LoadedUcodeMap[9]=RSP_GBI1_Sprite2DBase;
367         //LoadedUcodeMap[0xaf]=RSP_GBI1_LoadUCode;
368         //LoadedUcodeMap[0xb0]=RSP_GBI1_BranchZ;
369         LoadedUcodeMap[0xb4]=DLParser_RDPHalf_1_0xb4_GoldenEye;
370         status.bUseModifiedUcodeMap = true;
371         break;
372     case 3: // S2DEX GBI2
373         break;
374     case 4:
375         memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap));
376         LoadedUcodeMap[4]=RSP_Vtx_WRUS;
377         LoadedUcodeMap[0xb1]=RSP_GBI1_Tri2;
378         //LoadedUcodeMap[9]=RSP_GBI1_Sprite2DBase;
379         //LoadedUcodeMap[0xaf]=RSP_GBI1_LoadUCode;
380         //LoadedUcodeMap[0xb0]=RSP_GBI1_BranchZ;
381         //LoadedUcodeMap[0xb2]=RSP_GBI1_ModifyVtx;
382         status.bUseModifiedUcodeMap = true;
383         break;
384     case 5: // F3DEX GBI2
385         break;
386     case 6: // DKR, Jet Force Gemini, Mickey
387     case 11: // DKR, Jet Force Gemini, Mickey
388         memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap));
389         LoadedUcodeMap[1]=RSP_Mtx_DKR;
390         LoadedUcodeMap[4]=RSP_Vtx_DKR;
391         if( ucode == 11 )   LoadedUcodeMap[4]=RSP_Vtx_Gemini;
392         LoadedUcodeMap[5]=RSP_DMA_Tri_DKR;
393         LoadedUcodeMap[7]=RSP_DL_In_MEM_DKR;
394         LoadedUcodeMap[0xbc]=RSP_MoveWord_DKR;
395         LoadedUcodeMap[0xbf]=DLParser_Set_Addr_Ucode6;
396         //LoadedUcodeMap[9]=RSP_GBI1_Sprite2DBase;
397         //LoadedUcodeMap[0xb0]=RSP_GBI1_BranchZ;
398         //LoadedUcodeMap[0xb2]=RSP_GBI1_ModifyVtx;
399         status.bUseModifiedUcodeMap = true;
400         break;
401     case 7: // S2DEX GBI1
402         break;
403     case 8: // Ucode 0 with Sprite2D, Puzzle Master 64
404         memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap));
405         LoadedUcodeMap[RSP_SPRITE2D_BASE] = RSP_GBI_Sprite2D_PuzzleMaster64;
406         LoadedUcodeMap[RSP_SPRITE2D_SCALEFLIP] = RSP_GBI1_Sprite2DScaleFlip;
407         LoadedUcodeMap[RSP_SPRITE2D_DRAW] = RSP_GBI0_Sprite2DDraw;
408         status.bUseModifiedUcodeMap = true;
409         break;
410     case 9: // Perfect Dark
411         memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap));
412         LoadedUcodeMap[4]=RSP_Vtx_PD;
413         LoadedUcodeMap[7]=RSP_Set_Vtx_CI_PD;
414         LoadedUcodeMap[0xb1]=RSP_Tri4_PD;
415         LoadedUcodeMap[0xb4]=DLParser_RDPHalf_1_0xb4_GoldenEye;
416         status.bUseModifiedUcodeMap = true;
417         break;
418     case 10: // Conker BFD
419         memcpy( &LoadedUcodeMap, &ucodeMap5, sizeof(UcodeMap));
420         LoadedUcodeMap[1]=RSP_Vtx_Conker;
421         LoadedUcodeMap[0x10]=DLParser_Tri4_Conker;
422         LoadedUcodeMap[0x11]=DLParser_Tri4_Conker;
423         LoadedUcodeMap[0x12]=DLParser_Tri4_Conker;
424         LoadedUcodeMap[0x13]=DLParser_Tri4_Conker;
425         LoadedUcodeMap[0x14]=DLParser_Tri4_Conker;
426         LoadedUcodeMap[0x15]=DLParser_Tri4_Conker;
427         LoadedUcodeMap[0x16]=DLParser_Tri4_Conker;
428         LoadedUcodeMap[0x17]=DLParser_Tri4_Conker;
429         LoadedUcodeMap[0x18]=DLParser_Tri4_Conker;
430         LoadedUcodeMap[0x19]=DLParser_Tri4_Conker;
431         LoadedUcodeMap[0x1a]=DLParser_Tri4_Conker;
432         LoadedUcodeMap[0x1b]=DLParser_Tri4_Conker;
433         LoadedUcodeMap[0x1c]=DLParser_Tri4_Conker;
434         LoadedUcodeMap[0x1d]=DLParser_Tri4_Conker;
435         LoadedUcodeMap[0x1e]=DLParser_Tri4_Conker;
436         LoadedUcodeMap[0x1f]=DLParser_Tri4_Conker;
437         LoadedUcodeMap[0xdb]=DLParser_MoveWord_Conker;
438         LoadedUcodeMap[0xdc]=DLParser_MoveMem_Conker;
439         status.bUseModifiedUcodeMap = true;
440         break;
441     case 12: // Silicon Velley, Space Station
442         memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap));
443         LoadedUcodeMap[0x01]=RSP_GBI0_Mtx;
444         status.bUseModifiedUcodeMap = true;
445         break;
446     case 13: // modified S2DEX
447         memcpy( &LoadedUcodeMap, &ucodeMap7, sizeof(UcodeMap));
448         //LoadedUcodeMap[S2DEX_BG_1CYC] = ucodeMap1[S2DEX_BG_1CYC];
449         LoadedUcodeMap[S2DEX_OBJ_RECTANGLE] = ucodeMap1[S2DEX_OBJ_RECTANGLE];
450         LoadedUcodeMap[S2DEX_OBJ_SPRITE] = ucodeMap1[S2DEX_OBJ_SPRITE];
451         //LoadedUcodeMap[S2DEX_OBJ_RENDERMODE] = ucodeMap1[S2DEX_OBJ_RENDERMODE];
452         //LoadedUcodeMap[S2DEX_OBJ_RECTANGLE_R] = ucodeMap1[S2DEX_OBJ_RECTANGLE_R];
453         LoadedUcodeMap[S2DEX_RDPHALF_0] = ucodeMap1[S2DEX_RDPHALF_0];
454         status.bUseModifiedUcodeMap = true;
455         break;
456     case 14: // OgreBattle Background
457         memcpy( &LoadedUcodeMap, &ucodeMap5, sizeof(UcodeMap));
458         LoadedUcodeMap[0xda] = DLParser_OgreBatter64BG;
459         LoadedUcodeMap[0xdc] = RSP_S2DEX_OBJ_MOVEMEM;
460         status.bUseModifiedUcodeMap = true;
461         break;
462     case 15: // Ucode 0 with Sprite2D
463         memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap));
464         LoadedUcodeMap[RSP_SPRITE2D_BASE] = RSP_GBI_Sprite2DBase;
465         LoadedUcodeMap[RSP_SPRITE2D_SCALEFLIP] = RSP_GBI1_Sprite2DScaleFlip;
466         LoadedUcodeMap[RSP_SPRITE2D_DRAW] = RSP_GBI0_Sprite2DDraw;
467         status.bUseModifiedUcodeMap = true;
468         break;
469     case 16: // Star War, Shadow Of Empire
470         memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap));
471         LoadedUcodeMap[4]=RSP_Vtx_ShadowOfEmpire;
472         status.bUseModifiedUcodeMap = true;
473         break;
474     case 17:    //Indiana Jones, does not work anyway
475         memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap));
476         LoadedUcodeMap[0]=DLParser_Ucode8_0x0;
477         //LoadedUcodeMap[1]=RSP_RDP_Nothing;
478         LoadedUcodeMap[2]=DLParser_RS_Color_Buffer;
479         LoadedUcodeMap[3]=DLParser_RS_MoveMem;
480         LoadedUcodeMap[4]=DLParser_RS_Vtx_Buffer;
481         LoadedUcodeMap[5]=DLParser_Ucode8_0x05;
482         LoadedUcodeMap[6]=DLParser_Ucode8_DL;
483         LoadedUcodeMap[7]=DLParser_Ucode8_JUMP;
484         LoadedUcodeMap[8]=RSP_RDP_Nothing;
485         LoadedUcodeMap[9]=RSP_RDP_Nothing;
486         LoadedUcodeMap[10]=RSP_RDP_Nothing;
487         LoadedUcodeMap[11]=RSP_RDP_Nothing;
488         LoadedUcodeMap[0x80]=DLParser_RS_Block;
489         LoadedUcodeMap[0xb4]=DLParser_Ucode8_0xb4;
490         LoadedUcodeMap[0xb5]=DLParser_Ucode8_0xb5;
491         LoadedUcodeMap[0xb8]=DLParser_Ucode8_EndDL;
492         LoadedUcodeMap[0xbc]=DLParser_Ucode8_0xbc;
493         LoadedUcodeMap[0xbd]=DLParser_Ucode8_0xbd;
494         LoadedUcodeMap[0xbe]=DLParser_RS_0xbe;
495         LoadedUcodeMap[0xbF]=DLParser_Ucode8_0xbf;
496         LoadedUcodeMap[0xe4]=DLParser_TexRect_Last_Legion;
497         status.bUseModifiedUcodeMap = true;
498         break;
499     case 18: // World Driver Championship
500         memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap));
501         LoadedUcodeMap[0xe]=DLParser_RSP_DL_WorldDriver;
502         LoadedUcodeMap[0x2]=DLParser_RSP_Pop_DL_WorldDriver;
503         LoadedUcodeMap[0xdf]=DLParser_RSP_Pop_DL_WorldDriver;
504         LoadedUcodeMap[0x6]=RSP_RDP_Nothing;
505         status.bUseModifiedUcodeMap = true;
506         break;
507     case 19: // Last Legion UX
508         memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap));
509         LoadedUcodeMap[0x80]=DLParser_RSP_Last_Legion_0x80;
510         LoadedUcodeMap[0x00]=DLParser_RSP_Last_Legion_0x00;
511         LoadedUcodeMap[0xe4]=DLParser_TexRect_Last_Legion;
512         status.bUseModifiedUcodeMap = true;
513         break;
514     default:
515         memcpy( &LoadedUcodeMap, &ucodeMap5, sizeof(UcodeMap));
516         status.bUseModifiedUcodeMap = true;
517         break;
518     }
519
520 #ifdef DEBUGGER
521     if( logMicrocode )
522         TRACE1("Using ucode %d", ucode);
523 #endif
524 }
525
526 void RSP_SetUcode(int ucode, uint32 ucStart, uint32 ucDStart, uint32 ucSize)
527 {
528     if( status.ucodeHasBeenSet && gRSP.ucode == ucode )
529         return;
530
531     status.ucodeHasBeenSet = true;
532
533     if( ucode < 0 )
534         ucode = 5;
535
536     RDP_SetUcodeMap(ucode);
537     if( status.bUseModifiedUcodeMap )
538     {
539         currentUcodeMap = &LoadedUcodeMap[0];
540     }
541     else
542     {
543         currentUcodeMap = *ucodeMaps[ucode];
544     }
545
546     gRSP.vertexMult = vertexMultVals[ucode];
547
548     //if( gRSP.ucode != ucode ) DebuggerAppendMsg("Set to ucode: %d", ucode);
549     gRSP.ucode = ucode;
550
551     lastUcodeInfo.used = true;
552     if( ucStart == 0 )
553     {
554         lastUcodeInfo.ucStart = g_pOSTask->t.ucode;
555         lastUcodeInfo.ucDStart = g_pOSTask->t.ucode_data;
556         lastUcodeInfo.ucSize = g_pOSTask->t.ucode_size;
557     }
558     else
559     {
560         lastUcodeInfo.ucStart = ucStart;
561         lastUcodeInfo.ucDStart = ucDStart;
562         lastUcodeInfo.ucSize = ucSize;
563     }
564 }
565
566 //*****************************************************************************
567 //
568 //*****************************************************************************
569 static uint32 DLParser_IdentifyUcodeFromString( const unsigned char * str_ucode )
570 {
571     const unsigned char str_ucode0[] = "RSP SW Version: 2.0";
572     const unsigned char str_ucode1[] = "RSP Gfx ucode ";
573
574     if ( strncasecmp( (char*)str_ucode, (char*)str_ucode0, strlen((char*)str_ucode0) ) == 0 )
575     {
576         return 0;
577     }
578
579     if ( strncasecmp( (char*)str_ucode, (char*)str_ucode1, strlen((char*)str_ucode1) ) == 0 )
580     {
581         if( strstr((char*)str_ucode,"1.") != 0 )
582         {
583             if( strstr((char*)str_ucode,"S2DEX") != 0 )
584             {
585                 return 7;
586             }
587             else
588                 return 1;
589         }
590         else if( strstr((char*)str_ucode,"2.") != 0 )
591         {
592             if( strstr((char*)str_ucode,"S2DEX") != 0 )
593             {
594                 return 3;
595             }
596             else
597                 return 5;
598         }
599     }
600
601     return 5;
602 }
603
604 //*****************************************************************************
605 //
606 //*****************************************************************************
607 static uint32 DLParser_IdentifyUcode( uint32 crc_size, uint32 crc_800, char* str )
608 {
609     for ( uint32 i = 0; i < sizeof(g_UcodeData)/sizeof(UcodeData); i++ )
610     {
611 #ifdef DEBUGGER
612         if ( crc_800 == g_UcodeData[i].crc_800 )
613         {
614             if( strlen(str)==0 || strcmp((const char *) g_UcodeData[i].ucode_name, str) == 0 ) 
615             {
616                 TRACE0((const char *) g_UcodeData[i].ucode_name);
617             }
618             else
619             {
620                 DebuggerAppendMsg("Incorrect description for this ucode:\n%x, %x, %s",crc_800, crc_size, str);
621             }
622             status.bUcodeIsKnown = TRUE;
623             gRSP.bNearClip = !g_UcodeData[i].non_nearclip;
624             gRSP.bRejectVtx = g_UcodeData[i].reject;
625             DebuggerAppendMsg("Identify ucode = %d, crc = %08X, %s", g_UcodeData[i].ucode, crc_800, str);
626             return g_UcodeData[i].ucode;
627         }
628 #else
629         if ( crc_800 == g_UcodeData[i].crc_800 )
630         {
631             status.bUcodeIsKnown = TRUE;
632             gRSP.bNearClip = !g_UcodeData[i].non_nearclip;
633             gRSP.bRejectVtx = g_UcodeData[i].reject;
634             return g_UcodeData[i].ucode;
635         }
636 #endif
637     }
638
639 #ifdef DEBUGGER
640     {
641         static bool warned = false;
642         if( warned == false )
643         {
644             warned = true;
645             TRACE0("Can not identify ucode for this game");
646         }
647     }
648 #endif
649     gRSP.bNearClip = false;
650     gRSP.bRejectVtx = false;
651     status.bUcodeIsKnown = FALSE;
652     return ~0;
653 }
654
655 uint32 DLParser_CheckUcode(uint32 ucStart, uint32 ucDStart, uint32 ucSize, uint32 ucDSize)
656 {
657     if( options.enableHackForGames == HACK_FOR_ROGUE_SQUADRON )
658     {
659         return 17;
660     }
661
662     // Check the used ucode table first
663     int usedUcodeIndex = 0;
664     for( usedUcodeIndex=0; (unsigned int)usedUcodeIndex<maxUsedUcodes; usedUcodeIndex++ )
665     {
666         if( UsedUcodes[usedUcodeIndex].used == false )
667         {
668             break;
669         }
670
671         if( UsedUcodes[usedUcodeIndex].ucStart == ucStart && UsedUcodes[usedUcodeIndex].ucSize == ucSize &&
672             UsedUcodes[usedUcodeIndex].ucDStart == ucDStart /*&& UsedUcodes[usedUcodeIndex].ucDSize == ucDSize*/ )
673         {
674 #ifdef DEBUGGER
675             if(gRSP.ucode != (int)UsedUcodes[usedUcodeIndex].ucode && logMicrocode)
676             {
677                 DebuggerAppendMsg("Check, ucode = %d, crc = %08X, %s", UsedUcodes[usedUcodeIndex].ucode, 
678                     UsedUcodes[usedUcodeIndex].crc_800 , UsedUcodes[usedUcodeIndex].rspstr);
679             }
680 #endif
681             lastUcodeInfo.ucStart = ucStart;
682             lastUcodeInfo.used = true;
683             lastUcodeInfo.ucDStart = ucDStart;
684             lastUcodeInfo.ucSize = ucSize;
685             return UsedUcodes[usedUcodeIndex].ucode;
686         }
687     }
688
689     uint32 base = ucDStart & 0x1fffffff;
690     unsigned char str[300] = "";
691     if( base < g_dwRamSize+0x1000 )
692     {
693         for ( uint32 i = 0; i < 0x1000; i++ )
694         {
695             if ( g_pRDRAMs8[ base + ((i+0) ^ 3) ] == 'R' &&
696                  g_pRDRAMs8[ base + ((i+1) ^ 3) ] == 'S' &&
697                  g_pRDRAMs8[ base + ((i+2) ^ 3) ] == 'P' )
698             {
699                 unsigned char * p = str;
700                 while ( g_pRDRAMs8[ base + (i ^ 3) ] >= ' ')
701                 {
702                     *p++ = g_pRDRAMs8[ base + (i ^ 3) ];
703                     i++;
704                 }
705                 *p++ = 0;
706                 break;
707             }
708         }
709     }
710
711     //if ( strcmp( str, gLastMicrocodeString ) != 0 )
712     {
713         //uint32 size = ucDSize;
714         base = ucStart & 0x1fffffff;
715
716         uint32 crc_size = ComputeCRC32( 0, &g_pRDRAMu8[ base ], 8);//size );
717         uint32 crc_800 = ComputeCRC32( 0, &g_pRDRAMu8[ base ], 0x800 );
718         uint32 ucode;
719         ucode = DLParser_IdentifyUcode( crc_size, crc_800, (char*)str );
720         if ( (int)ucode == ~0 )
721         {
722 #ifdef DEBUGGER
723             static bool warned=false;
724             //if( warned == false )
725             {
726                 char message[300];
727
728                 sprintf(message, "Unable to find ucode to use for '%s' CRCSize: 0x%08x CRC800: 0x%08x",
729                         str, crc_size, crc_800);
730                 TRACE0(message);
731                 DebugMessage(M64MSG_ERROR, message);
732                 warned = true;
733             }
734 #endif
735             ucode = DLParser_IdentifyUcodeFromString(str);
736             if ( (int)ucode == ~0 )
737             {
738                 ucode=5;
739             }
740         }
741
742         //DLParser_SetuCode( ucode );
743         
744 #ifdef DEBUGGER
745         {
746             static bool warned=false;
747             if( warned == false )
748             {
749                 warned = true;
750                 if( strlen((char *) str) == 0 )
751                     DebuggerAppendMsg("Can not find RSP string in the DLIST, CRC800: 0x%08x, CRCSize: 0x%08x", crc_800, crc_size);
752                 else
753                     TRACE0((char *) str);
754             }
755         }
756 #endif
757         strcpy( (char*)gLastMicrocodeString, (char*)str );
758
759         if( usedUcodeIndex >= MAX_UCODE_INFO )
760         {
761             usedUcodeIndex = rand()%MAX_UCODE_INFO;
762         }
763
764         UsedUcodes[usedUcodeIndex].ucStart = ucStart;
765         UsedUcodes[usedUcodeIndex].ucSize = ucSize;
766         UsedUcodes[usedUcodeIndex].ucDStart = ucDStart;
767         UsedUcodes[usedUcodeIndex].ucDSize = ucDSize;
768         UsedUcodes[usedUcodeIndex].ucode = ucode;
769         UsedUcodes[usedUcodeIndex].crc_800 = crc_800;
770         UsedUcodes[usedUcodeIndex].crc_size = crc_size;
771         UsedUcodes[usedUcodeIndex].used = true;
772         strcpy( UsedUcodes[usedUcodeIndex].rspstr, (char*)str );
773
774         TRACE2("New ucode has been detected:\n%s, ucode=%d", str, ucode);
775     
776         return ucode;
777     }
778 }
779
780 extern int dlistMtxCount;
781 extern bool bHalfTxtScale;
782
783 extern float mspervi;
784 extern float numvi;
785 static int skipframe=0;
786 static unsigned int oldtick=0;
787 static int oldskip=0;
788 extern bool skipping;
789
790 void DLParser_Process(OSTask * pTask)
791 {
792     static int skipframe=0;
793     //BOOL menuWaiting = FALSE;
794
795     dlistMtxCount = 0;
796     bHalfTxtScale = false;
797
798     if ( CRender::g_pRender == NULL)
799     {
800         TriggerDPInterrupt();
801         TriggerSPInterrupt();
802         return;
803     }
804
805     status.bScreenIsDrawn = true;
806 /*    if( options.bSkipFrame )
807     {
808         skipframe++;
809         if(skipframe%2)
810         {
811             TriggerDPInterrupt();
812             TriggerSPInterrupt();
813             return;
814         }
815     }
816 */
817     if( currentRomOptions.N64RenderToTextureEmuType != TXT_BUF_NONE && defaultRomOptions.bSaveVRAM )
818     {
819         g_pFrameBufferManager->CheckRenderTextureCRCInRDRAM();
820     }
821
822     unsigned int newtick=0;
823     static int count = 0;
824     if( options.bSkipFrame )
825     {
826         skipping=false;
827         newtick = SDL_GetTicks();
828         if (newtick-oldtick>400 || skipframe>4 || numvi==0) {
829                 oldtick=newtick;                        // too long frame delay, something must have gone wrong
830                 skipping=false;
831         } else
832         if ((float)(newtick-oldtick)>=mspervi*numvi+3.0f) {
833                 skipping=true;
834         }
835         // don't jump frameskipping...
836         if (skipping) {
837                 //want to skip, be progress slowly...
838                 if (skipframe>oldskip+1)
839                         skipping = false;
840         }
841         if (skipping) {
842                 skipframe++;
843                 status.bScreenIsDrawn = false;
844                 TriggerDPInterrupt();
845                 TriggerSPInterrupt();
846                 return;
847         }
848         oldskip = skipframe;
849         skipframe=0;
850         oldtick=newtick;
851         numvi=0;
852     }
853
854     g_pOSTask = pTask;
855     
856     DebuggerPauseCountN( NEXT_DLIST );
857     status.gRDPTime = (uint32) SDL_GetTicks();
858
859     status.gDlistCount++;
860
861     if ( lastUcodeInfo.ucStart != (uint32)(pTask->t.ucode) )
862     {
863         uint32 ucode = DLParser_CheckUcode(pTask->t.ucode, pTask->t.ucode_data, pTask->t.ucode_size, pTask->t.ucode_data_size);
864         RSP_SetUcode(ucode, pTask->t.ucode, pTask->t.ucode_data, pTask->t.ucode_size);
865         DEBUGGER_PAUSE_AND_DUMP(NEXT_SWITCH_UCODE,{DebuggerAppendMsg("Pause at switching ucode");});
866     }
867
868     // Initialize stack
869     status.bN64FrameBufferIsUsed = false;
870     gDlistStackPointer=0;
871     gDlistStack[gDlistStackPointer].pc = (uint32)pTask->t.data_ptr;
872     gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
873     DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((gDlistStack[gDlistStackPointer].pc == 0 && pauseAtNext && eventToPause==NEXT_UNKNOWN_OP),
874             {DebuggerAppendMsg("Start Task without DLIST: ucode=%08X, data=%08X", (uint32)pTask->t.ucode, (uint32)pTask->t.ucode_data);});
875
876
877     // Check if we need to purge (every 5 milliseconds)
878     if (status.gRDPTime - status.lastPurgeTimeTime > 5)
879     {
880         gTextureManager.PurgeOldTextures();
881         status.lastPurgeTimeTime = status.gRDPTime;
882     }
883
884     status.dwNumDListsCulled = 0;
885     status.dwNumTrisRendered = 0;
886     status.dwNumTrisClipped = 0;
887     status.dwNumVertices = 0;
888     status.dwBiggestVertexIndex = 0;
889
890     if( g_curRomInfo.bForceScreenClear && CGraphicsContext::needCleanScene )
891     {
892         CRender::g_pRender->ClearBuffer(true,true);
893         CGraphicsContext::needCleanScene = false;
894     }
895
896     SetVIScales();
897     CRender::g_pRender->RenderReset();
898     CRender::g_pRender->BeginRendering();
899     CRender::g_pRender->SetViewport(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, 0x3FF);
900     CRender::g_pRender->SetFillMode(options.bWinFrameMode? RICE_FILLMODE_WINFRAME : RICE_FILLMODE_SOLID);
901
902     try
903     {
904         // The main loop
905         while( gDlistStackPointer >= 0 )
906         {
907 #ifdef DEBUGGER
908             DEBUGGER_PAUSE_COUNT_N(NEXT_UCODE);
909             if( debuggerPause )
910             {
911                 DebuggerPause();
912                 CRender::g_pRender->SetFillMode(options.bWinFrameMode? RICE_FILLMODE_WINFRAME : RICE_FILLMODE_SOLID);
913             }
914
915             if (gDlistStack[gDlistStackPointer].pc > g_dwRamSize)
916             {
917                 DebuggerAppendMsg("Error: dwPC is %08X", gDlistStack[gDlistStackPointer].pc );
918                 break;
919             }
920 #endif
921
922             status.gUcodeCount++;
923
924             Gfx *pgfx = (Gfx*)&g_pRDRAMu32[(gDlistStack[gDlistStackPointer].pc>>2)];
925 #ifdef DEBUGGER
926             LOG_UCODE("0x%08x: %08x %08x %-10s", 
927                 gDlistStack[gDlistStackPointer].pc, pgfx->words.w0, pgfx->words.w1, (gRSP.ucode!=5&&gRSP.ucode!=10)?ucodeNames_GBI1[(pgfx->words.w0>>24)]:ucodeNames_GBI2[(pgfx->words.w0>>24)]);
928 #endif
929             gDlistStack[gDlistStackPointer].pc += 8;
930             currentUcodeMap[pgfx->words.w0 >>24](pgfx);
931
932             if ( gDlistStackPointer >= 0 && --gDlistStack[gDlistStackPointer].countdown < 0 )
933             {
934                 LOG_UCODE("**EndDLInMem");
935                 gDlistStackPointer--;
936             }
937         }
938
939     }
940     catch(...)
941     {
942         TRACE0("Unknown exception happens in ProcessDList");
943         TriggerDPInterrupt();
944     }
945
946     CRender::g_pRender->EndRendering();
947
948     if( gRSP.ucode >= 17)
949         TriggerDPInterrupt();
950     TriggerSPInterrupt();
951 }
952
953 //////////////////////////////////////////////////////////
954 //////////////////////////////////////////////////////////
955 //                   Util Functions                     //
956 //////////////////////////////////////////////////////////
957 //////////////////////////////////////////////////////////
958
959 void RDP_NOIMPL_Real(const char* op, uint32 word0, uint32 word1) 
960 {
961 #ifdef DEBUGGER
962     if( logWarning )
963     {
964         TRACE0("Stack Trace");
965         for( int i=0; i<gDlistStackPointer; i++ )
966         {
967             DebuggerAppendMsg("  %08X", gDlistStack[i].pc);
968         }
969         uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8;
970         DebuggerAppendMsg("PC=%08X",dwPC);
971         DebuggerAppendMsg(op, word0, word1);
972     }
973     DEBUGGER_PAUSE_AND_DUMP_COUNT_N(NEXT_UNKNOWN_OP, {TRACE0("Paused at unimplemented ucode\n");})
974 #endif
975 }
976
977 void RDP_NOIMPL_WARN(const char* op)
978 {
979 #ifdef DEBUGGER
980     if(logWarning)
981     {
982         TRACE0(op);
983     }
984 #endif
985 }
986
987
988 void RSP_GBI1_Noop(Gfx *gfx)
989 {
990 }
991
992
993 void RDP_GFX_PopDL()
994 {
995     LOG_UCODE("Returning from DisplayList: level=%d", gDlistStackPointer+1);
996     LOG_UCODE("############################################");
997     LOG_UCODE("/\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\");
998     LOG_UCODE("");
999
1000     gDlistStackPointer--;
1001 }
1002
1003 uint32 CalcalateCRC(uint32* srcPtr, uint32 srcSize)
1004 {
1005     uint32 crc=0;
1006     for( uint32 i=0; i<srcSize; i++ )
1007     {
1008         crc += srcPtr[i];
1009     }
1010     return crc;
1011 }
1012
1013
1014 void RSP_GFX_InitGeometryMode()
1015 {
1016     bool bCullFront     = (gRDP.geometryMode & G_CULL_FRONT) ? true : false;
1017     bool bCullBack      = (gRDP.geometryMode & G_CULL_BACK) ? true : false;
1018     if( bCullFront && bCullBack ) // should never cull front
1019     {
1020         bCullFront = false;
1021     }
1022     CRender::g_pRender->SetCullMode(bCullFront, bCullBack);
1023     
1024     BOOL bShade         = (gRDP.geometryMode & G_SHADE) ? TRUE : FALSE;
1025     BOOL bShadeSmooth   = (gRDP.geometryMode & G_SHADING_SMOOTH) ? TRUE : FALSE;
1026     if (bShade && bShadeSmooth)     CRender::g_pRender->SetShadeMode( SHADE_SMOOTH );
1027     else                            CRender::g_pRender->SetShadeMode( SHADE_FLAT );
1028     
1029     CRender::g_pRender->SetFogEnable( gRDP.geometryMode & G_FOG ? true : false );
1030     SetTextureGen((gRDP.geometryMode & G_TEXTURE_GEN) ? true : false );
1031     SetLighting( (gRDP.geometryMode & G_LIGHTING ) ? true : false );
1032     CRender::g_pRender->ZBufferEnable( gRDP.geometryMode & G_ZBUFFER );
1033 }
1034
1035 //////////////////////////////////////////////////////////
1036 //////////////////////////////////////////////////////////
1037 //                   DP Ucodes                          //
1038 //////////////////////////////////////////////////////////
1039 //////////////////////////////////////////////////////////
1040
1041 void DLParser_SetKeyGB(Gfx *gfx)
1042 {
1043     DP_Timing(DLParser_SetKeyGB);
1044
1045     gRDP.keyB = ((gfx->words.w1)>>8)&0xFF;
1046     gRDP.keyG = ((gfx->words.w1)>>24)&0xFF;
1047     gRDP.keyA = (gRDP.keyR+gRDP.keyG+gRDP.keyB)/3;
1048     gRDP.fKeyA = gRDP.keyA/255.0f;
1049 }
1050 void DLParser_SetKeyR(Gfx *gfx)
1051 {
1052     DP_Timing(DLParser_SetKeyR);
1053
1054     gRDP.keyR = ((gfx->words.w1)>>8)&0xFF;
1055     gRDP.keyA = (gRDP.keyR+gRDP.keyG+gRDP.keyB)/3;
1056     gRDP.fKeyA = gRDP.keyA/255.0f;
1057 }
1058
1059 int g_convk0,g_convk1,g_convk2,g_convk3,g_convk4,g_convk5;
1060 float g_convc0,g_convc1,g_convc2,g_convc3,g_convc4,g_convc5;
1061 void DLParser_SetConvert(Gfx *gfx)
1062 {
1063     DP_Timing(DLParser_SetConvert);
1064
1065     int temp;
1066
1067     temp = ((gfx->words.w0)>>13)&0x1FF;
1068     g_convk0 = temp>0xFF ? -(temp-0x100) : temp;
1069
1070     temp = ((gfx->words.w0)>>4)&0x1FF;
1071     g_convk1 = temp>0xFF ? -(temp-0x100) : temp;
1072
1073     temp = (gfx->words.w0)&0xF;
1074     temp = (temp<<5)|(((gfx->words.w1)>>27)&0x1F);
1075     g_convk2 = temp>0xFF ? -(temp-0x100) : temp;
1076
1077     temp = ((gfx->words.w1)>>18)&0x1FF;
1078     g_convk3 = temp>0xFF ? -(temp-0x100) : temp;
1079
1080     temp = ((gfx->words.w1)>>9)&0x1FF;
1081     g_convk4 = temp>0xFF ? -(temp-0x100) : temp;
1082
1083     temp = (gfx->words.w1)&0x1FF;
1084     g_convk5 = temp>0xFF ? -(temp-0x100) : temp;
1085
1086     g_convc0 = g_convk5/255.0f+1.0f;
1087     g_convc1 = g_convk0/255.0f*g_convc0;
1088     g_convc2 = g_convk1/255.0f*g_convc0;
1089     g_convc3 = g_convk2/255.0f*g_convc0;
1090     g_convc4 = g_convk3/255.0f*g_convc0;
1091 }
1092 void DLParser_SetPrimDepth(Gfx *gfx)
1093 {
1094     DP_Timing(DLParser_SetPrimDepth);
1095     uint32 dwZ  = ((gfx->words.w1) >> 16) & 0xFFFF;
1096     uint32 dwDZ = ((gfx->words.w1)      ) & 0xFFFF;
1097
1098     LOG_UCODE("SetPrimDepth: 0x%08x 0x%08x - z: 0x%04x dz: 0x%04x",
1099         gfx->words.w0, gfx->words.w1, dwZ, dwDZ);
1100     
1101     SetPrimitiveDepth(dwZ, dwDZ);
1102     DEBUGGER_PAUSE(NEXT_SET_PRIM_COLOR);
1103 }
1104
1105 void DLParser_RDPSetOtherMode(Gfx *gfx)
1106 {
1107     DP_Timing(DLParser_RDPSetOtherMode);
1108     gRDP.otherMode._u32[1] = (gfx->words.w0);   // High
1109     gRDP.otherMode._u32[0] = (gfx->words.w1);   // Low
1110
1111     if( gRDP.otherModeH != ((gfx->words.w0) & 0x0FFFFFFF) )
1112     {
1113         gRDP.otherModeH = ((gfx->words.w0) & 0x0FFFFFFF);
1114
1115         uint32 dwTextFilt  = (gRDP.otherModeH>>RSP_SETOTHERMODE_SHIFT_TEXTFILT)&0x3;
1116         CRender::g_pRender->SetTextureFilter(dwTextFilt<<RSP_SETOTHERMODE_SHIFT_TEXTFILT);
1117     }
1118
1119     if( gRDP.otherModeL != (gfx->words.w1) )
1120     {
1121         if( (gRDP.otherModeL&ZMODE_DEC) != ((gfx->words.w1)&ZMODE_DEC) )
1122         {
1123             if( ((gfx->words.w1)&ZMODE_DEC) == ZMODE_DEC )
1124                 CRender::g_pRender->SetZBias( 2 );
1125             else
1126                 CRender::g_pRender->SetZBias( 0 );
1127         }
1128
1129         gRDP.otherModeL = (gfx->words.w1);
1130
1131         BOOL bZCompare      = (gRDP.otherModeL & Z_COMPARE)         ? TRUE : FALSE;
1132         BOOL bZUpdate       = (gRDP.otherModeL & Z_UPDATE)          ? TRUE : FALSE;
1133
1134         CRender::g_pRender->SetZCompare( bZCompare );
1135         CRender::g_pRender->SetZUpdate( bZUpdate );
1136
1137         uint32 dwAlphaTestMode = (gRDP.otherModeL >> RSP_SETOTHERMODE_SHIFT_ALPHACOMPARE) & 0x3;
1138
1139         if ((dwAlphaTestMode) != 0)
1140             CRender::g_pRender->SetAlphaTestEnable( TRUE );
1141         else
1142             CRender::g_pRender->SetAlphaTestEnable( FALSE );
1143     }
1144
1145     uint16 blender = gRDP.otherMode.blender;
1146     RDP_BlenderSetting &bl = *(RDP_BlenderSetting*)(&(blender));
1147     if( bl.c1_m1a==3 || bl.c1_m2a == 3 || bl.c2_m1a == 3 || bl.c2_m2a == 3 )
1148     {
1149         gRDP.bFogEnableInBlender = true;
1150     }
1151     else
1152     {
1153         gRDP.bFogEnableInBlender = false;
1154     }
1155 }
1156
1157
1158
1159 void DLParser_RDPLoadSync(Gfx *gfx) 
1160
1161     DP_Timing(DLParser_RDPLoadSync);
1162     LOG_UCODE("LoadSync: (Ignored)"); 
1163 }
1164
1165 void DLParser_RDPPipeSync(Gfx *gfx) 
1166
1167     DP_Timing(DLParser_RDPPipeSync);
1168     LOG_UCODE("PipeSync: (Ignored)"); 
1169 }
1170 void DLParser_RDPTileSync(Gfx *gfx) 
1171
1172     DP_Timing(DLParser_RDPTileSync);
1173     LOG_UCODE("TileSync: (Ignored)"); 
1174 }
1175
1176 void DLParser_RDPFullSync(Gfx *gfx)
1177
1178     DP_Timing(DLParser_RDPFullSync);
1179     TriggerDPInterrupt();
1180 }
1181
1182 void DLParser_SetScissor(Gfx *gfx)
1183 {
1184     DP_Timing(DLParser_SetScissor);
1185
1186     ScissorType tempScissor;
1187     // The coords are all in 8:2 fixed point
1188     tempScissor.x0   = ((gfx->words.w0)>>12)&0xFFF;
1189     tempScissor.y0   = ((gfx->words.w0)>>0 )&0xFFF;
1190     tempScissor.mode = ((gfx->words.w1)>>24)&0x03;
1191     tempScissor.x1   = ((gfx->words.w1)>>12)&0xFFF;
1192     tempScissor.y1   = ((gfx->words.w1)>>0 )&0xFFF;
1193
1194     tempScissor.left    = tempScissor.x0/4;
1195     tempScissor.top     = tempScissor.y0/4;
1196     tempScissor.right   = tempScissor.x1/4;
1197     tempScissor.bottom  = tempScissor.y1/4;
1198
1199     if( options.bEnableHacks )
1200     {
1201         if( g_CI.dwWidth == 0x200 && tempScissor.right == 0x200 )
1202         {
1203             uint32 width = *g_GraphicsInfo.VI_WIDTH_REG & 0xFFF;
1204
1205             if( width != 0x200 )
1206             {
1207                 // Hack for RE2
1208                 tempScissor.bottom = tempScissor.right*tempScissor.bottom/width;
1209                 tempScissor.right = width;
1210             }
1211
1212         }
1213     }
1214
1215     if( gRDP.scissor.left != tempScissor.left || gRDP.scissor.top != tempScissor.top ||
1216         gRDP.scissor.right != tempScissor.right || gRDP.scissor.bottom != tempScissor.bottom ||
1217         gRSP.real_clip_scissor_left != tempScissor.left || gRSP.real_clip_scissor_top != tempScissor.top ||
1218         gRSP.real_clip_scissor_right != tempScissor.right || gRSP.real_clip_scissor_bottom != tempScissor.bottom)
1219     {
1220         memcpy(&(gRDP.scissor), &tempScissor, sizeof(ScissorType) );
1221         if( !status.bHandleN64RenderTexture )
1222             SetVIScales();
1223
1224         if(  options.enableHackForGames == HACK_FOR_SUPER_BOWLING && g_CI.dwAddr%0x100 != 0 )
1225         {
1226             // right half screen
1227             gRDP.scissor.left += 160;
1228             gRDP.scissor.right += 160;
1229             CRender::g_pRender->SetViewport(160, 0, 320, 240, 0xFFFF);
1230         }
1231
1232         CRender::g_pRender->UpdateClipRectangle();
1233         CRender::g_pRender->UpdateScissor();
1234         CRender::g_pRender->SetViewportRender();
1235     }
1236
1237     LOG_UCODE("SetScissor: x0=%d y0=%d x1=%d y1=%d mode=%d",
1238         gRDP.scissor.left, gRDP.scissor.top,
1239         gRDP.scissor.right, gRDP.scissor.bottom,
1240         gRDP.scissor.mode);
1241
1242     ///TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("SetScissor: x0=%d y0=%d x1=%d y1=%d mode=%d", gRDP.scissor.left, gRDP.scissor.top,
1243     //gRDP.scissor.right, gRDP.scissor.bottom, gRDP.scissor.mode););
1244 }
1245
1246
1247 void DLParser_FillRect(Gfx *gfx)
1248
1249     DP_Timing(DLParser_FillRect);   // fix me
1250     status.primitiveType = PRIM_FILLRECT;
1251
1252     if( status.bN64IsDrawingTextureBuffer && frameBufferOptions.bIgnore )
1253     {
1254         return;
1255     }
1256
1257     if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
1258     {
1259         uint32 dwPC = gDlistStack[gDlistStackPointer].pc;       // This points to the next instruction
1260         uint32 w2 = *(uint32 *)(g_pRDRAMu8 + dwPC);
1261         if( (w2>>24) == RDP_FILLRECT )
1262         {
1263             // Mario Tennis, a lot of FillRect ucodes, skip all of them
1264             while( (w2>>24) == RDP_FILLRECT )
1265             {
1266                 dwPC += 8;
1267                 w2 = *(uint32 *)(g_pRDRAMu8 + dwPC);
1268             }
1269
1270             gDlistStack[gDlistStackPointer].pc = dwPC;
1271             return;
1272         }
1273     }
1274
1275     uint32 x0   = (((gfx->words.w1)>>12)&0xFFF)/4;
1276     uint32 y0   = (((gfx->words.w1)>>0 )&0xFFF)/4;
1277     uint32 x1   = (((gfx->words.w0)>>12)&0xFFF)/4;
1278     uint32 y1   = (((gfx->words.w0)>>0 )&0xFFF)/4;
1279
1280     // Note, in some modes, the right/bottom lines aren't drawn
1281
1282     LOG_UCODE("    (%d,%d) (%d,%d)", x0, y0, x1, y1);
1283
1284     if( gRDP.otherMode.cycle_type >= CYCLE_TYPE_COPY )
1285     {
1286         x1++;
1287         y1++;
1288     }
1289
1290     //TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("FillRect: X0=%d, Y0=%d, X1=%d, Y1=%d, Color=0x%08X", x0, y0, x1, y1, gRDP.originalFillColor););
1291
1292     if( status.bHandleN64RenderTexture && options.enableHackForGames == HACK_FOR_BANJO_TOOIE )
1293     {
1294         // Skip this
1295         return;
1296     }
1297
1298     if (IsUsedAsDI(g_CI.dwAddr))
1299     {
1300         // Clear the Z Buffer
1301         if( x0!=0 || y0!=0 || windowSetting.uViWidth-x1>1 || windowSetting.uViHeight-y1>1)
1302         {
1303             if( options.enableHackForGames == HACK_FOR_GOLDEN_EYE )
1304             {
1305                 // GoldenEye is using double zbuffer
1306                 if( g_CI.dwAddr == g_ZI.dwAddr )
1307                 {
1308                     // The zbuffer is the upper screen
1309                     COORDRECT rect={int(x0*windowSetting.fMultX),int(y0*windowSetting.fMultY),int(x1*windowSetting.fMultX),int(y1*windowSetting.fMultY)};
1310                     CRender::g_pRender->ClearBuffer(false,true,rect);   //Check me
1311                     LOG_UCODE("    Clearing ZBuffer");
1312                 }
1313                 else
1314                 {
1315                     // The zbuffer is the lower screen
1316                     int h = (g_CI.dwAddr-g_ZI.dwAddr)/g_CI.dwWidth/2;
1317                     COORDRECT rect={int(x0*windowSetting.fMultX),int((y0+h)*windowSetting.fMultY),int(x1*windowSetting.fMultX),int((y1+h)*windowSetting.fMultY)};
1318                     CRender::g_pRender->ClearBuffer(false,true,rect);   //Check me
1319                     LOG_UCODE("    Clearing ZBuffer");
1320                 }
1321             }
1322             else
1323             {
1324                 COORDRECT rect={int(x0*windowSetting.fMultX),int(y0*windowSetting.fMultY),int(x1*windowSetting.fMultX),int(y1*windowSetting.fMultY)};
1325                 CRender::g_pRender->ClearBuffer(false,true,rect);   //Check me
1326                 LOG_UCODE("    Clearing ZBuffer");
1327             }
1328         }
1329         else
1330         {
1331             CRender::g_pRender->ClearBuffer(false,true);    //Check me
1332             LOG_UCODE("    Clearing ZBuffer");
1333         }
1334
1335         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect: ClearZbuffer\n");});
1336         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FILLRECT, {DebuggerAppendMsg("ClearZbuffer: X0=%d, Y0=%d, X1=%d, Y1=%d, Color=0x%08X", x0, y0, x1, y1, gRDP.originalFillColor);
1337         DebuggerAppendMsg("Pause after ClearZbuffer: Color=%08X\n", gRDP.originalFillColor);});
1338
1339         if( g_curRomInfo.bEmulateClear )
1340         {
1341             // Emulating Clear, by write the memory in RDRAM
1342             uint16 color = (uint16)gRDP.originalFillColor;
1343             uint32 pitch = g_CI.dwWidth<<1;
1344             long long base = (long long) (g_pRDRAMu8 + g_CI.dwAddr);
1345             for( uint32 i =y0; i<y1; i++ )
1346             {
1347                 for( uint32 j=x0; j<x1; j++ )
1348                 {
1349                     *(uint16*)((base+pitch*i+j)^2) = color;
1350                 }
1351             }
1352         }
1353     }
1354     else if( status.bHandleN64RenderTexture )
1355     {
1356         if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
1357
1358         status.leftRendered = status.leftRendered<0 ? x0 : min((int)x0,status.leftRendered);
1359         status.topRendered = status.topRendered<0 ? y0 : min((int)y0,status.topRendered);
1360         status.rightRendered = status.rightRendered<0 ? x1 : max((int)x1,status.rightRendered);
1361         status.bottomRendered = status.bottomRendered<0 ? y1 : max((int)y1,status.bottomRendered);
1362
1363         g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,(int)y1);
1364
1365         if( status.bDirectWriteIntoRDRAM || ( x0==0 && y0==0 && (x1 == g_pRenderTextureInfo->N64Width || x1 == g_pRenderTextureInfo->N64Width-1 ) ) )
1366         {
1367             if( g_pRenderTextureInfo->CI_Info.dwSize == TXT_SIZE_16b )
1368             {
1369                 uint16 color = (uint16)gRDP.originalFillColor;
1370                 uint32 pitch = g_pRenderTextureInfo->N64Width<<1;
1371                 long long base = (long long) (g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr);
1372                 for( uint32 i =y0; i<y1; i++ )
1373                 {
1374                     for( uint32 j=x0; j<x1; j++ )
1375                     {
1376                         *(uint16*)((base+pitch*i+j)^2) = color;
1377                     }
1378                 }
1379             }
1380             else
1381             {
1382                 uint8 color = (uint8)gRDP.originalFillColor;
1383                 uint32 pitch = g_pRenderTextureInfo->N64Width;
1384                 long long base = (long long) (g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr);
1385                 for( uint32 i=y0; i<y1; i++ )
1386                 {
1387                     for( uint32 j=x0; j<x1; j++ )
1388                     {
1389                         *(uint8*)((base+pitch*i+j)^3) = color;
1390                     }
1391                 }
1392             }
1393
1394             status.bFrameBufferDrawnByTriangles = false;
1395         }
1396         else
1397         {
1398             status.bFrameBufferDrawnByTriangles = true;
1399         }
1400         status.bFrameBufferDrawnByTriangles = true;
1401
1402         if( !status.bDirectWriteIntoRDRAM )
1403         {
1404             status.bFrameBufferIsDrawn = true;
1405
1406             //if( x0==0 && y0==0 && (x1 == g_pRenderTextureInfo->N64Width || x1 == g_pRenderTextureInfo->N64Width-1 ) && gRDP.fillColor == 0)
1407             //{
1408             //  CRender::g_pRender->ClearBuffer(true,false);
1409             //}
1410             //else
1411             {
1412                 if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL )
1413                 {
1414                     CRender::g_pRender->FillRect(x0, y0, x1, y1, gRDP.fillColor);
1415                 }
1416                 else
1417                 {
1418                     COLOR primColor = GetPrimitiveColor();
1419                     CRender::g_pRender->FillRect(x0, y0, x1, y1, primColor);
1420                 }
1421             }
1422         }
1423
1424         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect\n");});
1425         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FILLRECT, {DebuggerAppendMsg("FillRect: X0=%d, Y0=%d, X1=%d, Y1=%d, Color=0x%08X", x0, y0, x1, y1, gRDP.originalFillColor);
1426         DebuggerAppendMsg("Pause after FillRect: Color=%08X\n", gRDP.originalFillColor);});
1427     }
1428     else
1429     {
1430         LOG_UCODE("    Filling Rectangle");
1431         if( frameBufferOptions.bSupportRenderTextures || frameBufferOptions.bCheckBackBufs )
1432         {
1433             if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
1434
1435             status.leftRendered = status.leftRendered<0 ? x0 : min((int)x0,status.leftRendered);
1436             status.topRendered = status.topRendered<0 ? y0 : min((int)y0,status.topRendered);
1437             status.rightRendered = status.rightRendered<0 ? x1 : max((int)x1,status.rightRendered);
1438             status.bottomRendered = status.bottomRendered<0 ? y1 : max((int)y1,status.bottomRendered);
1439         }
1440
1441         if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL )
1442         {
1443             if( !status.bHandleN64RenderTexture || g_pRenderTextureInfo->CI_Info.dwSize == TXT_SIZE_16b )
1444             {
1445                 CRender::g_pRender->FillRect(x0, y0, x1, y1, gRDP.fillColor);
1446             }
1447         }
1448         else
1449         {
1450             COLOR primColor = GetPrimitiveColor();
1451             //if( RGBA_GETALPHA(primColor) != 0 )
1452             {
1453                 CRender::g_pRender->FillRect(x0, y0, x1, y1, primColor);
1454             }
1455         }
1456         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect\n");});
1457         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FILLRECT, {DebuggerAppendMsg("FillRect: X0=%d, Y0=%d, X1=%d, Y1=%d, Color=0x%08X", x0, y0, x1, y1, gRDP.originalFillColor);
1458         DebuggerAppendMsg("Pause after FillRect: Color=%08X\n", gRDP.originalFillColor);});
1459     }
1460 }
1461
1462
1463 #define STORE_CI    {g_CI.dwAddr = dwNewAddr;g_CI.dwFormat = dwFmt;g_CI.dwSize = dwSiz;g_CI.dwWidth = dwWidth;g_CI.bpl=dwBpl;}
1464
1465 void DLParser_SetCImg(Gfx *gfx)
1466 {
1467     uint32 dwFmt        = gfx->setimg.fmt;
1468     uint32 dwSiz        = gfx->setimg.siz;
1469     uint32 dwWidth      = gfx->setimg.width + 1;
1470     uint32 dwNewAddr    = RSPSegmentAddr((gfx->setimg.addr)) & 0x00FFFFFF ;
1471     uint32 dwBpl        = dwWidth << dwSiz >> 1;
1472
1473     TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", dwNewAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth););
1474
1475     if( dwFmt == TXT_FMT_YUV || dwFmt == TXT_FMT_IA )
1476     {
1477         WARNING(TRACE4("Check me:  SetCImg Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1478             g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth));
1479     }
1480
1481     LOG_UCODE("    Image: 0x%08x", RSPSegmentAddr(gfx->words.w1));
1482     LOG_UCODE("    Fmt: %s Size: %s Width: %d",
1483         pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1484
1485     if( g_CI.dwAddr == dwNewAddr && g_CI.dwFormat == dwFmt && g_CI.dwSize == dwSiz && g_CI.dwWidth == dwWidth )
1486     {
1487         TXTRBUF_OR_CI_DETAIL_DUMP({
1488             TRACE0("Set CIMG to the same address, no change, skipped");
1489             DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1490                 g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1491         });
1492         return;
1493     }
1494
1495     if( status.bVIOriginIsUpdated == true && currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_1ST_CI_CHANGE )
1496     {
1497         status.bVIOriginIsUpdated=false;
1498         CGraphicsContext::Get()->UpdateFrame();
1499         TXTRBUF_OR_CI_DETAIL_DUMP(TRACE0("Screen Update at 1st CI change"););
1500     }
1501
1502     if( options.enableHackForGames == HACK_FOR_SUPER_BOWLING )
1503     {
1504         if( dwNewAddr%0x100 == 0 )
1505         {
1506             if( dwWidth < 320 )
1507             {
1508                 // Left half screen
1509                 gRDP.scissor.left = 0;
1510                 gRDP.scissor.right = 160;
1511                 CRender::g_pRender->SetViewport(0, 0, 160, 240, 0xFFFF);
1512                 CRender::g_pRender->UpdateClipRectangle();
1513                 CRender::g_pRender->UpdateScissor();
1514             }
1515             else
1516             {
1517                 gRDP.scissor.left = 0;
1518                 gRDP.scissor.right = 320;
1519                 CRender::g_pRender->SetViewport(0, 0, 320, 240, 0xFFFF);
1520                 CRender::g_pRender->UpdateClipRectangle();
1521                 CRender::g_pRender->UpdateScissor();
1522             }
1523         }
1524         else
1525         {
1526             // right half screen
1527             gRDP.scissor.left = 160;
1528             gRDP.scissor.right = 320;
1529             gRSP.nVPLeftN = 160;
1530             gRSP.nVPRightN = 320;
1531             CRender::g_pRender->UpdateClipRectangle();
1532             CRender::g_pRender->UpdateScissor();
1533             CRender::g_pRender->SetViewport(160, 0, 320, 240, 0xFFFF);
1534         }
1535     }
1536
1537
1538     if( !frameBufferOptions.bUpdateCIInfo )
1539     {
1540         STORE_CI;
1541         status.bCIBufferIsRendered = false;
1542         status.bN64IsDrawingTextureBuffer = false;
1543
1544         TXTRBUF_DUMP(TRACE4("SetCImg : Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1545             g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth));
1546
1547         DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG, 
1548         {
1549             DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1550                 dwNewAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1551         }
1552         );
1553         return;
1554     }
1555
1556     SetImgInfo newCI;
1557     newCI.bpl = dwBpl;
1558     newCI.dwAddr = dwNewAddr;
1559     newCI.dwFormat = dwFmt;
1560     newCI.dwSize = dwSiz;
1561     newCI.dwWidth = dwWidth;
1562
1563     g_pFrameBufferManager->Set_CI_addr(newCI);
1564 }
1565
1566 void DLParser_SetZImg(Gfx *gfx)
1567 {
1568     DP_Timing(DLParser_SetZImg);
1569     LOG_UCODE("    Image: 0x%08x", RSPSegmentAddr(gfx->words.w1));
1570
1571     uint32 dwFmt   = gfx->setimg.fmt;
1572     uint32 dwSiz   = gfx->setimg.siz;
1573     uint32 dwWidth = gfx->setimg.width + 1;
1574     uint32 dwAddr = RSPSegmentAddr((gfx->setimg.addr));
1575
1576     if( dwAddr != g_ZI_saves[0].CI_Info.dwAddr )
1577     {
1578         g_ZI_saves[1].CI_Info.dwAddr    = g_ZI.dwAddr;
1579         g_ZI_saves[1].CI_Info.dwFormat  = g_ZI.dwFormat;
1580         g_ZI_saves[1].CI_Info.dwSize    = g_ZI.dwSize;
1581         g_ZI_saves[1].CI_Info.dwWidth   = g_ZI.dwWidth;
1582         g_ZI_saves[1].updateAtFrame = g_ZI_saves[0].updateAtFrame;
1583
1584         g_ZI_saves[0].CI_Info.dwAddr    = g_ZI.dwAddr   = dwAddr;
1585         g_ZI_saves[0].CI_Info.dwFormat  = g_ZI.dwFormat = dwFmt;
1586         g_ZI_saves[0].CI_Info.dwSize    = g_ZI.dwSize   = dwSiz;
1587         g_ZI_saves[0].CI_Info.dwWidth   = g_ZI.dwWidth  = dwWidth;
1588         g_ZI_saves[0].updateAtFrame     = status.gDlistCount;
1589     }
1590     else
1591     {
1592         g_ZI.dwAddr = dwAddr;
1593         g_ZI.dwFormat = dwFmt;
1594         g_ZI.dwSize = dwSiz;
1595         g_ZI.dwWidth    = dwWidth;
1596     }
1597
1598     DEBUGGER_IF_DUMP((pauseAtNext) ,
1599     {DebuggerAppendMsg("SetZImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1600     g_ZI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);}
1601     );
1602
1603     DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG, 
1604         {
1605             DebuggerAppendMsg("Pause after SetZImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1606                 g_ZI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1607         }
1608     );
1609 }
1610
1611 bool IsUsedAsDI(uint32 addr)
1612 {
1613     if( addr == g_ZI_saves[0].CI_Info.dwAddr )
1614         return true;
1615     else if( addr == g_ZI_saves[1].CI_Info.dwAddr && status.gDlistCount - g_ZI_saves[1].updateAtFrame < 10 
1616         && g_ZI_saves[1].CI_Info.dwAddr != 0 )
1617         return true;
1618     else
1619         return false;
1620 }
1621
1622 void DLParser_SetCombine(Gfx *gfx)
1623 {
1624     DP_Timing(DLParser_SetCombine);
1625     uint32 dwMux0 = (gfx->words.w0)&0x00FFFFFF;
1626     uint32 dwMux1 = (gfx->words.w1);
1627     CRender::g_pRender->SetMux(dwMux0, dwMux1);
1628 }
1629
1630 void DLParser_SetFillColor(Gfx *gfx)
1631 {
1632     DP_Timing(DLParser_SetFillColor);
1633     gRDP.fillColor = Convert555ToRGBA(gfx->setcolor.fillcolor);
1634     gRDP.originalFillColor = (gfx->setcolor.color);
1635
1636     LOG_UCODE("    Color5551=0x%04x = 0x%08x", (uint16)gfx->words.w1, gRDP.fillColor);
1637
1638 }
1639
1640 void DLParser_SetFogColor(Gfx *gfx)
1641 {
1642     DP_Timing(DLParser_SetFogColor);
1643     CRender::g_pRender->SetFogColor( gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a );
1644     FOG_DUMP(TRACE1("Set Fog color: %08X", gfx->setcolor.color));
1645 }
1646
1647 void DLParser_SetBlendColor(Gfx *gfx)
1648 {
1649     DP_Timing(DLParser_SetBlendColor);
1650     CRender::g_pRender->SetAlphaRef(gfx->setcolor.a);
1651 }
1652
1653
1654 void DLParser_SetPrimColor(Gfx *gfx)
1655 {
1656     DP_Timing(DLParser_SetPrimColor);
1657     SetPrimitiveColor( COLOR_RGBA(gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a), 
1658         gfx->setcolor.prim_min_level, gfx->setcolor.prim_level);
1659 }
1660
1661 void DLParser_SetEnvColor(Gfx *gfx)
1662 {
1663     DP_Timing(DLParser_SetEnvColor);
1664     SetEnvColor( COLOR_RGBA(gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a) );
1665 }
1666
1667
1668 void RDP_DLParser_Process(void)
1669 {
1670     status.gRDPTime = (uint32) SDL_GetTicks();
1671
1672     status.gDlistCount++;
1673
1674     uint32 start = *(g_GraphicsInfo.DPC_START_REG);
1675     uint32 end = *(g_GraphicsInfo.DPC_END_REG);
1676
1677     gDlistStackPointer=0;
1678     gDlistStack[gDlistStackPointer].pc = start;
1679     gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
1680
1681     // Check if we need to purge (every 5 milliseconds)
1682     if (status.gRDPTime - status.lastPurgeTimeTime > 5)
1683     {
1684         gTextureManager.PurgeOldTextures();
1685         status.lastPurgeTimeTime = status.gRDPTime;
1686     }
1687     
1688     // Lock the graphics context here.
1689     CRender::g_pRender->SetFillMode(RICE_FILLMODE_SOLID);
1690
1691     SetVIScales();
1692
1693     CRender::g_pRender->RenderReset();
1694     CRender::g_pRender->BeginRendering();
1695     CRender::g_pRender->SetViewport(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, 0x3FF);
1696
1697     while( gDlistStack[gDlistStackPointer].pc < end )
1698     {
1699         Gfx *pgfx = (Gfx*)&g_pRDRAMu32[(gDlistStack[gDlistStackPointer].pc>>2)];
1700         gDlistStack[gDlistStackPointer].pc += 8;
1701         currentUcodeMap[pgfx->words.w0 >>24](pgfx);
1702     }
1703
1704     CRender::g_pRender->EndRendering();
1705 }
1706
1707 void RDP_TriFill(Gfx *gfx)
1708 {
1709 }
1710
1711 void RDP_TriFillZ(Gfx *gfx)
1712 {
1713 }
1714
1715 void RDP_TriTxtr(Gfx *gfx)
1716 {
1717 }
1718
1719 void RDP_TriTxtrZ(Gfx *gfx)
1720 {
1721 }
1722
1723 void RDP_TriShade(Gfx *gfx)
1724 {
1725 }
1726
1727 void RDP_TriShadeZ(Gfx *gfx)
1728 {
1729 }
1730
1731 void RDP_TriShadeTxtr(Gfx *gfx)
1732 {
1733 }
1734
1735 void RDP_TriShadeTxtrZ(Gfx *gfx)
1736 {
1737 }
1738
1739 static int crc_table_empty = 1;
1740 static unsigned int crc_table[256];
1741 static void make_crc_table(void);
1742
1743 static void make_crc_table()
1744 {
1745   unsigned int c;
1746   int n, k;
1747   unsigned int poly;            /* polynomial exclusive-or pattern */
1748   /* terms of polynomial defining this crc (except x^32): */
1749   static const uint8 p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
1750
1751   /* make exclusive-or pattern from polynomial (0xedb88320L) */
1752   poly = 0L;
1753   for (n = 0; (unsigned int)n < sizeof(p)/sizeof(uint8); n++)
1754     poly |= 1L << (31 - p[n]);
1755  
1756   for (n = 0; n < 256; n++)
1757   {
1758     c = (unsigned int)n;
1759     for (k = 0; k < 8; k++)
1760       c = (c & 1) ? (poly ^ (c >> 1)) : c >> 1;
1761     crc_table[n] = c;
1762   }
1763   crc_table_empty = 0;
1764 }
1765
1766 /* ========================================================================= */
1767 #define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
1768 #define DO2(buf)  DO1(buf); DO1(buf);
1769 #define DO4(buf)  DO2(buf); DO2(buf);
1770 #define DO8(buf)  DO4(buf); DO4(buf);
1771
1772 /* ========================================================================= */
1773 unsigned int ComputeCRC32(unsigned int crc, const uint8 *buf, unsigned int len)
1774 {
1775     if (buf == NULL)
1776         return 0L;
1777
1778     if (crc_table_empty)
1779       make_crc_table();
1780
1781     crc = crc ^ 0xffffffffL;
1782     while (len >= 8)
1783     {
1784       DO8(buf);
1785       len -= 8;
1786     }
1787     if (len) do {
1788       DO1(buf);
1789     } while (--len);
1790     return crc ^ 0xffffffffL;
1791 }
1792
1793 Matrix matToLoad;
1794 void LoadMatrix(uint32 addr)
1795 {
1796     const float fRecip = 1.0f / 65536.0f;
1797     if (addr + 64 > g_dwRamSize)
1798     {
1799         TRACE1("Mtx: Address invalid (0x%08x)", addr);
1800         return;
1801     }
1802
1803     for (int i = 0; i < 4; i++)
1804     {
1805         for (int j = 0; j < 4; j++) 
1806         {
1807             int hi = *(short *)(g_pRDRAMu8 + ((addr+(i<<3)+(j<<1)     )^0x2));
1808             int lo = *(unsigned short *)(g_pRDRAMu8 + ((addr+(i<<3)+(j<<1) + 32)^0x2));
1809             matToLoad.m[i][j] = (float)((hi<<16) | lo) * fRecip;
1810         }
1811     }
1812
1813
1814 #ifdef DEBUGGER
1815     LOG_UCODE(
1816         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n"
1817         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n"
1818         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n"
1819         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n",
1820         matToLoad.m[0][0], matToLoad.m[0][1], matToLoad.m[0][2], matToLoad.m[0][3],
1821         matToLoad.m[1][0], matToLoad.m[1][1], matToLoad.m[1][2], matToLoad.m[1][3],
1822         matToLoad.m[2][0], matToLoad.m[2][1], matToLoad.m[2][2], matToLoad.m[2][3],
1823         matToLoad.m[3][0], matToLoad.m[3][1], matToLoad.m[3][2], matToLoad.m[3][3]);
1824 #endif // DEBUGGER
1825 }
1826