d3a69d308c73b3ec6db9ee1bb8c76a9816e27f86
[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 void DLParser_Process(OSTask * pTask)
784 {
785     static int skipframe=0;
786     //BOOL menuWaiting = FALSE;
787
788     dlistMtxCount = 0;
789     bHalfTxtScale = false;
790
791     if ( CRender::g_pRender == NULL)
792     {
793         TriggerDPInterrupt();
794         TriggerSPInterrupt();
795         return;
796     }
797
798     status.bScreenIsDrawn = true;
799     if( options.bSkipFrame )
800     {
801         skipframe++;
802         if(skipframe%2)
803         {
804             TriggerDPInterrupt();
805             TriggerSPInterrupt();
806             return;
807         }
808     }
809
810     if( currentRomOptions.N64RenderToTextureEmuType != TXT_BUF_NONE && defaultRomOptions.bSaveVRAM )
811     {
812         g_pFrameBufferManager->CheckRenderTextureCRCInRDRAM();
813     }
814
815     g_pOSTask = pTask;
816     
817     DebuggerPauseCountN( NEXT_DLIST );
818     status.gRDPTime = (uint32) SDL_GetTicks();
819
820     status.gDlistCount++;
821
822     if ( lastUcodeInfo.ucStart != (uint32)(pTask->t.ucode) )
823     {
824         uint32 ucode = DLParser_CheckUcode(pTask->t.ucode, pTask->t.ucode_data, pTask->t.ucode_size, pTask->t.ucode_data_size);
825         RSP_SetUcode(ucode, pTask->t.ucode, pTask->t.ucode_data, pTask->t.ucode_size);
826         DEBUGGER_PAUSE_AND_DUMP(NEXT_SWITCH_UCODE,{DebuggerAppendMsg("Pause at switching ucode");});
827     }
828
829     // Initialize stack
830     status.bN64FrameBufferIsUsed = false;
831     gDlistStackPointer=0;
832     gDlistStack[gDlistStackPointer].pc = (uint32)pTask->t.data_ptr;
833     gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
834     DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((gDlistStack[gDlistStackPointer].pc == 0 && pauseAtNext && eventToPause==NEXT_UNKNOWN_OP),
835             {DebuggerAppendMsg("Start Task without DLIST: ucode=%08X, data=%08X", (uint32)pTask->t.ucode, (uint32)pTask->t.ucode_data);});
836
837
838     // Check if we need to purge (every 5 milliseconds)
839     if (status.gRDPTime - status.lastPurgeTimeTime > 5)
840     {
841         gTextureManager.PurgeOldTextures();
842         status.lastPurgeTimeTime = status.gRDPTime;
843     }
844
845     status.dwNumDListsCulled = 0;
846     status.dwNumTrisRendered = 0;
847     status.dwNumTrisClipped = 0;
848     status.dwNumVertices = 0;
849     status.dwBiggestVertexIndex = 0;
850
851     if( g_curRomInfo.bForceScreenClear && CGraphicsContext::needCleanScene )
852     {
853         CRender::g_pRender->ClearBuffer(true,true);
854         CGraphicsContext::needCleanScene = false;
855     }
856
857     SetVIScales();
858     CRender::g_pRender->RenderReset();
859     CRender::g_pRender->BeginRendering();
860     CRender::g_pRender->SetViewport(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, 0x3FF);
861     CRender::g_pRender->SetFillMode(options.bWinFrameMode? RICE_FILLMODE_WINFRAME : RICE_FILLMODE_SOLID);
862
863     try
864     {
865         // The main loop
866         while( gDlistStackPointer >= 0 )
867         {
868 #ifdef DEBUGGER
869             DEBUGGER_PAUSE_COUNT_N(NEXT_UCODE);
870             if( debuggerPause )
871             {
872                 DebuggerPause();
873                 CRender::g_pRender->SetFillMode(options.bWinFrameMode? RICE_FILLMODE_WINFRAME : RICE_FILLMODE_SOLID);
874             }
875
876             if (gDlistStack[gDlistStackPointer].pc > g_dwRamSize)
877             {
878                 DebuggerAppendMsg("Error: dwPC is %08X", gDlistStack[gDlistStackPointer].pc );
879                 break;
880             }
881 #endif
882
883             status.gUcodeCount++;
884
885             Gfx *pgfx = (Gfx*)&g_pRDRAMu32[(gDlistStack[gDlistStackPointer].pc>>2)];
886 #ifdef DEBUGGER
887             LOG_UCODE("0x%08x: %08x %08x %-10s", 
888                 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)]);
889 #endif
890             gDlistStack[gDlistStackPointer].pc += 8;
891             currentUcodeMap[pgfx->words.w0 >>24](pgfx);
892
893             if ( gDlistStackPointer >= 0 && --gDlistStack[gDlistStackPointer].countdown < 0 )
894             {
895                 LOG_UCODE("**EndDLInMem");
896                 gDlistStackPointer--;
897             }
898         }
899
900     }
901     catch(...)
902     {
903         TRACE0("Unknown exception happens in ProcessDList");
904         TriggerDPInterrupt();
905     }
906
907     CRender::g_pRender->EndRendering();
908
909     if( gRSP.ucode >= 17)
910         TriggerDPInterrupt();
911     TriggerSPInterrupt();
912 }
913
914 //////////////////////////////////////////////////////////
915 //////////////////////////////////////////////////////////
916 //                   Util Functions                     //
917 //////////////////////////////////////////////////////////
918 //////////////////////////////////////////////////////////
919
920 void RDP_NOIMPL_Real(const char* op, uint32 word0, uint32 word1) 
921 {
922 #ifdef DEBUGGER
923     if( logWarning )
924     {
925         TRACE0("Stack Trace");
926         for( int i=0; i<gDlistStackPointer; i++ )
927         {
928             DebuggerAppendMsg("  %08X", gDlistStack[i].pc);
929         }
930         uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8;
931         DebuggerAppendMsg("PC=%08X",dwPC);
932         DebuggerAppendMsg(op, word0, word1);
933     }
934     DEBUGGER_PAUSE_AND_DUMP_COUNT_N(NEXT_UNKNOWN_OP, {TRACE0("Paused at unimplemented ucode\n");})
935 #endif
936 }
937
938 void RDP_NOIMPL_WARN(const char* op)
939 {
940 #ifdef DEBUGGER
941     if(logWarning)
942     {
943         TRACE0(op);
944     }
945 #endif
946 }
947
948
949 void RSP_GBI1_Noop(Gfx *gfx)
950 {
951 }
952
953
954 void RDP_GFX_PopDL()
955 {
956     LOG_UCODE("Returning from DisplayList: level=%d", gDlistStackPointer+1);
957     LOG_UCODE("############################################");
958     LOG_UCODE("/\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\ /\\");
959     LOG_UCODE("");
960
961     gDlistStackPointer--;
962 }
963
964 uint32 CalcalateCRC(uint32* srcPtr, uint32 srcSize)
965 {
966     uint32 crc=0;
967     for( uint32 i=0; i<srcSize; i++ )
968     {
969         crc += srcPtr[i];
970     }
971     return crc;
972 }
973
974
975 void RSP_GFX_InitGeometryMode()
976 {
977     bool bCullFront     = (gRDP.geometryMode & G_CULL_FRONT) ? true : false;
978     bool bCullBack      = (gRDP.geometryMode & G_CULL_BACK) ? true : false;
979     if( bCullFront && bCullBack ) // should never cull front
980     {
981         bCullFront = false;
982     }
983     CRender::g_pRender->SetCullMode(bCullFront, bCullBack);
984     
985     BOOL bShade         = (gRDP.geometryMode & G_SHADE) ? TRUE : FALSE;
986     BOOL bShadeSmooth   = (gRDP.geometryMode & G_SHADING_SMOOTH) ? TRUE : FALSE;
987     if (bShade && bShadeSmooth)     CRender::g_pRender->SetShadeMode( SHADE_SMOOTH );
988     else                            CRender::g_pRender->SetShadeMode( SHADE_FLAT );
989     
990     CRender::g_pRender->SetFogEnable( gRDP.geometryMode & G_FOG ? true : false );
991     SetTextureGen((gRDP.geometryMode & G_TEXTURE_GEN) ? true : false );
992     SetLighting( (gRDP.geometryMode & G_LIGHTING ) ? true : false );
993     CRender::g_pRender->ZBufferEnable( gRDP.geometryMode & G_ZBUFFER );
994 }
995
996 //////////////////////////////////////////////////////////
997 //////////////////////////////////////////////////////////
998 //                   DP Ucodes                          //
999 //////////////////////////////////////////////////////////
1000 //////////////////////////////////////////////////////////
1001
1002 void DLParser_SetKeyGB(Gfx *gfx)
1003 {
1004     DP_Timing(DLParser_SetKeyGB);
1005
1006     gRDP.keyB = ((gfx->words.w1)>>8)&0xFF;
1007     gRDP.keyG = ((gfx->words.w1)>>24)&0xFF;
1008     gRDP.keyA = (gRDP.keyR+gRDP.keyG+gRDP.keyB)/3;
1009     gRDP.fKeyA = gRDP.keyA/255.0f;
1010 }
1011 void DLParser_SetKeyR(Gfx *gfx)
1012 {
1013     DP_Timing(DLParser_SetKeyR);
1014
1015     gRDP.keyR = ((gfx->words.w1)>>8)&0xFF;
1016     gRDP.keyA = (gRDP.keyR+gRDP.keyG+gRDP.keyB)/3;
1017     gRDP.fKeyA = gRDP.keyA/255.0f;
1018 }
1019
1020 int g_convk0,g_convk1,g_convk2,g_convk3,g_convk4,g_convk5;
1021 float g_convc0,g_convc1,g_convc2,g_convc3,g_convc4,g_convc5;
1022 void DLParser_SetConvert(Gfx *gfx)
1023 {
1024     DP_Timing(DLParser_SetConvert);
1025
1026     int temp;
1027
1028     temp = ((gfx->words.w0)>>13)&0x1FF;
1029     g_convk0 = temp>0xFF ? -(temp-0x100) : temp;
1030
1031     temp = ((gfx->words.w0)>>4)&0x1FF;
1032     g_convk1 = temp>0xFF ? -(temp-0x100) : temp;
1033
1034     temp = (gfx->words.w0)&0xF;
1035     temp = (temp<<5)|(((gfx->words.w1)>>27)&0x1F);
1036     g_convk2 = temp>0xFF ? -(temp-0x100) : temp;
1037
1038     temp = ((gfx->words.w1)>>18)&0x1FF;
1039     g_convk3 = temp>0xFF ? -(temp-0x100) : temp;
1040
1041     temp = ((gfx->words.w1)>>9)&0x1FF;
1042     g_convk4 = temp>0xFF ? -(temp-0x100) : temp;
1043
1044     temp = (gfx->words.w1)&0x1FF;
1045     g_convk5 = temp>0xFF ? -(temp-0x100) : temp;
1046
1047     g_convc0 = g_convk5/255.0f+1.0f;
1048     g_convc1 = g_convk0/255.0f*g_convc0;
1049     g_convc2 = g_convk1/255.0f*g_convc0;
1050     g_convc3 = g_convk2/255.0f*g_convc0;
1051     g_convc4 = g_convk3/255.0f*g_convc0;
1052 }
1053 void DLParser_SetPrimDepth(Gfx *gfx)
1054 {
1055     DP_Timing(DLParser_SetPrimDepth);
1056     uint32 dwZ  = ((gfx->words.w1) >> 16) & 0xFFFF;
1057     uint32 dwDZ = ((gfx->words.w1)      ) & 0xFFFF;
1058
1059     LOG_UCODE("SetPrimDepth: 0x%08x 0x%08x - z: 0x%04x dz: 0x%04x",
1060         gfx->words.w0, gfx->words.w1, dwZ, dwDZ);
1061     
1062     SetPrimitiveDepth(dwZ, dwDZ);
1063     DEBUGGER_PAUSE(NEXT_SET_PRIM_COLOR);
1064 }
1065
1066 void DLParser_RDPSetOtherMode(Gfx *gfx)
1067 {
1068     DP_Timing(DLParser_RDPSetOtherMode);
1069     gRDP.otherMode._u32[1] = (gfx->words.w0);   // High
1070     gRDP.otherMode._u32[0] = (gfx->words.w1);   // Low
1071
1072     if( gRDP.otherModeH != ((gfx->words.w0) & 0x0FFFFFFF) )
1073     {
1074         gRDP.otherModeH = ((gfx->words.w0) & 0x0FFFFFFF);
1075
1076         uint32 dwTextFilt  = (gRDP.otherModeH>>RSP_SETOTHERMODE_SHIFT_TEXTFILT)&0x3;
1077         CRender::g_pRender->SetTextureFilter(dwTextFilt<<RSP_SETOTHERMODE_SHIFT_TEXTFILT);
1078     }
1079
1080     if( gRDP.otherModeL != (gfx->words.w1) )
1081     {
1082         if( (gRDP.otherModeL&ZMODE_DEC) != ((gfx->words.w1)&ZMODE_DEC) )
1083         {
1084             if( ((gfx->words.w1)&ZMODE_DEC) == ZMODE_DEC )
1085                 CRender::g_pRender->SetZBias( 2 );
1086             else
1087                 CRender::g_pRender->SetZBias( 0 );
1088         }
1089
1090         gRDP.otherModeL = (gfx->words.w1);
1091
1092         BOOL bZCompare      = (gRDP.otherModeL & Z_COMPARE)         ? TRUE : FALSE;
1093         BOOL bZUpdate       = (gRDP.otherModeL & Z_UPDATE)          ? TRUE : FALSE;
1094
1095         CRender::g_pRender->SetZCompare( bZCompare );
1096         CRender::g_pRender->SetZUpdate( bZUpdate );
1097
1098         uint32 dwAlphaTestMode = (gRDP.otherModeL >> RSP_SETOTHERMODE_SHIFT_ALPHACOMPARE) & 0x3;
1099
1100         if ((dwAlphaTestMode) != 0)
1101             CRender::g_pRender->SetAlphaTestEnable( TRUE );
1102         else
1103             CRender::g_pRender->SetAlphaTestEnable( FALSE );
1104     }
1105
1106     uint16 blender = gRDP.otherMode.blender;
1107     RDP_BlenderSetting &bl = *(RDP_BlenderSetting*)(&(blender));
1108     if( bl.c1_m1a==3 || bl.c1_m2a == 3 || bl.c2_m1a == 3 || bl.c2_m2a == 3 )
1109     {
1110         gRDP.bFogEnableInBlender = true;
1111     }
1112     else
1113     {
1114         gRDP.bFogEnableInBlender = false;
1115     }
1116 }
1117
1118
1119
1120 void DLParser_RDPLoadSync(Gfx *gfx) 
1121
1122     DP_Timing(DLParser_RDPLoadSync);
1123     LOG_UCODE("LoadSync: (Ignored)"); 
1124 }
1125
1126 void DLParser_RDPPipeSync(Gfx *gfx) 
1127
1128     DP_Timing(DLParser_RDPPipeSync);
1129     LOG_UCODE("PipeSync: (Ignored)"); 
1130 }
1131 void DLParser_RDPTileSync(Gfx *gfx) 
1132
1133     DP_Timing(DLParser_RDPTileSync);
1134     LOG_UCODE("TileSync: (Ignored)"); 
1135 }
1136
1137 void DLParser_RDPFullSync(Gfx *gfx)
1138
1139     DP_Timing(DLParser_RDPFullSync);
1140     TriggerDPInterrupt();
1141 }
1142
1143 void DLParser_SetScissor(Gfx *gfx)
1144 {
1145     DP_Timing(DLParser_SetScissor);
1146
1147     ScissorType tempScissor;
1148     // The coords are all in 8:2 fixed point
1149     tempScissor.x0   = ((gfx->words.w0)>>12)&0xFFF;
1150     tempScissor.y0   = ((gfx->words.w0)>>0 )&0xFFF;
1151     tempScissor.mode = ((gfx->words.w1)>>24)&0x03;
1152     tempScissor.x1   = ((gfx->words.w1)>>12)&0xFFF;
1153     tempScissor.y1   = ((gfx->words.w1)>>0 )&0xFFF;
1154
1155     tempScissor.left    = tempScissor.x0/4;
1156     tempScissor.top     = tempScissor.y0/4;
1157     tempScissor.right   = tempScissor.x1/4;
1158     tempScissor.bottom  = tempScissor.y1/4;
1159
1160     if( options.bEnableHacks )
1161     {
1162         if( g_CI.dwWidth == 0x200 && tempScissor.right == 0x200 )
1163         {
1164             uint32 width = *g_GraphicsInfo.VI_WIDTH_REG & 0xFFF;
1165
1166             if( width != 0x200 )
1167             {
1168                 // Hack for RE2
1169                 tempScissor.bottom = tempScissor.right*tempScissor.bottom/width;
1170                 tempScissor.right = width;
1171             }
1172
1173         }
1174     }
1175
1176     if( gRDP.scissor.left != tempScissor.left || gRDP.scissor.top != tempScissor.top ||
1177         gRDP.scissor.right != tempScissor.right || gRDP.scissor.bottom != tempScissor.bottom ||
1178         gRSP.real_clip_scissor_left != tempScissor.left || gRSP.real_clip_scissor_top != tempScissor.top ||
1179         gRSP.real_clip_scissor_right != tempScissor.right || gRSP.real_clip_scissor_bottom != tempScissor.bottom)
1180     {
1181         memcpy(&(gRDP.scissor), &tempScissor, sizeof(ScissorType) );
1182         if( !status.bHandleN64RenderTexture )
1183             SetVIScales();
1184
1185         if(  options.enableHackForGames == HACK_FOR_SUPER_BOWLING && g_CI.dwAddr%0x100 != 0 )
1186         {
1187             // right half screen
1188             gRDP.scissor.left += 160;
1189             gRDP.scissor.right += 160;
1190             CRender::g_pRender->SetViewport(160, 0, 320, 240, 0xFFFF);
1191         }
1192
1193         CRender::g_pRender->UpdateClipRectangle();
1194         CRender::g_pRender->UpdateScissor();
1195         CRender::g_pRender->SetViewportRender();
1196     }
1197
1198     LOG_UCODE("SetScissor: x0=%d y0=%d x1=%d y1=%d mode=%d",
1199         gRDP.scissor.left, gRDP.scissor.top,
1200         gRDP.scissor.right, gRDP.scissor.bottom,
1201         gRDP.scissor.mode);
1202
1203     ///TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("SetScissor: x0=%d y0=%d x1=%d y1=%d mode=%d", gRDP.scissor.left, gRDP.scissor.top,
1204     //gRDP.scissor.right, gRDP.scissor.bottom, gRDP.scissor.mode););
1205 }
1206
1207
1208 void DLParser_FillRect(Gfx *gfx)
1209
1210     DP_Timing(DLParser_FillRect);   // fix me
1211     status.primitiveType = PRIM_FILLRECT;
1212
1213     if( status.bN64IsDrawingTextureBuffer && frameBufferOptions.bIgnore )
1214     {
1215         return;
1216     }
1217
1218     if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
1219     {
1220         uint32 dwPC = gDlistStack[gDlistStackPointer].pc;       // This points to the next instruction
1221         uint32 w2 = *(uint32 *)(g_pRDRAMu8 + dwPC);
1222         if( (w2>>24) == RDP_FILLRECT )
1223         {
1224             // Mario Tennis, a lot of FillRect ucodes, skip all of them
1225             while( (w2>>24) == RDP_FILLRECT )
1226             {
1227                 dwPC += 8;
1228                 w2 = *(uint32 *)(g_pRDRAMu8 + dwPC);
1229             }
1230
1231             gDlistStack[gDlistStackPointer].pc = dwPC;
1232             return;
1233         }
1234     }
1235
1236     uint32 x0   = (((gfx->words.w1)>>12)&0xFFF)/4;
1237     uint32 y0   = (((gfx->words.w1)>>0 )&0xFFF)/4;
1238     uint32 x1   = (((gfx->words.w0)>>12)&0xFFF)/4;
1239     uint32 y1   = (((gfx->words.w0)>>0 )&0xFFF)/4;
1240
1241     // Note, in some modes, the right/bottom lines aren't drawn
1242
1243     LOG_UCODE("    (%d,%d) (%d,%d)", x0, y0, x1, y1);
1244
1245     if( gRDP.otherMode.cycle_type >= CYCLE_TYPE_COPY )
1246     {
1247         x1++;
1248         y1++;
1249     }
1250
1251     //TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("FillRect: X0=%d, Y0=%d, X1=%d, Y1=%d, Color=0x%08X", x0, y0, x1, y1, gRDP.originalFillColor););
1252
1253     if( status.bHandleN64RenderTexture && options.enableHackForGames == HACK_FOR_BANJO_TOOIE )
1254     {
1255         // Skip this
1256         return;
1257     }
1258
1259     if (IsUsedAsDI(g_CI.dwAddr))
1260     {
1261         // Clear the Z Buffer
1262         if( x0!=0 || y0!=0 || windowSetting.uViWidth-x1>1 || windowSetting.uViHeight-y1>1)
1263         {
1264             if( options.enableHackForGames == HACK_FOR_GOLDEN_EYE )
1265             {
1266                 // GoldenEye is using double zbuffer
1267                 if( g_CI.dwAddr == g_ZI.dwAddr )
1268                 {
1269                     // The zbuffer is the upper screen
1270                     COORDRECT rect={int(x0*windowSetting.fMultX),int(y0*windowSetting.fMultY),int(x1*windowSetting.fMultX),int(y1*windowSetting.fMultY)};
1271                     CRender::g_pRender->ClearBuffer(false,true,rect);   //Check me
1272                     LOG_UCODE("    Clearing ZBuffer");
1273                 }
1274                 else
1275                 {
1276                     // The zbuffer is the lower screen
1277                     int h = (g_CI.dwAddr-g_ZI.dwAddr)/g_CI.dwWidth/2;
1278                     COORDRECT rect={int(x0*windowSetting.fMultX),int((y0+h)*windowSetting.fMultY),int(x1*windowSetting.fMultX),int((y1+h)*windowSetting.fMultY)};
1279                     CRender::g_pRender->ClearBuffer(false,true,rect);   //Check me
1280                     LOG_UCODE("    Clearing ZBuffer");
1281                 }
1282             }
1283             else
1284             {
1285                 COORDRECT rect={int(x0*windowSetting.fMultX),int(y0*windowSetting.fMultY),int(x1*windowSetting.fMultX),int(y1*windowSetting.fMultY)};
1286                 CRender::g_pRender->ClearBuffer(false,true,rect);   //Check me
1287                 LOG_UCODE("    Clearing ZBuffer");
1288             }
1289         }
1290         else
1291         {
1292             CRender::g_pRender->ClearBuffer(false,true);    //Check me
1293             LOG_UCODE("    Clearing ZBuffer");
1294         }
1295
1296         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect: ClearZbuffer\n");});
1297         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);
1298         DebuggerAppendMsg("Pause after ClearZbuffer: Color=%08X\n", gRDP.originalFillColor);});
1299
1300         if( g_curRomInfo.bEmulateClear )
1301         {
1302             // Emulating Clear, by write the memory in RDRAM
1303             uint16 color = (uint16)gRDP.originalFillColor;
1304             uint32 pitch = g_CI.dwWidth<<1;
1305             long long base = (long long) (g_pRDRAMu8 + g_CI.dwAddr);
1306             for( uint32 i =y0; i<y1; i++ )
1307             {
1308                 for( uint32 j=x0; j<x1; j++ )
1309                 {
1310                     *(uint16*)((base+pitch*i+j)^2) = color;
1311                 }
1312             }
1313         }
1314     }
1315     else if( status.bHandleN64RenderTexture )
1316     {
1317         if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
1318
1319         status.leftRendered = status.leftRendered<0 ? x0 : min((int)x0,status.leftRendered);
1320         status.topRendered = status.topRendered<0 ? y0 : min((int)y0,status.topRendered);
1321         status.rightRendered = status.rightRendered<0 ? x1 : max((int)x1,status.rightRendered);
1322         status.bottomRendered = status.bottomRendered<0 ? y1 : max((int)y1,status.bottomRendered);
1323
1324         g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,(int)y1);
1325
1326         if( status.bDirectWriteIntoRDRAM || ( x0==0 && y0==0 && (x1 == g_pRenderTextureInfo->N64Width || x1 == g_pRenderTextureInfo->N64Width-1 ) ) )
1327         {
1328             if( g_pRenderTextureInfo->CI_Info.dwSize == TXT_SIZE_16b )
1329             {
1330                 uint16 color = (uint16)gRDP.originalFillColor;
1331                 uint32 pitch = g_pRenderTextureInfo->N64Width<<1;
1332                 long long base = (long long) (g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr);
1333                 for( uint32 i =y0; i<y1; i++ )
1334                 {
1335                     for( uint32 j=x0; j<x1; j++ )
1336                     {
1337                         *(uint16*)((base+pitch*i+j)^2) = color;
1338                     }
1339                 }
1340             }
1341             else
1342             {
1343                 uint8 color = (uint8)gRDP.originalFillColor;
1344                 uint32 pitch = g_pRenderTextureInfo->N64Width;
1345                 long long base = (long long) (g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr);
1346                 for( uint32 i=y0; i<y1; i++ )
1347                 {
1348                     for( uint32 j=x0; j<x1; j++ )
1349                     {
1350                         *(uint8*)((base+pitch*i+j)^3) = color;
1351                     }
1352                 }
1353             }
1354
1355             status.bFrameBufferDrawnByTriangles = false;
1356         }
1357         else
1358         {
1359             status.bFrameBufferDrawnByTriangles = true;
1360         }
1361         status.bFrameBufferDrawnByTriangles = true;
1362
1363         if( !status.bDirectWriteIntoRDRAM )
1364         {
1365             status.bFrameBufferIsDrawn = true;
1366
1367             //if( x0==0 && y0==0 && (x1 == g_pRenderTextureInfo->N64Width || x1 == g_pRenderTextureInfo->N64Width-1 ) && gRDP.fillColor == 0)
1368             //{
1369             //  CRender::g_pRender->ClearBuffer(true,false);
1370             //}
1371             //else
1372             {
1373                 if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL )
1374                 {
1375                     CRender::g_pRender->FillRect(x0, y0, x1, y1, gRDP.fillColor);
1376                 }
1377                 else
1378                 {
1379                     COLOR primColor = GetPrimitiveColor();
1380                     CRender::g_pRender->FillRect(x0, y0, x1, y1, primColor);
1381                 }
1382             }
1383         }
1384
1385         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect\n");});
1386         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);
1387         DebuggerAppendMsg("Pause after FillRect: Color=%08X\n", gRDP.originalFillColor);});
1388     }
1389     else
1390     {
1391         LOG_UCODE("    Filling Rectangle");
1392         if( frameBufferOptions.bSupportRenderTextures || frameBufferOptions.bCheckBackBufs )
1393         {
1394             if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
1395
1396             status.leftRendered = status.leftRendered<0 ? x0 : min((int)x0,status.leftRendered);
1397             status.topRendered = status.topRendered<0 ? y0 : min((int)y0,status.topRendered);
1398             status.rightRendered = status.rightRendered<0 ? x1 : max((int)x1,status.rightRendered);
1399             status.bottomRendered = status.bottomRendered<0 ? y1 : max((int)y1,status.bottomRendered);
1400         }
1401
1402         if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL )
1403         {
1404             if( !status.bHandleN64RenderTexture || g_pRenderTextureInfo->CI_Info.dwSize == TXT_SIZE_16b )
1405             {
1406                 CRender::g_pRender->FillRect(x0, y0, x1, y1, gRDP.fillColor);
1407             }
1408         }
1409         else
1410         {
1411             COLOR primColor = GetPrimitiveColor();
1412             //if( RGBA_GETALPHA(primColor) != 0 )
1413             {
1414                 CRender::g_pRender->FillRect(x0, y0, x1, y1, primColor);
1415             }
1416         }
1417         DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect\n");});
1418         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);
1419         DebuggerAppendMsg("Pause after FillRect: Color=%08X\n", gRDP.originalFillColor);});
1420     }
1421 }
1422
1423
1424 #define STORE_CI    {g_CI.dwAddr = dwNewAddr;g_CI.dwFormat = dwFmt;g_CI.dwSize = dwSiz;g_CI.dwWidth = dwWidth;g_CI.bpl=dwBpl;}
1425
1426 void DLParser_SetCImg(Gfx *gfx)
1427 {
1428     uint32 dwFmt        = gfx->setimg.fmt;
1429     uint32 dwSiz        = gfx->setimg.siz;
1430     uint32 dwWidth      = gfx->setimg.width + 1;
1431     uint32 dwNewAddr    = RSPSegmentAddr((gfx->setimg.addr)) & 0x00FFFFFF ;
1432     uint32 dwBpl        = dwWidth << dwSiz >> 1;
1433
1434     TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", dwNewAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth););
1435
1436     if( dwFmt == TXT_FMT_YUV || dwFmt == TXT_FMT_IA )
1437     {
1438         WARNING(TRACE4("Check me:  SetCImg Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1439             g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth));
1440     }
1441
1442     LOG_UCODE("    Image: 0x%08x", RSPSegmentAddr(gfx->words.w1));
1443     LOG_UCODE("    Fmt: %s Size: %s Width: %d",
1444         pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1445
1446     if( g_CI.dwAddr == dwNewAddr && g_CI.dwFormat == dwFmt && g_CI.dwSize == dwSiz && g_CI.dwWidth == dwWidth )
1447     {
1448         TXTRBUF_OR_CI_DETAIL_DUMP({
1449             TRACE0("Set CIMG to the same address, no change, skipped");
1450             DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1451                 g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1452         });
1453         return;
1454     }
1455
1456     if( status.bVIOriginIsUpdated == true && currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_1ST_CI_CHANGE )
1457     {
1458         status.bVIOriginIsUpdated=false;
1459         CGraphicsContext::Get()->UpdateFrame();
1460         TXTRBUF_OR_CI_DETAIL_DUMP(TRACE0("Screen Update at 1st CI change"););
1461     }
1462
1463     if( options.enableHackForGames == HACK_FOR_SUPER_BOWLING )
1464     {
1465         if( dwNewAddr%0x100 == 0 )
1466         {
1467             if( dwWidth < 320 )
1468             {
1469                 // Left half screen
1470                 gRDP.scissor.left = 0;
1471                 gRDP.scissor.right = 160;
1472                 CRender::g_pRender->SetViewport(0, 0, 160, 240, 0xFFFF);
1473                 CRender::g_pRender->UpdateClipRectangle();
1474                 CRender::g_pRender->UpdateScissor();
1475             }
1476             else
1477             {
1478                 gRDP.scissor.left = 0;
1479                 gRDP.scissor.right = 320;
1480                 CRender::g_pRender->SetViewport(0, 0, 320, 240, 0xFFFF);
1481                 CRender::g_pRender->UpdateClipRectangle();
1482                 CRender::g_pRender->UpdateScissor();
1483             }
1484         }
1485         else
1486         {
1487             // right half screen
1488             gRDP.scissor.left = 160;
1489             gRDP.scissor.right = 320;
1490             gRSP.nVPLeftN = 160;
1491             gRSP.nVPRightN = 320;
1492             CRender::g_pRender->UpdateClipRectangle();
1493             CRender::g_pRender->UpdateScissor();
1494             CRender::g_pRender->SetViewport(160, 0, 320, 240, 0xFFFF);
1495         }
1496     }
1497
1498
1499     if( !frameBufferOptions.bUpdateCIInfo )
1500     {
1501         STORE_CI;
1502         status.bCIBufferIsRendered = false;
1503         status.bN64IsDrawingTextureBuffer = false;
1504
1505         TXTRBUF_DUMP(TRACE4("SetCImg : Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1506             g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth));
1507
1508         DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG, 
1509         {
1510             DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1511                 dwNewAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1512         }
1513         );
1514         return;
1515     }
1516
1517     SetImgInfo newCI;
1518     newCI.bpl = dwBpl;
1519     newCI.dwAddr = dwNewAddr;
1520     newCI.dwFormat = dwFmt;
1521     newCI.dwSize = dwSiz;
1522     newCI.dwWidth = dwWidth;
1523
1524     g_pFrameBufferManager->Set_CI_addr(newCI);
1525 }
1526
1527 void DLParser_SetZImg(Gfx *gfx)
1528 {
1529     DP_Timing(DLParser_SetZImg);
1530     LOG_UCODE("    Image: 0x%08x", RSPSegmentAddr(gfx->words.w1));
1531
1532     uint32 dwFmt   = gfx->setimg.fmt;
1533     uint32 dwSiz   = gfx->setimg.siz;
1534     uint32 dwWidth = gfx->setimg.width + 1;
1535     uint32 dwAddr = RSPSegmentAddr((gfx->setimg.addr));
1536
1537     if( dwAddr != g_ZI_saves[0].CI_Info.dwAddr )
1538     {
1539         g_ZI_saves[1].CI_Info.dwAddr    = g_ZI.dwAddr;
1540         g_ZI_saves[1].CI_Info.dwFormat  = g_ZI.dwFormat;
1541         g_ZI_saves[1].CI_Info.dwSize    = g_ZI.dwSize;
1542         g_ZI_saves[1].CI_Info.dwWidth   = g_ZI.dwWidth;
1543         g_ZI_saves[1].updateAtFrame = g_ZI_saves[0].updateAtFrame;
1544
1545         g_ZI_saves[0].CI_Info.dwAddr    = g_ZI.dwAddr   = dwAddr;
1546         g_ZI_saves[0].CI_Info.dwFormat  = g_ZI.dwFormat = dwFmt;
1547         g_ZI_saves[0].CI_Info.dwSize    = g_ZI.dwSize   = dwSiz;
1548         g_ZI_saves[0].CI_Info.dwWidth   = g_ZI.dwWidth  = dwWidth;
1549         g_ZI_saves[0].updateAtFrame     = status.gDlistCount;
1550     }
1551     else
1552     {
1553         g_ZI.dwAddr = dwAddr;
1554         g_ZI.dwFormat = dwFmt;
1555         g_ZI.dwSize = dwSiz;
1556         g_ZI.dwWidth    = dwWidth;
1557     }
1558
1559     DEBUGGER_IF_DUMP((pauseAtNext) ,
1560     {DebuggerAppendMsg("SetZImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1561     g_ZI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);}
1562     );
1563
1564     DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG, 
1565         {
1566             DebuggerAppendMsg("Pause after SetZImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
1567                 g_ZI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);
1568         }
1569     );
1570 }
1571
1572 bool IsUsedAsDI(uint32 addr)
1573 {
1574     if( addr == g_ZI_saves[0].CI_Info.dwAddr )
1575         return true;
1576     else if( addr == g_ZI_saves[1].CI_Info.dwAddr && status.gDlistCount - g_ZI_saves[1].updateAtFrame < 10 
1577         && g_ZI_saves[1].CI_Info.dwAddr != 0 )
1578         return true;
1579     else
1580         return false;
1581 }
1582
1583 void DLParser_SetCombine(Gfx *gfx)
1584 {
1585     DP_Timing(DLParser_SetCombine);
1586     uint32 dwMux0 = (gfx->words.w0)&0x00FFFFFF;
1587     uint32 dwMux1 = (gfx->words.w1);
1588     CRender::g_pRender->SetMux(dwMux0, dwMux1);
1589 }
1590
1591 void DLParser_SetFillColor(Gfx *gfx)
1592 {
1593     DP_Timing(DLParser_SetFillColor);
1594     gRDP.fillColor = Convert555ToRGBA(gfx->setcolor.fillcolor);
1595     gRDP.originalFillColor = (gfx->setcolor.color);
1596
1597     LOG_UCODE("    Color5551=0x%04x = 0x%08x", (uint16)gfx->words.w1, gRDP.fillColor);
1598
1599 }
1600
1601 void DLParser_SetFogColor(Gfx *gfx)
1602 {
1603     DP_Timing(DLParser_SetFogColor);
1604     CRender::g_pRender->SetFogColor( gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a );
1605     FOG_DUMP(TRACE1("Set Fog color: %08X", gfx->setcolor.color));
1606 }
1607
1608 void DLParser_SetBlendColor(Gfx *gfx)
1609 {
1610     DP_Timing(DLParser_SetBlendColor);
1611     CRender::g_pRender->SetAlphaRef(gfx->setcolor.a);
1612 }
1613
1614
1615 void DLParser_SetPrimColor(Gfx *gfx)
1616 {
1617     DP_Timing(DLParser_SetPrimColor);
1618     SetPrimitiveColor( COLOR_RGBA(gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a), 
1619         gfx->setcolor.prim_min_level, gfx->setcolor.prim_level);
1620 }
1621
1622 void DLParser_SetEnvColor(Gfx *gfx)
1623 {
1624     DP_Timing(DLParser_SetEnvColor);
1625     SetEnvColor( COLOR_RGBA(gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a) );
1626 }
1627
1628
1629 void RDP_DLParser_Process(void)
1630 {
1631     status.gRDPTime = (uint32) SDL_GetTicks();
1632
1633     status.gDlistCount++;
1634
1635     uint32 start = *(g_GraphicsInfo.DPC_START_REG);
1636     uint32 end = *(g_GraphicsInfo.DPC_END_REG);
1637
1638     gDlistStackPointer=0;
1639     gDlistStack[gDlistStackPointer].pc = start;
1640     gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
1641
1642     // Check if we need to purge (every 5 milliseconds)
1643     if (status.gRDPTime - status.lastPurgeTimeTime > 5)
1644     {
1645         gTextureManager.PurgeOldTextures();
1646         status.lastPurgeTimeTime = status.gRDPTime;
1647     }
1648     
1649     // Lock the graphics context here.
1650     CRender::g_pRender->SetFillMode(RICE_FILLMODE_SOLID);
1651
1652     SetVIScales();
1653
1654     CRender::g_pRender->RenderReset();
1655     CRender::g_pRender->BeginRendering();
1656     CRender::g_pRender->SetViewport(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, 0x3FF);
1657
1658     while( gDlistStack[gDlistStackPointer].pc < end )
1659     {
1660         Gfx *pgfx = (Gfx*)&g_pRDRAMu32[(gDlistStack[gDlistStackPointer].pc>>2)];
1661         gDlistStack[gDlistStackPointer].pc += 8;
1662         currentUcodeMap[pgfx->words.w0 >>24](pgfx);
1663     }
1664
1665     CRender::g_pRender->EndRendering();
1666 }
1667
1668 void RDP_TriFill(Gfx *gfx)
1669 {
1670 }
1671
1672 void RDP_TriFillZ(Gfx *gfx)
1673 {
1674 }
1675
1676 void RDP_TriTxtr(Gfx *gfx)
1677 {
1678 }
1679
1680 void RDP_TriTxtrZ(Gfx *gfx)
1681 {
1682 }
1683
1684 void RDP_TriShade(Gfx *gfx)
1685 {
1686 }
1687
1688 void RDP_TriShadeZ(Gfx *gfx)
1689 {
1690 }
1691
1692 void RDP_TriShadeTxtr(Gfx *gfx)
1693 {
1694 }
1695
1696 void RDP_TriShadeTxtrZ(Gfx *gfx)
1697 {
1698 }
1699
1700 static int crc_table_empty = 1;
1701 static unsigned int crc_table[256];
1702 static void make_crc_table(void);
1703
1704 static void make_crc_table()
1705 {
1706   unsigned int c;
1707   int n, k;
1708   unsigned int poly;            /* polynomial exclusive-or pattern */
1709   /* terms of polynomial defining this crc (except x^32): */
1710   static const uint8 p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
1711
1712   /* make exclusive-or pattern from polynomial (0xedb88320L) */
1713   poly = 0L;
1714   for (n = 0; (unsigned int)n < sizeof(p)/sizeof(uint8); n++)
1715     poly |= 1L << (31 - p[n]);
1716  
1717   for (n = 0; n < 256; n++)
1718   {
1719     c = (unsigned int)n;
1720     for (k = 0; k < 8; k++)
1721       c = (c & 1) ? (poly ^ (c >> 1)) : c >> 1;
1722     crc_table[n] = c;
1723   }
1724   crc_table_empty = 0;
1725 }
1726
1727 /* ========================================================================= */
1728 #define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
1729 #define DO2(buf)  DO1(buf); DO1(buf);
1730 #define DO4(buf)  DO2(buf); DO2(buf);
1731 #define DO8(buf)  DO4(buf); DO4(buf);
1732
1733 /* ========================================================================= */
1734 unsigned int ComputeCRC32(unsigned int crc, const uint8 *buf, unsigned int len)
1735 {
1736     if (buf == NULL)
1737         return 0L;
1738
1739     if (crc_table_empty)
1740       make_crc_table();
1741
1742     crc = crc ^ 0xffffffffL;
1743     while (len >= 8)
1744     {
1745       DO8(buf);
1746       len -= 8;
1747     }
1748     if (len) do {
1749       DO1(buf);
1750     } while (--len);
1751     return crc ^ 0xffffffffL;
1752 }
1753
1754 Matrix matToLoad;
1755 void LoadMatrix(uint32 addr)
1756 {
1757     const float fRecip = 1.0f / 65536.0f;
1758     if (addr + 64 > g_dwRamSize)
1759     {
1760         TRACE1("Mtx: Address invalid (0x%08x)", addr);
1761         return;
1762     }
1763
1764     for (int i = 0; i < 4; i++)
1765     {
1766         for (int j = 0; j < 4; j++) 
1767         {
1768             int hi = *(short *)(g_pRDRAMu8 + ((addr+(i<<3)+(j<<1)     )^0x2));
1769             int lo = *(unsigned short *)(g_pRDRAMu8 + ((addr+(i<<3)+(j<<1) + 32)^0x2));
1770             matToLoad.m[i][j] = (float)((hi<<16) | lo) * fRecip;
1771         }
1772     }
1773
1774
1775 #ifdef DEBUGGER
1776     LOG_UCODE(
1777         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n"
1778         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n"
1779         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n"
1780         " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n",
1781         matToLoad.m[0][0], matToLoad.m[0][1], matToLoad.m[0][2], matToLoad.m[0][3],
1782         matToLoad.m[1][0], matToLoad.m[1][1], matToLoad.m[1][2], matToLoad.m[1][3],
1783         matToLoad.m[2][0], matToLoad.m[2][1], matToLoad.m[2][2], matToLoad.m[2][3],
1784         matToLoad.m[3][0], matToLoad.m[3][1], matToLoad.m[3][2], matToLoad.m[3][3]);
1785 #endif // DEBUGGER
1786 }
1787