Some attempts to speedup Rice when using FB
[mupen64plus-pandora.git] / source / gles2rice / src / RSP_Parser.cpp
CommitLineData
292f9317 1/*
2Copyright (C) 2003 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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
37UcodeInfo ucodeInfo[MAX_UCODE_INFO];
38
39RDPInstruction LoadedUcodeMap[256];
40char* LoadedUcodeNameMap[256];
41
42OSTask *g_pOSTask = NULL;
43UcodeInfo lastUcodeInfo;
44UcodeInfo UsedUcodes[MAX_UCODE_INFO];
45const uint32 maxUsedUcodes = sizeof(UsedUcodes)/sizeof(UcodeInfo);
46
47//////////////////////////////////////////////////////////
48//////////////////////////////////////////////////////////
49// Ucodes //
50//////////////////////////////////////////////////////////
51//////////////////////////////////////////////////////////
52
53UcodeMap *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
78uint32 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
104unsigned char gLastMicrocodeString[ 300 ] = "";
105
106//*****************************************************************************
107//
108//*****************************************************************************
109static 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
241FiddledVtx * g_pVtxBase=NULL;
242
243SetImgInfo g_TI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 };
244SetImgInfo g_CI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 };
245SetImgInfo g_ZI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 };
246RenderTextureInfo g_ZI_saves[2];
247
248DListStack gDlistStack[MAX_DL_STACK_SIZE];
249int gDlistStackPointer= -1;
250
251TMEMLoadMapInfo g_tmemLoadAddrMap[0x200]; // Totally 4KB TMEM
252TMEMLoadMapInfo g_tmemInfo0; // Info for Tmem=0
253TMEMLoadMapInfo g_tmemInfo1; // Info for Tmem=0x100
254
255const char *pszImgSize[4] = {"4", "8", "16", "32"};
256const char *textluttype[4] = {"RGB16", "I16?", "RGBA16", "IA16"};
257uint16 g_wRDPTlut[0x200];
258uint32 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
275void 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
338void RDP_GFX_Reset()
339{
340 gDlistStackPointer=-1;
341 status.bUcodeIsKnown = FALSE;
342 gTextureManager.RecycleAllTextures();
343}
344
345
346void RDP_Cleanup()
347{
348 if( status.bHandleN64RenderTexture )
349 {
350 g_pFrameBufferManager->CloseRenderTexture(false);
351 }
352}
353
354void 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
526void 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//*****************************************************************************
569static 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//*****************************************************************************
607static 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
655uint32 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
780extern int dlistMtxCount;
781extern bool bHalfTxtScale;
782
ca22e7b7 783extern float mspervi;
784extern float numvi;
785static int skipframe=0;
786static unsigned int oldtick=0;
787static int oldskip=0;
788extern bool skipping;
789
292f9317 790void 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;
ca22e7b7 806/* if( options.bSkipFrame )
292f9317 807 {
808 skipframe++;
809 if(skipframe%2)
810 {
811 TriggerDPInterrupt();
812 TriggerSPInterrupt();
813 return;
814 }
815 }
ca22e7b7 816*/
292f9317 817 if( currentRomOptions.N64RenderToTextureEmuType != TXT_BUF_NONE && defaultRomOptions.bSaveVRAM )
818 {
819 g_pFrameBufferManager->CheckRenderTextureCRCInRDRAM();
820 }
821
ca22e7b7 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
292f9317 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
959void 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
977void RDP_NOIMPL_WARN(const char* op)
978{
979#ifdef DEBUGGER
980 if(logWarning)
981 {
982 TRACE0(op);
983 }
984#endif
985}
986
987
988void RSP_GBI1_Noop(Gfx *gfx)
989{
990}
991
992
993void 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
1003uint32 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
1014void 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
1041void 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}
1050void 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
1059int g_convk0,g_convk1,g_convk2,g_convk3,g_convk4,g_convk5;
1060float g_convc0,g_convc1,g_convc2,g_convc3,g_convc4,g_convc5;
1061void 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}
1092void 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
1105void 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
1159void DLParser_RDPLoadSync(Gfx *gfx)
1160{
1161 DP_Timing(DLParser_RDPLoadSync);
1162 LOG_UCODE("LoadSync: (Ignored)");
1163}
1164
1165void DLParser_RDPPipeSync(Gfx *gfx)
1166{
1167 DP_Timing(DLParser_RDPPipeSync);
1168 LOG_UCODE("PipeSync: (Ignored)");
1169}
1170void DLParser_RDPTileSync(Gfx *gfx)
1171{
1172 DP_Timing(DLParser_RDPTileSync);
1173 LOG_UCODE("TileSync: (Ignored)");
1174}
1175
1176void DLParser_RDPFullSync(Gfx *gfx)
1177{
1178 DP_Timing(DLParser_RDPFullSync);
1179 TriggerDPInterrupt();
1180}
1181
1182void 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
1247void 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
1465void 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
1566void 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
1611bool 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
1622void 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
1630void 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
1640void 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
1647void DLParser_SetBlendColor(Gfx *gfx)
1648{
1649 DP_Timing(DLParser_SetBlendColor);
1650 CRender::g_pRender->SetAlphaRef(gfx->setcolor.a);
1651}
1652
1653
1654void 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
1661void 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
1668void 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
1707void RDP_TriFill(Gfx *gfx)
1708{
1709}
1710
1711void RDP_TriFillZ(Gfx *gfx)
1712{
1713}
1714
1715void RDP_TriTxtr(Gfx *gfx)
1716{
1717}
1718
1719void RDP_TriTxtrZ(Gfx *gfx)
1720{
1721}
1722
1723void RDP_TriShade(Gfx *gfx)
1724{
1725}
1726
1727void RDP_TriShadeZ(Gfx *gfx)
1728{
1729}
1730
1731void RDP_TriShadeTxtr(Gfx *gfx)
1732{
1733}
1734
1735void RDP_TriShadeTxtrZ(Gfx *gfx)
1736{
1737}
1738
1739static int crc_table_empty = 1;
1740static unsigned int crc_table[256];
1741static void make_crc_table(void);
1742
1743static 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/* ========================================================================= */
1773unsigned 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
1793Matrix matToLoad;
1794void 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