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