X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Frice_gles%2Fsrc%2FRSP_Parser.cpp;fp=source%2Frice_gles%2Fsrc%2FRSP_Parser.cpp;h=effe75cba6d5ea519618e053c3972700331eed1d;hb=d07c171fa694cae985ad7045f9ce2b2f1a5699b4;hp=0000000000000000000000000000000000000000;hpb=ca22e7b76883b946060a6b40bb8709c1981e1cf6;p=mupen64plus-pandora.git diff --git a/source/rice_gles/src/RSP_Parser.cpp b/source/rice_gles/src/RSP_Parser.cpp new file mode 100755 index 0000000..effe75c --- /dev/null +++ b/source/rice_gles/src/RSP_Parser.cpp @@ -0,0 +1,1826 @@ +/* +Copyright (C) 2003 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include +#include + +#include "ConvertImage.h" +#include "GraphicsContext.h" +#include "Render.h" +#include "RenderTexture.h" +#include "Video.h" +#include "ucode.h" +#include + +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// +// uCode Config // +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// +#define MAX_UCODE_INFO 16 +UcodeInfo ucodeInfo[MAX_UCODE_INFO]; + +RDPInstruction LoadedUcodeMap[256]; +char* LoadedUcodeNameMap[256]; + +OSTask *g_pOSTask = NULL; +UcodeInfo lastUcodeInfo; +UcodeInfo UsedUcodes[MAX_UCODE_INFO]; +const uint32 maxUsedUcodes = sizeof(UsedUcodes)/sizeof(UcodeInfo); + +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// +// Ucodes // +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// + +UcodeMap *ucodeMaps[] = +{ + &ucodeMap0, // ucode 0 - Mario + &ucodeMap1, // ucode 1 - GBI1 + NULL, // ucode 2 - Golden Eye + &ucodeMap3, // ucode 3 - S2DEX GBI2 + NULL, // ucode 4 - Wave Racer + &ucodeMap5, // ucode 5 - BGI2 + NULL, // ucode 6 - DKR + &ucodeMap7, // ucode 7 - S2DEX + NULL, // ucode 8 - ucode 0 with sprite2D, for Demo Puzzle Master 64 + NULL, // ucode 9 - Perfect Dark + NULL, // ucode 10 - Conker + NULL, // ucode 11 - Gemini + NULL, // ucode 12 - Silicon Valley, Spacestation + NULL, // ucode 13 - modified ucode S2DEX + NULL, // ucode 14 - OgreBattle Background + NULL, // ucode 15 - ucode 0 with sprite2D + NULL, // ucode 16 - Star War, Shadow of Empire + NULL, // ucode 17 - Star Wars - Rogue Squadron, + NULL, // ucode 18 - World Driver Championship + NULL, // ucode 19 - Last Legion UX + &ucodeMap1, // ucode 20 - ZSortp +}; + +uint32 vertexMultVals[] = +{ + 10, // ucode 0 - Mario + 2, // ucode 1 - GBI1 + 10, // ucode 2 - Golden Eye + 2, // ucode 3 - S2DEX GBI2 + 5, // ucode 4 - Wave Racer + 2, // ucode 5 - BGI2 + 10, // ucode 6 - DKR + 2, // ucode 7 - S2DEX + 10, // ucode 8 - ucode 0 with sprite2D, for Demo Puzzle Master 64 + 10, // ucode 9 - Perfect Dark + 2, // ucode 10 - Conker + 10, // ucode 11 - Gemini + 2, // ucode 12 - Silicon Valley, Spacestation + 2, // ucode 13 - modified ucode S2DEX + 2, // ucode 14 - OgreBattle Background + 10, // ucode 15 - ucode 0 with sprite2D + 5, // ucode 16 - Star War, Shadow of Empire + + 2, // ucode 17 - Star Wars - Rogue Squadron, + 2, // ucode 18 - World Driver Championship, check me here + 2, // ucode 19 - Last Legion UX, check me here + 2, // ucode 20 - ZSortp +}; + +unsigned char gLastMicrocodeString[ 300 ] = ""; + +//***************************************************************************** +// +//***************************************************************************** +static UcodeData g_UcodeData[] = +{ + //crc_size, crc_800; + + {0, 0x150c3ce8, 0x150c3ce8, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Super Mario 64 + {4, 0x2b94276f, 0x2b94276f, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Wave Race 64 (v1.0) + {16,0xb1870454, 0xb1870454, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Star Wars - Shadows of the Empire (v1.0), + {0, 0x51671ae4, 0x51671ae4, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Pilot Wings 64, + {0, 0x67b5ac55, 0x67b5ac55, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Wibble, + {0, 0x64dc8104, 0x64dc8104, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Dark Rift, + {0, 0x309f363d, 0x309f363d, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Killer Instinct Gold, + {0, 0xfcb57e57, 0xfcb57e57, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Blast Corps, + {0, 0xb420f35a, 0xb420f35a, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, // Blast Corps, + {0, 0x6e26c1df, 0x7c98e9c2, (unsigned char*)"RSP SW Version: 2.0D, 04-01-96",}, + {2, 0xc02ac7bc, 0xc02ac7bc, (unsigned char*)"RSP SW Version: 2.0G, 09-30-96",}, // GoldenEye 007, + {0, 0xe5fee3bc, 0xe5fee3bc, (unsigned char*)"RSP SW Version: 2.0G, 09-30-96",}, // Aero Fighters Assault, + {8, 0xe4bb5ad8, 0x80129845, (unsigned char*)"RSP SW Version: 2.0G, 09-30-96",}, // Puzzle Master 64, + {0, 0x72109ec6, 0x72109ec6, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Duke Nukem 64, + {0, 0xf24a9a04, 0xf24a9a04, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Tetrisphere, + {15,0x700de42e, 0x700de42e, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Wipeout 64 (uses GBI1 too!), + {15,0x1b304a74, 0x1b304a74, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Flying Dragon, + {15,0xe4bb5ad8, 0xa7b2f704, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Silicon Valley, + {15,0xe4bb5ad8, 0x88202781, (unsigned char*)"RSP SW Version: 2.0H, 02-12-97",}, // Glover, + {0, 0xe466b5bd, 0xe466b5bd, (unsigned char*)"Unknown 0xe466b5bd, 0xe466b5bd",}, // Dark Rift, + {9, 0x7064a163, 0x7064a163, (unsigned char*)"Unknown 0x7064a163, 0x7064a163",}, // Perfect Dark (v1.0), + {0, 0x6522df69, 0x71bd078d, (unsigned char*)"Unknown 0x6522df69, 0x71bd078d",}, // Tetris + {0, 0x6522df69, 0x1b0c23a8, (unsigned char*)"Unknown 0x6522df69, 0x1b0c23a8",}, // Pachinko Nichi + + // GBI1 + + {1, 0x45ca328e, 0x45ca328e, (unsigned char*)"RSP Gfx ucode F3DLX 0.95 Yoshitaka Yasumoto Nintendo.",}, // Mario Kart 64, + {1, 0x98e3b909, 0x98e3b909, (unsigned char*)"RSP Gfx ucode F3DEX 0.95 Yoshitaka Yasumoto Nintendo.",}, // Mario Kart 64 + {1, 0x5d446090, 0x5d446090, (unsigned char*)"RSP Gfx ucode F3DLP.Rej 0.96 Yoshitaka Yasumoto Nintendo.",0,1}, // Jikkyou J. League Perfect Striker, + {1, 0x244f5ca3, 0x244f5ca3, (unsigned char*)"RSP Gfx ucode F3DEX 1.00 Yoshitaka Yasumoto Nintendo.",}, // F-1 Pole Position 64, + {1, 0x6a022585, 0x6a022585, (unsigned char*)"RSP Gfx ucode F3DEX.NoN 1.00 Yoshitaka Yasumoto Nintendo.",1}, // Turok - The Dinosaur Hunter (v1.0), + {1, 0x150706be, 0x150706be, (unsigned char*)"RSP Gfx ucode F3DLX.NoN 1.00 Yoshitaka Yasumoto Nintendo.",1}, // Extreme-G, + {1, 0x503f2c53, 0x503f2c53, (unsigned char*)"RSP Gfx ucode F3DEX.NoN 1.21 Yoshitaka Yasumoto Nintendo.",1}, // Bomberman 64, + {1, 0xc705c37c, 0xc705c37c, (unsigned char*)"RSP Gfx ucode F3DLX 1.21 Yoshitaka Yasumoto Nintendo.",}, // Fighting Force 64, Wipeout 64 + {1, 0xa2146075, 0xa2146075, (unsigned char*)"RSP Gfx ucode F3DLX.NoN 1.21 Yoshitaka Yasumoto Nintendo.",1}, // San Francisco Rush - Extreme Racing, + {1, 0xb65aa2da, 0xb65aa2da, (unsigned char*)"RSP Gfx ucode L3DEX 1.21 Yoshitaka Yasumoto Nintendo.",}, // Wipeout 64, + {1, 0x0c8e5ec9, 0x0c8e5ec9, (unsigned char*)"RSP Gfx ucode F3DEX 1.21 Yoshitaka Yasumoto Nintendo.",}, // + {1, 0xe30795f2, 0xa53df3c4, (unsigned char*)"RSP Gfx ucode F3DLP.Rej 1.21 Yoshitaka Yasumoto Nintendo.",0,1}, + + {1, 0xaebeda7d, 0xaebeda7d, (unsigned char*)"RSP Gfx ucode F3DLX.Rej 1.21 Yoshitaka Yasumoto Nintendo.",0,1}, // Jikkyou World Soccer 3, + {1, 0x0c8e5ec9, 0x0c8e5ec9, (unsigned char*)"RSP Gfx ucode F3DEX 1.23 Yoshitaka Yasumoto Nintendo" ,}, // Wave Race 64 (Rev. 2) - Shindou Rumble Edition (JAP) + {1, 0xc705c37c, 0xc705c37c, (unsigned char*)"RSP Gfx ucode F3DLX 1.23 Yoshitaka Yasumoto Nintendo.",}, // GT + {1, 0x2a61350d, 0x2a61350d, (unsigned char*)"RSP Gfx ucode F3DLX 1.23 Yoshitaka Yasumoto Nintendo.",}, // Toy Story2 + {1, 0x0c8e5ec9, 0x0c8e5ec9, (unsigned char*)"RSP Gfx ucode F3DEX 1.23 Yoshitaka Yasumoto Nintendo.",}, // Wave Race 64 Shindou Edition + {12,0xfc6529aa, 0xfc6529aa, (unsigned char*)"RSP Gfx ucode F3DEX 1.23 Yoshitaka Yasumoto Nintendo.",}, // Superman - The Animated Series, + {1, 0xa56cf996, 0xa56cf996, (unsigned char*)"RSP Gfx ucode L3DEX 1.23 Yoshitaka Yasumoto Nintendo.",}, // Flying Dragon, + {1, 0xcc83b43f, 0xcc83b43f, (unsigned char*)"RSP Gfx ucode F3DEX.NoN 1.23 Yoshitaka Yasumoto Nintendo.",1}, // AeroGauge, + {1, 0xca8927a0, 0xca8927a0, (unsigned char*)"RSP Gfx ucode F3DLX.Rej 1.23 Yoshitaka Yasumoto Nintendo.",0,1}, // Puzzle Bobble 64, + {1, 0x25689c75, 0xbe481ae8, (unsigned char*)"RSP Gfx ucode F3DLP.Rej 1.23 Yoshitaka Yasumoto Nintendo.",0,1}, + {1, 0xd2d747b7, 0xd2d747b7, (unsigned char*)"RSP Gfx ucode F3DLX.NoN 1.23 Yoshitaka Yasumoto Nintendo.",1}, // Penny Racers, + {1, 0xa849c858, 0x5bd32b5a, (unsigned char*)"RSP Gfx ucode F3DTEX/A 1.23 Yoshitaka Yasumoto Nintendo.",}, // Tamagotchi + + {7, 0xecd8b772, 0xecd8b772, (unsigned char*)"RSP Gfx ucode S2DEX 1.06 Yoshitaka Yasumoto Nintendo.",}, // Yoshi's Story, + {7, 0xf59132f5, 0xf59132f5, (unsigned char*)"RSP Gfx ucode S2DEX 1.07 Yoshitaka Yasumoto Nintendo.",}, // Bakuretsu Muteki Bangaioh, + {7, 0x961dd811, 0x961dd811, (unsigned char*)"RSP Gfx ucode S2DEX 1.03 Yoshitaka Yasumoto Nintendo.",}, // GT + + {5, 0x3e083afa, 0x722f97cc, (unsigned char*)"RSP Gfx ucode F3DEX.NoN fifo 2.03 Yoshitaka Yasumoto 1998 Nintendo.",1}, // F-Zero X, + {5, 0xa8050bd1, 0xa8050bd1, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.03 Yoshitaka Yasumoto 1998 Nintendo.",}, // F-Zero X, + {5, 0x4e8055f0, 0x4e8055f0, (unsigned char*)"RSP Gfx ucode F3DLX.Rej fifo 2.03 Yoshitaka Yasumoto 1998 Nintendo.",0,1}, // F-Zero X, + {5, 0xabf001f5, 0xabf001f5, (unsigned char*)"RSP Gfx ucode F3DFLX.Rej fifo 2.03F Yoshitaka Yasumoto 1998 Nintendo.",0,1}, // F-Zero X, + {5, 0xadb4b686, 0xadb4b686, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.04 Yoshitaka Yasumoto 1998 Nintendo.",}, // Top Gear Rally 2, + {5, 0x779e2a9b, 0x779e2a9b, (unsigned char*)"RSP Gfx ucode F3DEX.NoN fifo 2.04 Yoshitaka Yasumoto 1998 Nintendo.",1}, // California Speed, + {5, 0xa8cb3e09, 0xa8cb3e09, (unsigned char*)"RSP Gfx ucode L3DEX fifo 2.04 Yoshitaka Yasumoto 1998 Nintendo.",}, // In-Fisherman Bass Hunter 64, + {5, 0x2a1341d6, 0x2a1341d6, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.04H Yoshitaka Yasumoto 1998 Nintendo.",}, // Kirby 64 - The Crystal Shards, + {5, 0x3e083afa, 0x89a8e0ed, (unsigned char*)"RSP Gfx ucode F3DEX.NoN fifo 2.05 Yoshitaka Yasumoto 1998 Nintendo.",1}, // Carmageddon 64 (uncensored), + {5, 0x4964b75d, 0x4964b75d, (unsigned char*)"RSP Gfx ucode F3DEX.NoN fifo 2.05 Yoshitaka Yasumoto 1998 Nintendo.",1}, + {5, 0x39e3e95a, 0x39e3e95a, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.05 Yoshitaka Yasumoto 1998 Nintendo."}, // Knife Edge - Nose Gunner, + {5, 0xd2913522, 0xd2913522, (unsigned char*)"RSP Gfx ucode F3DAM fifo 2.05 Yoshitaka Yasumoto 1998 Nintendo."}, // Hey You, Pikachu!, + {5, 0x3e083afa, 0xc998443f, (unsigned char*)"RSP Gfx ucode F3DEX xbus 2.05 Yoshitaka Yasumoto 1998 Nintendo."}, //Triple play + {5, 0xf4184a7d, 0xf4184a7d, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.06 Yoshitaka Yasumoto 1998 Nintendo.",}, // Hey You, Pikachu!, + {5, 0x595a88de, 0x595a88de, (unsigned char*)"RSP Gfx ucode F3DEX.Rej fifo 2.06 Yoshitaka Yasumoto 1998 Nintendo.",0,1}, // Bio Hazard 2, + {5, 0x0259f764, 0x0259f764, (unsigned char*)"RSP Gfx ucode F3DLX.Rej fifo 2.06 Yoshitaka Yasumoto 1998 Nintendo.",0,1}, // Mario Party, + {5, 0xe1a5477a, 0xe1a5477a, (unsigned char*)"RSP Gfx ucode F3DEX.NoN xbus 2.06 Yoshitaka Yasumoto 1998 Nintendo.",1}, // Command & Conquer, + {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), + {5, 0x2cbd9514, 0x5f40b9f5, (unsigned char*)"RSP Gfx ucode F3DZEX.NoN fifo 2.06H Yoshitaka Yasumoto 1998 Nintendo.",1}, + + {5, 0x3e083afa, 0x882680f4, (unsigned char*)"RSP Gfx ucode L3DEX fifo 2.07 Yoshitaka Yasumoto 1998 Nintendo."}, // Polaris Sno + + {5, 0xdeb1cac0, 0xdeb1cac0, (unsigned char*)"RSP Gfx ucode F3DEX.NoN fifo 2.07 Yoshitaka Yasumoto 1998 Nintendo.",1}, // Knockout Kings 2000, + {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 + {5, 0x4b013e60, 0x4b013e60, (unsigned char*)"RSP Gfx ucode F3DEX xbus 2.07 Yoshitaka Yasumoto 1998 Nintendo.",}, // Lode Runner 3-D, + {5, 0xd1a63836, 0xd1a63836, (unsigned char*)"RSP Gfx ucode L3DEX fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // Hey You, Pikachu!, + {5, 0x97193667, 0x97193667, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // Top Gear Hyper-Bike, + {5, 0x92149ba8, 0x92149ba8, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.08 Yoshitaka Yasumoto/Kawasedo 1999.",}, // Paper Mario, + {5, 0xae0fb88f, 0xae0fb88f, (unsigned char*)"RSP Gfx ucode F3DEX xbus 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // WWF WrestleMania 2000, + {5, 0xc572f368, 0xc572f368, (unsigned char*)"RSP Gfx ucode F3DLX.Rej xbus 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // WWF No Mercy, + {5, 0x3e083afa, 0x74252492, (unsigned char*)"RSP Gfx ucode F3DEX.NoN xbus 2.08 Yoshitaka Yasumoto 1999 Nintendo.",1}, + + {5, 0x9c2edb70, 0xea98e740, (unsigned char*)"RSP Gfx ucode F3DEX.NoN fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",1}, // LEGO Racers, + {5, 0x79e004a6, 0x79e004a6, (unsigned char*)"RSP Gfx ucode F3DLX.Rej fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",0,1}, // Mario Party 2, + {5, 0xaa6ab3ca, 0xaa6ab3ca, (unsigned char*)"RSP Gfx ucode F3DEX.Rej fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",0,1}, // V-Rally Edition 99, + {5, 0x2c597e0f, 0x2c597e0f, (unsigned char*)"RSP Gfx ucode F3DEX fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // Cruis'n Exotica, + {10, 0x4e5f3e3b, 0x4e5f3e3b,(unsigned char*)"RSP Gfx ucode F3DEXBG.NoN fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",1}, // Conker The Bad Fur Day + {5, 0x61f31862, 0x61f31862, (unsigned char*)"RSP Gfx ucode F3DEX.NoN fifo 2.08H Yoshitaka Yasumoto 1999 Nintendo.",1}, // Pokemon Snap, + {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, + + {3, 0x41839d1e, 0x41839d1e, (unsigned char*)"RSP Gfx ucode S2DEX fifo 2.05 Yoshitaka Yasumoto 1998 Nintendo.",}, // Chou Snobow Kids, + {3, 0x2cbd9514, 0xc639dbb9, (unsigned char*)"RSP Gfx ucode S2DEX xbus 2.06 Yoshitaka Yasumoto 1998 Nintendo.",}, + {3, 0xec89e273, 0xec89e273, (unsigned char*)"RSP Gfx ucode S2DEX fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // V-Rally Edition 99, + {3, 0x9429b7d6, 0x9429b7d6, (unsigned char*)"RSP Gfx ucode S2DEX xbus 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // Star Craft, + //{14,0x5a72397b, 0xec89e273, "RSP Gfx ucode S2DEX fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // OgreBattle Background, + {3, 0x2cbd9514, 0xec89e273, (unsigned char*)"RSP Gfx ucode S2DEX fifo 2.08 Yoshitaka Yasumoto 1999 Nintendo.",}, // Zelda MM, + + {6, 0x6aef74f8, 0x6aef74f8, (unsigned char*)"Unknown 0x6aef74f8, 0x6aef74f8",}, // Diddy Kong Racing (v1.0), + {6, 0x4c4eead8, 0x4c4eead8, (unsigned char*)"Unknown 0x4c4eead8, 0x4c4eead8",}, // Diddy Kong Racing (v1.1), + + {1, 0xed421e9a, 0xed421e9a, (unsigned char*)"Unknown 0xed421e9a, 0xed421e9a",}, // Kuiki Uhabi Suigo, + {5, 0x37751932, 0x55c0fd25, (unsigned char*)"Unknown 0x37751932, 0x55c0fd25",}, // Bio Hazard 2, + {11,0xbe0b83e7, 0xbe0b83e7,(unsigned char*)"Unknown 0xbe0b83e7, 0xbe0b83e7",}, // Jet Force Gemini, + + {17, 0x02e882cf, 0x2ad17281, (unsigned char*)"Unknown 0x02e882cf, 0x2ad17281",}, // Indiana Jones, + {17, 0x1f7d9118, 0xdab2199b, (unsigned char*)"Unknown 0x1f7d9118, 0xdab2199b",}, // Battle Naboo, + {17, 0x74583614, 0x74583614, (unsigned char*)"Unknown 0x74583614, 0x74583614",}, // Star Wars - Rogue Squadron, + {17, 0xe37e2f49, 0x1eb63fd8, (unsigned char*)"Unknown 0xe37e2f49, 0x1eb63fd8",}, // Star Wars - Rogue Squadron, + {17, 0x8ce1af3d, 0xb2760ea2, (unsigned char*)"Unknown 0x8ce1af3d, 0xb2760ea2",}, // Star Wars - Rogue Squadron, + + {18, 0x7b685972, 0x57b8095a, (unsigned char*)"Unknown 0x7b685972, 0x57b8095a",}, // World Driver Championship + {18, 0xe92dbb9b, 0x57b8095a, (unsigned char*)"Unknown 0xe92dbb9b, 0x57b8095a",}, // World Driver Championship + {18, 0xe6c9acc1, 0x65f80845, (unsigned char*)"Unknown 0xe6c9acc1, 0x65f80845",}, // World Driver Championship + {18, 0x6522df69, 0x720b88a0, (unsigned char*)"Unknown 0x6522df69, 0x720b88a0",}, // World Driver Championship + {18, 0x6522df69, 0xf1e8ba9e, (unsigned char*)"Unknown 0x6522df69, 0xf1e8ba9e",}, // World Driver Championship + + {19, 0xa486bed3, 0xa486bed3, (unsigned char*)"Unknown 0xa486bed3, 0xa486bed3",}, // Last Legion UX, + {19, 0x6b519381, 0xfebacfd8, (unsigned char*)"Unknown in Toukan Road",}, // I don't know which ucode + + {20, 0x6d2a01b1, 0x6d2a01b1, (unsigned char*)"RSP Gfx ucode ZSortp 0.33 Yoshitaka Yasumoto Nintendo.",}, // Mia Hamm Soccer 64, +}; + +FiddledVtx * g_pVtxBase=NULL; + +SetImgInfo g_TI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 }; +SetImgInfo g_CI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 }; +SetImgInfo g_ZI = { TXT_FMT_RGBA, TXT_SIZE_16b, 1, 0 }; +RenderTextureInfo g_ZI_saves[2]; + +DListStack gDlistStack[MAX_DL_STACK_SIZE]; +int gDlistStackPointer= -1; + +TMEMLoadMapInfo g_tmemLoadAddrMap[0x200]; // Totally 4KB TMEM +TMEMLoadMapInfo g_tmemInfo0; // Info for Tmem=0 +TMEMLoadMapInfo g_tmemInfo1; // Info for Tmem=0x100 + +const char *pszImgSize[4] = {"4", "8", "16", "32"}; +const char *textluttype[4] = {"RGB16", "I16?", "RGBA16", "IA16"}; +uint16 g_wRDPTlut[0x200]; +uint32 g_dwRDPPalCrc[16]; + +#include "FrameBuffer.h" +#include "RSP_GBI0.h" +#include "RSP_GBI1.h" +#include "RSP_GBI2.h" +#include "RSP_GBI2_ext.h" +#include "RSP_GBI_Others.h" +#include "RSP_GBI_Sprite2D.h" +#include "RDP_Texture.h" + +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// +// Init and Reset // +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// + +void DLParser_Init() +{ + int i; + + status.gRDPTime = 0; + status.gDlistCount = 0; + status.gUcodeCount = 0; + status.frameReadByCPU = FALSE; + status.frameWriteByCPU = FALSE; + status.SPCycleCount = 0; + status.DPCycleCount = 0; + status.bN64IsDrawingTextureBuffer = false; + status.bDirectWriteIntoRDRAM = false; + status.bHandleN64RenderTexture = false; + + status.bUcodeIsKnown = FALSE; + status.lastPurgeTimeTime = status.gRDPTime; + + status.curRenderBuffer = 0; + status.curDisplayBuffer = 0; + status.curVIOriginReg = 0; + + status.primitiveType = PRIM_TRI1; + + status.lastPurgeTimeTime = 0; // Time textures were last purged + + status.UseLargerTile[0] = false; + status.LargerTileRealLeft[0] = status.LargerTileRealLeft[1] = 0; + memset(&g_ZI_saves, 0, sizeof(RenderTextureInfo)*2); + + for( i=0; i<8; i++ ) + { + memset(&gRDP.tiles[i], 0, sizeof(Tile)); + } + memset(g_tmemLoadAddrMap, 0, sizeof(g_tmemLoadAddrMap)); + + for( i=0; iCloseRenderTexture(false); + } +} + +void RDP_SetUcodeMap(int ucode) +{ + status.bUseModifiedUcodeMap = false; + switch( ucode ) + { + case 0: // Mario and demos + break; + case 1: // F3DEX GBI1 + case 20: + break; + case 2: // Golden Eye + memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap)); + //LoadedUcodeMap[9]=RSP_GBI1_Sprite2DBase; + //LoadedUcodeMap[0xaf]=RSP_GBI1_LoadUCode; + //LoadedUcodeMap[0xb0]=RSP_GBI1_BranchZ; + LoadedUcodeMap[0xb4]=DLParser_RDPHalf_1_0xb4_GoldenEye; + status.bUseModifiedUcodeMap = true; + break; + case 3: // S2DEX GBI2 + break; + case 4: + memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap)); + LoadedUcodeMap[4]=RSP_Vtx_WRUS; + LoadedUcodeMap[0xb1]=RSP_GBI1_Tri2; + //LoadedUcodeMap[9]=RSP_GBI1_Sprite2DBase; + //LoadedUcodeMap[0xaf]=RSP_GBI1_LoadUCode; + //LoadedUcodeMap[0xb0]=RSP_GBI1_BranchZ; + //LoadedUcodeMap[0xb2]=RSP_GBI1_ModifyVtx; + status.bUseModifiedUcodeMap = true; + break; + case 5: // F3DEX GBI2 + break; + case 6: // DKR, Jet Force Gemini, Mickey + case 11: // DKR, Jet Force Gemini, Mickey + memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap)); + LoadedUcodeMap[1]=RSP_Mtx_DKR; + LoadedUcodeMap[4]=RSP_Vtx_DKR; + if( ucode == 11 ) LoadedUcodeMap[4]=RSP_Vtx_Gemini; + LoadedUcodeMap[5]=RSP_DMA_Tri_DKR; + LoadedUcodeMap[7]=RSP_DL_In_MEM_DKR; + LoadedUcodeMap[0xbc]=RSP_MoveWord_DKR; + LoadedUcodeMap[0xbf]=DLParser_Set_Addr_Ucode6; + //LoadedUcodeMap[9]=RSP_GBI1_Sprite2DBase; + //LoadedUcodeMap[0xb0]=RSP_GBI1_BranchZ; + //LoadedUcodeMap[0xb2]=RSP_GBI1_ModifyVtx; + status.bUseModifiedUcodeMap = true; + break; + case 7: // S2DEX GBI1 + break; + case 8: // Ucode 0 with Sprite2D, Puzzle Master 64 + memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap)); + LoadedUcodeMap[RSP_SPRITE2D_BASE] = RSP_GBI_Sprite2D_PuzzleMaster64; + LoadedUcodeMap[RSP_SPRITE2D_SCALEFLIP] = RSP_GBI1_Sprite2DScaleFlip; + LoadedUcodeMap[RSP_SPRITE2D_DRAW] = RSP_GBI0_Sprite2DDraw; + status.bUseModifiedUcodeMap = true; + break; + case 9: // Perfect Dark + memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap)); + LoadedUcodeMap[4]=RSP_Vtx_PD; + LoadedUcodeMap[7]=RSP_Set_Vtx_CI_PD; + LoadedUcodeMap[0xb1]=RSP_Tri4_PD; + LoadedUcodeMap[0xb4]=DLParser_RDPHalf_1_0xb4_GoldenEye; + status.bUseModifiedUcodeMap = true; + break; + case 10: // Conker BFD + memcpy( &LoadedUcodeMap, &ucodeMap5, sizeof(UcodeMap)); + LoadedUcodeMap[1]=RSP_Vtx_Conker; + LoadedUcodeMap[0x10]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x11]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x12]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x13]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x14]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x15]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x16]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x17]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x18]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x19]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x1a]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x1b]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x1c]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x1d]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x1e]=DLParser_Tri4_Conker; + LoadedUcodeMap[0x1f]=DLParser_Tri4_Conker; + LoadedUcodeMap[0xdb]=DLParser_MoveWord_Conker; + LoadedUcodeMap[0xdc]=DLParser_MoveMem_Conker; + status.bUseModifiedUcodeMap = true; + break; + case 12: // Silicon Velley, Space Station + memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap)); + LoadedUcodeMap[0x01]=RSP_GBI0_Mtx; + status.bUseModifiedUcodeMap = true; + break; + case 13: // modified S2DEX + memcpy( &LoadedUcodeMap, &ucodeMap7, sizeof(UcodeMap)); + //LoadedUcodeMap[S2DEX_BG_1CYC] = ucodeMap1[S2DEX_BG_1CYC]; + LoadedUcodeMap[S2DEX_OBJ_RECTANGLE] = ucodeMap1[S2DEX_OBJ_RECTANGLE]; + LoadedUcodeMap[S2DEX_OBJ_SPRITE] = ucodeMap1[S2DEX_OBJ_SPRITE]; + //LoadedUcodeMap[S2DEX_OBJ_RENDERMODE] = ucodeMap1[S2DEX_OBJ_RENDERMODE]; + //LoadedUcodeMap[S2DEX_OBJ_RECTANGLE_R] = ucodeMap1[S2DEX_OBJ_RECTANGLE_R]; + LoadedUcodeMap[S2DEX_RDPHALF_0] = ucodeMap1[S2DEX_RDPHALF_0]; + status.bUseModifiedUcodeMap = true; + break; + case 14: // OgreBattle Background + memcpy( &LoadedUcodeMap, &ucodeMap5, sizeof(UcodeMap)); + LoadedUcodeMap[0xda] = DLParser_OgreBatter64BG; + LoadedUcodeMap[0xdc] = RSP_S2DEX_OBJ_MOVEMEM; + status.bUseModifiedUcodeMap = true; + break; + case 15: // Ucode 0 with Sprite2D + memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap)); + LoadedUcodeMap[RSP_SPRITE2D_BASE] = RSP_GBI_Sprite2DBase; + LoadedUcodeMap[RSP_SPRITE2D_SCALEFLIP] = RSP_GBI1_Sprite2DScaleFlip; + LoadedUcodeMap[RSP_SPRITE2D_DRAW] = RSP_GBI0_Sprite2DDraw; + status.bUseModifiedUcodeMap = true; + break; + case 16: // Star War, Shadow Of Empire + memcpy( &LoadedUcodeMap, &ucodeMap0, sizeof(UcodeMap)); + LoadedUcodeMap[4]=RSP_Vtx_ShadowOfEmpire; + status.bUseModifiedUcodeMap = true; + break; + case 17: //Indiana Jones, does not work anyway + memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap)); + LoadedUcodeMap[0]=DLParser_Ucode8_0x0; + //LoadedUcodeMap[1]=RSP_RDP_Nothing; + LoadedUcodeMap[2]=DLParser_RS_Color_Buffer; + LoadedUcodeMap[3]=DLParser_RS_MoveMem; + LoadedUcodeMap[4]=DLParser_RS_Vtx_Buffer; + LoadedUcodeMap[5]=DLParser_Ucode8_0x05; + LoadedUcodeMap[6]=DLParser_Ucode8_DL; + LoadedUcodeMap[7]=DLParser_Ucode8_JUMP; + LoadedUcodeMap[8]=RSP_RDP_Nothing; + LoadedUcodeMap[9]=RSP_RDP_Nothing; + LoadedUcodeMap[10]=RSP_RDP_Nothing; + LoadedUcodeMap[11]=RSP_RDP_Nothing; + LoadedUcodeMap[0x80]=DLParser_RS_Block; + LoadedUcodeMap[0xb4]=DLParser_Ucode8_0xb4; + LoadedUcodeMap[0xb5]=DLParser_Ucode8_0xb5; + LoadedUcodeMap[0xb8]=DLParser_Ucode8_EndDL; + LoadedUcodeMap[0xbc]=DLParser_Ucode8_0xbc; + LoadedUcodeMap[0xbd]=DLParser_Ucode8_0xbd; + LoadedUcodeMap[0xbe]=DLParser_RS_0xbe; + LoadedUcodeMap[0xbF]=DLParser_Ucode8_0xbf; + LoadedUcodeMap[0xe4]=DLParser_TexRect_Last_Legion; + status.bUseModifiedUcodeMap = true; + break; + case 18: // World Driver Championship + memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap)); + LoadedUcodeMap[0xe]=DLParser_RSP_DL_WorldDriver; + LoadedUcodeMap[0x2]=DLParser_RSP_Pop_DL_WorldDriver; + LoadedUcodeMap[0xdf]=DLParser_RSP_Pop_DL_WorldDriver; + LoadedUcodeMap[0x6]=RSP_RDP_Nothing; + status.bUseModifiedUcodeMap = true; + break; + case 19: // Last Legion UX + memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap)); + LoadedUcodeMap[0x80]=DLParser_RSP_Last_Legion_0x80; + LoadedUcodeMap[0x00]=DLParser_RSP_Last_Legion_0x00; + LoadedUcodeMap[0xe4]=DLParser_TexRect_Last_Legion; + status.bUseModifiedUcodeMap = true; + break; + default: + memcpy( &LoadedUcodeMap, &ucodeMap5, sizeof(UcodeMap)); + status.bUseModifiedUcodeMap = true; + break; + } + +#ifdef DEBUGGER + if( logMicrocode ) + TRACE1("Using ucode %d", ucode); +#endif +} + +void RSP_SetUcode(int ucode, uint32 ucStart, uint32 ucDStart, uint32 ucSize) +{ + if( status.ucodeHasBeenSet && gRSP.ucode == ucode ) + return; + + status.ucodeHasBeenSet = true; + + if( ucode < 0 ) + ucode = 5; + + RDP_SetUcodeMap(ucode); + if( status.bUseModifiedUcodeMap ) + { + currentUcodeMap = &LoadedUcodeMap[0]; + } + else + { + currentUcodeMap = *ucodeMaps[ucode]; + } + + gRSP.vertexMult = vertexMultVals[ucode]; + + //if( gRSP.ucode != ucode ) DebuggerAppendMsg("Set to ucode: %d", ucode); + gRSP.ucode = ucode; + + lastUcodeInfo.used = true; + if( ucStart == 0 ) + { + lastUcodeInfo.ucStart = g_pOSTask->t.ucode; + lastUcodeInfo.ucDStart = g_pOSTask->t.ucode_data; + lastUcodeInfo.ucSize = g_pOSTask->t.ucode_size; + } + else + { + lastUcodeInfo.ucStart = ucStart; + lastUcodeInfo.ucDStart = ucDStart; + lastUcodeInfo.ucSize = ucSize; + } +} + +//***************************************************************************** +// +//***************************************************************************** +static uint32 DLParser_IdentifyUcodeFromString( const unsigned char * str_ucode ) +{ + const unsigned char str_ucode0[] = "RSP SW Version: 2.0"; + const unsigned char str_ucode1[] = "RSP Gfx ucode "; + + if ( strncasecmp( (char*)str_ucode, (char*)str_ucode0, strlen((char*)str_ucode0) ) == 0 ) + { + return 0; + } + + if ( strncasecmp( (char*)str_ucode, (char*)str_ucode1, strlen((char*)str_ucode1) ) == 0 ) + { + if( strstr((char*)str_ucode,"1.") != 0 ) + { + if( strstr((char*)str_ucode,"S2DEX") != 0 ) + { + return 7; + } + else + return 1; + } + else if( strstr((char*)str_ucode,"2.") != 0 ) + { + if( strstr((char*)str_ucode,"S2DEX") != 0 ) + { + return 3; + } + else + return 5; + } + } + + return 5; +} + +//***************************************************************************** +// +//***************************************************************************** +static uint32 DLParser_IdentifyUcode( uint32 crc_size, uint32 crc_800, char* str ) +{ + for ( uint32 i = 0; i < sizeof(g_UcodeData)/sizeof(UcodeData); i++ ) + { +#ifdef DEBUGGER + if ( crc_800 == g_UcodeData[i].crc_800 ) + { + if( strlen(str)==0 || strcmp((const char *) g_UcodeData[i].ucode_name, str) == 0 ) + { + TRACE0((const char *) g_UcodeData[i].ucode_name); + } + else + { + DebuggerAppendMsg("Incorrect description for this ucode:\n%x, %x, %s",crc_800, crc_size, str); + } + status.bUcodeIsKnown = TRUE; + gRSP.bNearClip = !g_UcodeData[i].non_nearclip; + gRSP.bRejectVtx = g_UcodeData[i].reject; + DebuggerAppendMsg("Identify ucode = %d, crc = %08X, %s", g_UcodeData[i].ucode, crc_800, str); + return g_UcodeData[i].ucode; + } +#else + if ( crc_800 == g_UcodeData[i].crc_800 ) + { + status.bUcodeIsKnown = TRUE; + gRSP.bNearClip = !g_UcodeData[i].non_nearclip; + gRSP.bRejectVtx = g_UcodeData[i].reject; + return g_UcodeData[i].ucode; + } +#endif + } + +#ifdef DEBUGGER + { + static bool warned = false; + if( warned == false ) + { + warned = true; + TRACE0("Can not identify ucode for this game"); + } + } +#endif + gRSP.bNearClip = false; + gRSP.bRejectVtx = false; + status.bUcodeIsKnown = FALSE; + return ~0; +} + +uint32 DLParser_CheckUcode(uint32 ucStart, uint32 ucDStart, uint32 ucSize, uint32 ucDSize) +{ + if( options.enableHackForGames == HACK_FOR_ROGUE_SQUADRON ) + { + return 17; + } + + // Check the used ucode table first + int usedUcodeIndex = 0; + for( usedUcodeIndex=0; (unsigned int)usedUcodeIndex= ' ') + { + *p++ = g_pRDRAMs8[ base + (i ^ 3) ]; + i++; + } + *p++ = 0; + break; + } + } + } + + //if ( strcmp( str, gLastMicrocodeString ) != 0 ) + { + //uint32 size = ucDSize; + base = ucStart & 0x1fffffff; + + uint32 crc_size = ComputeCRC32( 0, &g_pRDRAMu8[ base ], 8);//size ); + uint32 crc_800 = ComputeCRC32( 0, &g_pRDRAMu8[ base ], 0x800 ); + uint32 ucode; + ucode = DLParser_IdentifyUcode( crc_size, crc_800, (char*)str ); + if ( (int)ucode == ~0 ) + { +#ifdef DEBUGGER + static bool warned=false; + //if( warned == false ) + { + char message[300]; + + sprintf(message, "Unable to find ucode to use for '%s' CRCSize: 0x%08x CRC800: 0x%08x", + str, crc_size, crc_800); + TRACE0(message); + DebugMessage(M64MSG_ERROR, message); + warned = true; + } +#endif + ucode = DLParser_IdentifyUcodeFromString(str); + if ( (int)ucode == ~0 ) + { + ucode=5; + } + } + + //DLParser_SetuCode( ucode ); + +#ifdef DEBUGGER + { + static bool warned=false; + if( warned == false ) + { + warned = true; + if( strlen((char *) str) == 0 ) + DebuggerAppendMsg("Can not find RSP string in the DLIST, CRC800: 0x%08x, CRCSize: 0x%08x", crc_800, crc_size); + else + TRACE0((char *) str); + } + } +#endif + strcpy( (char*)gLastMicrocodeString, (char*)str ); + + if( usedUcodeIndex >= MAX_UCODE_INFO ) + { + usedUcodeIndex = rand()%MAX_UCODE_INFO; + } + + UsedUcodes[usedUcodeIndex].ucStart = ucStart; + UsedUcodes[usedUcodeIndex].ucSize = ucSize; + UsedUcodes[usedUcodeIndex].ucDStart = ucDStart; + UsedUcodes[usedUcodeIndex].ucDSize = ucDSize; + UsedUcodes[usedUcodeIndex].ucode = ucode; + UsedUcodes[usedUcodeIndex].crc_800 = crc_800; + UsedUcodes[usedUcodeIndex].crc_size = crc_size; + UsedUcodes[usedUcodeIndex].used = true; + strcpy( UsedUcodes[usedUcodeIndex].rspstr, (char*)str ); + + TRACE2("New ucode has been detected:\n%s, ucode=%d", str, ucode); + + return ucode; + } +} + +extern int dlistMtxCount; +extern bool bHalfTxtScale; + +extern float mspervi; +extern float numvi; +static int skipframe=0; +static unsigned int oldtick=0; +static int oldskip=0; + +void DLParser_Process(OSTask * pTask) +{ + //BOOL menuWaiting = FALSE; + + dlistMtxCount = 0; + bHalfTxtScale = false; + + if ( CRender::g_pRender == NULL) + { + TriggerDPInterrupt(); + TriggerSPInterrupt(); + return; + } + + status.bScreenIsDrawn = true; + unsigned int newtick=0; + bool skipping; + static int count = 0; + if( options.bSkipFrame ) + { + skipping=false; + newtick = SDL_GetTicks(); + if (newtick-oldtick>400 || skipframe>4 || numvi==0) { + oldtick=newtick; // too long frame delay, something must have gone wrong + skipping=false; + } else + if ((float)(newtick-oldtick)>=mspervi*numvi+3.0f) { + skipping=true; +/* +if (count<20) +printf("skipframe=%i, newtick-oldtick=%u (%f), mspervi=%f, numvi=%f\n", skipframe, newtick-oldtick, mspervi*numvi+2.0f, mspervi, numvi); +if (++count>2000) count=0; +*/ + } + // don't jump frameskipping... + if (skipping) { + //want to skip, be progress slowly... + if (skipframe>oldskip+1) + skipping = false; + }/* else { + //don't want to skip, but do it slowly too + if (skipframeCheckRenderTextureCRCInRDRAM(); + } + + g_pOSTask = pTask; + + DebuggerPauseCountN( NEXT_DLIST ); + status.gRDPTime = (uint32) SDL_GetTicks(); + + status.gDlistCount++; + + if ( lastUcodeInfo.ucStart != (uint32)(pTask->t.ucode) ) + { + uint32 ucode = DLParser_CheckUcode(pTask->t.ucode, pTask->t.ucode_data, pTask->t.ucode_size, pTask->t.ucode_data_size); + RSP_SetUcode(ucode, pTask->t.ucode, pTask->t.ucode_data, pTask->t.ucode_size); + DEBUGGER_PAUSE_AND_DUMP(NEXT_SWITCH_UCODE,{DebuggerAppendMsg("Pause at switching ucode");}); + } + + // Initialize stack + status.bN64FrameBufferIsUsed = false; + gDlistStackPointer=0; + gDlistStack[gDlistStackPointer].pc = (uint32)pTask->t.data_ptr; + gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT; + DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((gDlistStack[gDlistStackPointer].pc == 0 && pauseAtNext && eventToPause==NEXT_UNKNOWN_OP), + {DebuggerAppendMsg("Start Task without DLIST: ucode=%08X, data=%08X", (uint32)pTask->t.ucode, (uint32)pTask->t.ucode_data);}); + + + // Check if we need to purge (every 5 milliseconds) /*SEB maybe that's too frequent. Let's change 5 by 2*1000 = 2sec !*/ + if (status.gRDPTime - status.lastPurgeTimeTime > 5) + { + gTextureManager.PurgeOldTextures(); + status.lastPurgeTimeTime = status.gRDPTime; + } + + status.dwNumDListsCulled = 0; + status.dwNumTrisRendered = 0; + status.dwNumTrisClipped = 0; + status.dwNumVertices = 0; + status.dwBiggestVertexIndex = 0; + + if( g_curRomInfo.bForceScreenClear && CGraphicsContext::needCleanScene ) + { + CRender::g_pRender->ClearBuffer(true,true); + CGraphicsContext::needCleanScene = false; + } + + SetVIScales(); + CRender::g_pRender->RenderReset(); + CRender::g_pRender->BeginRendering(); + CRender::g_pRender->SetViewport(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, 0x3FF); + CRender::g_pRender->SetFillMode(options.bWinFrameMode? RICE_FILLMODE_WINFRAME : RICE_FILLMODE_SOLID); + + try + { + // The main loop + while( gDlistStackPointer >= 0 ) + { +#ifdef DEBUGGER + DEBUGGER_PAUSE_COUNT_N(NEXT_UCODE); + if( debuggerPause ) + { + DebuggerPause(); + CRender::g_pRender->SetFillMode(options.bWinFrameMode? RICE_FILLMODE_WINFRAME : RICE_FILLMODE_SOLID); + } + + if (gDlistStack[gDlistStackPointer].pc > g_dwRamSize) + { + DebuggerAppendMsg("Error: dwPC is %08X", gDlistStack[gDlistStackPointer].pc ); + break; + } +#endif + + status.gUcodeCount++; + + Gfx *pgfx = (Gfx*)&g_pRDRAMu32[(gDlistStack[gDlistStackPointer].pc>>2)]; +#ifdef DEBUGGER + LOG_UCODE("0x%08x: %08x %08x %-10s", + 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)]); +#endif + gDlistStack[gDlistStackPointer].pc += 8; + currentUcodeMap[pgfx->words.w0 >>24](pgfx); + + if ( gDlistStackPointer >= 0 && --gDlistStack[gDlistStackPointer].countdown < 0 ) + { + LOG_UCODE("**EndDLInMem"); + gDlistStackPointer--; + } + } + + } + catch(...) + { + TRACE0("Unknown exception happens in ProcessDList"); + TriggerDPInterrupt(); + } + + CRender::g_pRender->EndRendering(); + + + if( gRSP.ucode >= 17) + TriggerDPInterrupt(); + TriggerSPInterrupt(); +} + +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// +// Util Functions // +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// + +void RDP_NOIMPL_Real(const char* op, uint32 word0, uint32 word1) +{ +#ifdef DEBUGGER + if( logWarning ) + { + TRACE0("Stack Trace"); + for( int i=0; iSetCullMode(bCullFront, bCullBack); + + BOOL bShade = (gRDP.geometryMode & G_SHADE) ? TRUE : FALSE; + BOOL bShadeSmooth = (gRDP.geometryMode & G_SHADING_SMOOTH) ? TRUE : FALSE; + if (bShade && bShadeSmooth) CRender::g_pRender->SetShadeMode( SHADE_SMOOTH ); + else CRender::g_pRender->SetShadeMode( SHADE_FLAT ); + + CRender::g_pRender->SetFogEnable( gRDP.geometryMode & G_FOG ? true : false ); + SetTextureGen((gRDP.geometryMode & G_TEXTURE_GEN) ? true : false ); + SetLighting( (gRDP.geometryMode & G_LIGHTING ) ? true : false ); + CRender::g_pRender->ZBufferEnable( gRDP.geometryMode & G_ZBUFFER ); +} + +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// +// DP Ucodes // +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// + +void DLParser_SetKeyGB(Gfx *gfx) +{ + DP_Timing(DLParser_SetKeyGB); + + gRDP.keyB = ((gfx->words.w1)>>8)&0xFF; + gRDP.keyG = ((gfx->words.w1)>>24)&0xFF; + gRDP.keyA = (gRDP.keyR+gRDP.keyG+gRDP.keyB)/3; + gRDP.fKeyA = gRDP.keyA/255.0f; +} +void DLParser_SetKeyR(Gfx *gfx) +{ + DP_Timing(DLParser_SetKeyR); + + gRDP.keyR = ((gfx->words.w1)>>8)&0xFF; + gRDP.keyA = (gRDP.keyR+gRDP.keyG+gRDP.keyB)/3; + gRDP.fKeyA = gRDP.keyA/255.0f; +} + +int g_convk0,g_convk1,g_convk2,g_convk3,g_convk4,g_convk5; +float g_convc0,g_convc1,g_convc2,g_convc3,g_convc4,g_convc5; +void DLParser_SetConvert(Gfx *gfx) +{ + DP_Timing(DLParser_SetConvert); + + int temp; + + temp = ((gfx->words.w0)>>13)&0x1FF; + g_convk0 = temp>0xFF ? -(temp-0x100) : temp; + + temp = ((gfx->words.w0)>>4)&0x1FF; + g_convk1 = temp>0xFF ? -(temp-0x100) : temp; + + temp = (gfx->words.w0)&0xF; + temp = (temp<<5)|(((gfx->words.w1)>>27)&0x1F); + g_convk2 = temp>0xFF ? -(temp-0x100) : temp; + + temp = ((gfx->words.w1)>>18)&0x1FF; + g_convk3 = temp>0xFF ? -(temp-0x100) : temp; + + temp = ((gfx->words.w1)>>9)&0x1FF; + g_convk4 = temp>0xFF ? -(temp-0x100) : temp; + + temp = (gfx->words.w1)&0x1FF; + g_convk5 = temp>0xFF ? -(temp-0x100) : temp; + + g_convc0 = g_convk5/255.0f+1.0f; + g_convc1 = g_convk0/255.0f*g_convc0; + g_convc2 = g_convk1/255.0f*g_convc0; + g_convc3 = g_convk2/255.0f*g_convc0; + g_convc4 = g_convk3/255.0f*g_convc0; +} +void DLParser_SetPrimDepth(Gfx *gfx) +{ + DP_Timing(DLParser_SetPrimDepth); + uint32 dwZ = ((gfx->words.w1) >> 16) & 0xFFFF; + uint32 dwDZ = ((gfx->words.w1) ) & 0xFFFF; + + LOG_UCODE("SetPrimDepth: 0x%08x 0x%08x - z: 0x%04x dz: 0x%04x", + gfx->words.w0, gfx->words.w1, dwZ, dwDZ); + + SetPrimitiveDepth(dwZ, dwDZ); + DEBUGGER_PAUSE(NEXT_SET_PRIM_COLOR); +} + +void DLParser_RDPSetOtherMode(Gfx *gfx) +{ + DP_Timing(DLParser_RDPSetOtherMode); + gRDP.otherMode._u32[1] = (gfx->words.w0); // High + gRDP.otherMode._u32[0] = (gfx->words.w1); // Low + + if( gRDP.otherModeH != ((gfx->words.w0) & 0x0FFFFFFF) ) + { + gRDP.otherModeH = ((gfx->words.w0) & 0x0FFFFFFF); + + uint32 dwTextFilt = (gRDP.otherModeH>>RSP_SETOTHERMODE_SHIFT_TEXTFILT)&0x3; + CRender::g_pRender->SetTextureFilter(dwTextFilt<words.w1) ) + { + if( (gRDP.otherModeL&ZMODE_DEC) != ((gfx->words.w1)&ZMODE_DEC) ) + { + if( ((gfx->words.w1)&ZMODE_DEC) == ZMODE_DEC ) + CRender::g_pRender->SetZBias( 2 ); + else + CRender::g_pRender->SetZBias( 0 ); + } + + gRDP.otherModeL = (gfx->words.w1); + + BOOL bZCompare = (gRDP.otherModeL & Z_COMPARE) ? TRUE : FALSE; + BOOL bZUpdate = (gRDP.otherModeL & Z_UPDATE) ? TRUE : FALSE; + + CRender::g_pRender->SetZCompare( bZCompare ); + CRender::g_pRender->SetZUpdate( bZUpdate ); + + uint32 dwAlphaTestMode = (gRDP.otherModeL >> RSP_SETOTHERMODE_SHIFT_ALPHACOMPARE) & 0x3; + + if ((dwAlphaTestMode) != 0) + CRender::g_pRender->SetAlphaTestEnable( TRUE ); + else + CRender::g_pRender->SetAlphaTestEnable( FALSE ); + } + + uint16 blender = gRDP.otherMode.blender; + RDP_BlenderSetting &bl = *(RDP_BlenderSetting*)(&(blender)); + if( bl.c1_m1a==3 || bl.c1_m2a == 3 || bl.c2_m1a == 3 || bl.c2_m2a == 3 ) + { + gRDP.bFogEnableInBlender = true; + } + else + { + gRDP.bFogEnableInBlender = false; + } +} + + + +void DLParser_RDPLoadSync(Gfx *gfx) +{ + DP_Timing(DLParser_RDPLoadSync); + LOG_UCODE("LoadSync: (Ignored)"); +} + +void DLParser_RDPPipeSync(Gfx *gfx) +{ + DP_Timing(DLParser_RDPPipeSync); + LOG_UCODE("PipeSync: (Ignored)"); +} +void DLParser_RDPTileSync(Gfx *gfx) +{ + DP_Timing(DLParser_RDPTileSync); + LOG_UCODE("TileSync: (Ignored)"); +} + +void DLParser_RDPFullSync(Gfx *gfx) +{ + DP_Timing(DLParser_RDPFullSync); + TriggerDPInterrupt(); +} + +void DLParser_SetScissor(Gfx *gfx) +{ + DP_Timing(DLParser_SetScissor); + + ScissorType tempScissor; + // The coords are all in 8:2 fixed point + tempScissor.x0 = ((gfx->words.w0)>>12)&0xFFF; + tempScissor.y0 = ((gfx->words.w0)>>0 )&0xFFF; + tempScissor.mode = ((gfx->words.w1)>>24)&0x03; + tempScissor.x1 = ((gfx->words.w1)>>12)&0xFFF; + tempScissor.y1 = ((gfx->words.w1)>>0 )&0xFFF; + + tempScissor.left = tempScissor.x0/4; + tempScissor.top = tempScissor.y0/4; + tempScissor.right = tempScissor.x1/4; + tempScissor.bottom = tempScissor.y1/4; + + if( options.bEnableHacks ) + { + if( g_CI.dwWidth == 0x200 && tempScissor.right == 0x200 ) + { + uint32 width = *g_GraphicsInfo.VI_WIDTH_REG & 0xFFF; + + if( width != 0x200 ) + { + // Hack for RE2 + tempScissor.bottom = tempScissor.right*tempScissor.bottom/width; + tempScissor.right = width; + } + + } + } + + if( gRDP.scissor.left != tempScissor.left || gRDP.scissor.top != tempScissor.top || + gRDP.scissor.right != tempScissor.right || gRDP.scissor.bottom != tempScissor.bottom || + gRSP.real_clip_scissor_left != tempScissor.left || gRSP.real_clip_scissor_top != tempScissor.top || + gRSP.real_clip_scissor_right != tempScissor.right || gRSP.real_clip_scissor_bottom != tempScissor.bottom) + { + memcpy(&(gRDP.scissor), &tempScissor, sizeof(ScissorType) ); + if( !status.bHandleN64RenderTexture ) + SetVIScales(); + + if( options.enableHackForGames == HACK_FOR_SUPER_BOWLING && g_CI.dwAddr%0x100 != 0 ) + { + // right half screen + gRDP.scissor.left += 160; + gRDP.scissor.right += 160; + CRender::g_pRender->SetViewport(160, 0, 320, 240, 0xFFFF); + } + + CRender::g_pRender->UpdateClipRectangle(); + CRender::g_pRender->UpdateScissor(); + CRender::g_pRender->SetViewportRender(); + } + + LOG_UCODE("SetScissor: x0=%d y0=%d x1=%d y1=%d mode=%d", + gRDP.scissor.left, gRDP.scissor.top, + gRDP.scissor.right, gRDP.scissor.bottom, + gRDP.scissor.mode); + + ///TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("SetScissor: x0=%d y0=%d x1=%d y1=%d mode=%d", gRDP.scissor.left, gRDP.scissor.top, + //gRDP.scissor.right, gRDP.scissor.bottom, gRDP.scissor.mode);); +} + + +void DLParser_FillRect(Gfx *gfx) +{ + DP_Timing(DLParser_FillRect); // fix me + status.primitiveType = PRIM_FILLRECT; + + if( status.bN64IsDrawingTextureBuffer && frameBufferOptions.bIgnore ) + { + return; + } + + if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS ) + { + uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction + uint32 w2 = *(uint32 *)(g_pRDRAMu8 + dwPC); + if( (w2>>24) == RDP_FILLRECT ) + { + // Mario Tennis, a lot of FillRect ucodes, skip all of them + while( (w2>>24) == RDP_FILLRECT ) + { + dwPC += 8; + w2 = *(uint32 *)(g_pRDRAMu8 + dwPC); + } + + gDlistStack[gDlistStackPointer].pc = dwPC; + return; + } + } + + uint32 x0 = (((gfx->words.w1)>>12)&0xFFF)/4; + uint32 y0 = (((gfx->words.w1)>>0 )&0xFFF)/4; + uint32 x1 = (((gfx->words.w0)>>12)&0xFFF)/4; + uint32 y1 = (((gfx->words.w0)>>0 )&0xFFF)/4; + + // Note, in some modes, the right/bottom lines aren't drawn + + LOG_UCODE(" (%d,%d) (%d,%d)", x0, y0, x1, y1); + + if( gRDP.otherMode.cycle_type >= CYCLE_TYPE_COPY ) + { + x1++; + y1++; + } + + //TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("FillRect: X0=%d, Y0=%d, X1=%d, Y1=%d, Color=0x%08X", x0, y0, x1, y1, gRDP.originalFillColor);); + + if( status.bHandleN64RenderTexture && options.enableHackForGames == HACK_FOR_BANJO_TOOIE ) + { + // Skip this + return; + } + + if (IsUsedAsDI(g_CI.dwAddr)) + { + // Clear the Z Buffer + if( x0!=0 || y0!=0 || windowSetting.uViWidth-x1>1 || windowSetting.uViHeight-y1>1) + { + if( options.enableHackForGames == HACK_FOR_GOLDEN_EYE ) + { + // GoldenEye is using double zbuffer + if( g_CI.dwAddr == g_ZI.dwAddr ) + { + // The zbuffer is the upper screen + COORDRECT rect={int(x0*windowSetting.fMultX),int(y0*windowSetting.fMultY),int(x1*windowSetting.fMultX),int(y1*windowSetting.fMultY)}; + CRender::g_pRender->ClearBuffer(false,true,rect); //Check me + LOG_UCODE(" Clearing ZBuffer"); + } + else + { + // The zbuffer is the lower screen + int h = (g_CI.dwAddr-g_ZI.dwAddr)/g_CI.dwWidth/2; + COORDRECT rect={int(x0*windowSetting.fMultX),int((y0+h)*windowSetting.fMultY),int(x1*windowSetting.fMultX),int((y1+h)*windowSetting.fMultY)}; + CRender::g_pRender->ClearBuffer(false,true,rect); //Check me + LOG_UCODE(" Clearing ZBuffer"); + } + } + else + { + COORDRECT rect={int(x0*windowSetting.fMultX),int(y0*windowSetting.fMultY),int(x1*windowSetting.fMultX),int(y1*windowSetting.fMultY)}; + CRender::g_pRender->ClearBuffer(false,true,rect); //Check me + LOG_UCODE(" Clearing ZBuffer"); + } + } + else + { + CRender::g_pRender->ClearBuffer(false,true); //Check me + LOG_UCODE(" Clearing ZBuffer"); + } + + DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect: ClearZbuffer\n");}); + 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); + DebuggerAppendMsg("Pause after ClearZbuffer: Color=%08X\n", gRDP.originalFillColor);}); + + if( g_curRomInfo.bEmulateClear ) + { + // Emulating Clear, by write the memory in RDRAM + uint16 color = (uint16)gRDP.originalFillColor; + uint32 pitch = g_CI.dwWidth<<1; + long long base = (long long) (g_pRDRAMu8 + g_CI.dwAddr); + for( uint32 i =y0; iActiveTextureBuffer(); + + status.leftRendered = status.leftRendered<0 ? x0 : min((int)x0,status.leftRendered); + status.topRendered = status.topRendered<0 ? y0 : min((int)y0,status.topRendered); + status.rightRendered = status.rightRendered<0 ? x1 : max((int)x1,status.rightRendered); + status.bottomRendered = status.bottomRendered<0 ? y1 : max((int)y1,status.bottomRendered); + + g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,(int)y1); + + if( status.bDirectWriteIntoRDRAM || ( x0==0 && y0==0 && (x1 == g_pRenderTextureInfo->N64Width || x1 == g_pRenderTextureInfo->N64Width-1 ) ) ) + { + if( g_pRenderTextureInfo->CI_Info.dwSize == TXT_SIZE_16b ) + { + uint16 color = (uint16)gRDP.originalFillColor; + uint32 pitch = g_pRenderTextureInfo->N64Width<<1; + long long base = (long long) (g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr); + for( uint32 i =y0; iN64Width; + long long base = (long long) (g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr); + for( uint32 i=y0; iN64Width || x1 == g_pRenderTextureInfo->N64Width-1 ) && gRDP.fillColor == 0) + //{ + // CRender::g_pRender->ClearBuffer(true,false); + //} + //else + { + if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL ) + { + CRender::g_pRender->FillRect(x0, y0, x1, y1, gRDP.fillColor); + } + else + { + COLOR primColor = GetPrimitiveColor(); + CRender::g_pRender->FillRect(x0, y0, x1, y1, primColor); + } + } + } + + DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect\n");}); + 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); + DebuggerAppendMsg("Pause after FillRect: Color=%08X\n", gRDP.originalFillColor);}); + } + else + { + LOG_UCODE(" Filling Rectangle"); + if( frameBufferOptions.bSupportRenderTextures || frameBufferOptions.bCheckBackBufs ) + { + if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer(); + + status.leftRendered = status.leftRendered<0 ? x0 : min((int)x0,status.leftRendered); + status.topRendered = status.topRendered<0 ? y0 : min((int)y0,status.topRendered); + status.rightRendered = status.rightRendered<0 ? x1 : max((int)x1,status.rightRendered); + status.bottomRendered = status.bottomRendered<0 ? y1 : max((int)y1,status.bottomRendered); + } + + if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL ) + { + if( !status.bHandleN64RenderTexture || g_pRenderTextureInfo->CI_Info.dwSize == TXT_SIZE_16b ) + { + CRender::g_pRender->FillRect(x0, y0, x1, y1, gRDP.fillColor); + } + } + else + { + COLOR primColor = GetPrimitiveColor(); + //if( RGBA_GETALPHA(primColor) != 0 ) + { + CRender::g_pRender->FillRect(x0, y0, x1, y1, primColor); + } + } + DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_FLUSH_TRI,{TRACE0("Pause after FillRect\n");}); + 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); + DebuggerAppendMsg("Pause after FillRect: Color=%08X\n", gRDP.originalFillColor);}); + } +} + + +#define STORE_CI {g_CI.dwAddr = dwNewAddr;g_CI.dwFormat = dwFmt;g_CI.dwSize = dwSiz;g_CI.dwWidth = dwWidth;g_CI.bpl=dwBpl;} + +void DLParser_SetCImg(Gfx *gfx) +{ + uint32 dwFmt = gfx->setimg.fmt; + uint32 dwSiz = gfx->setimg.siz; + uint32 dwWidth = gfx->setimg.width + 1; + uint32 dwNewAddr = RSPSegmentAddr((gfx->setimg.addr)) & 0x00FFFFFF ; + uint32 dwBpl = dwWidth << dwSiz >> 1; + + TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", dwNewAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);); + + if( dwFmt == TXT_FMT_YUV || dwFmt == TXT_FMT_IA ) + { + WARNING(TRACE4("Check me: SetCImg Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", + g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth)); + } + + LOG_UCODE(" Image: 0x%08x", RSPSegmentAddr(gfx->words.w1)); + LOG_UCODE(" Fmt: %s Size: %s Width: %d", + pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth); + + if( g_CI.dwAddr == dwNewAddr && g_CI.dwFormat == dwFmt && g_CI.dwSize == dwSiz && g_CI.dwWidth == dwWidth ) + { + TXTRBUF_OR_CI_DETAIL_DUMP({ + TRACE0("Set CIMG to the same address, no change, skipped"); + DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", + g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth); + }); + return; + } + + if( status.bVIOriginIsUpdated == true && currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_1ST_CI_CHANGE ) + { + status.bVIOriginIsUpdated=false; + CGraphicsContext::Get()->UpdateFrame(); + TXTRBUF_OR_CI_DETAIL_DUMP(TRACE0("Screen Update at 1st CI change");); + } + + if( options.enableHackForGames == HACK_FOR_SUPER_BOWLING ) + { + if( dwNewAddr%0x100 == 0 ) + { + if( dwWidth < 320 ) + { + // Left half screen + gRDP.scissor.left = 0; + gRDP.scissor.right = 160; + CRender::g_pRender->SetViewport(0, 0, 160, 240, 0xFFFF); + CRender::g_pRender->UpdateClipRectangle(); + CRender::g_pRender->UpdateScissor(); + } + else + { + gRDP.scissor.left = 0; + gRDP.scissor.right = 320; + CRender::g_pRender->SetViewport(0, 0, 320, 240, 0xFFFF); + CRender::g_pRender->UpdateClipRectangle(); + CRender::g_pRender->UpdateScissor(); + } + } + else + { + // right half screen + gRDP.scissor.left = 160; + gRDP.scissor.right = 320; + gRSP.nVPLeftN = 160; + gRSP.nVPRightN = 320; + CRender::g_pRender->UpdateClipRectangle(); + CRender::g_pRender->UpdateScissor(); + CRender::g_pRender->SetViewport(160, 0, 320, 240, 0xFFFF); + } + } + + + if( !frameBufferOptions.bUpdateCIInfo ) + { + STORE_CI; + status.bCIBufferIsRendered = false; + status.bN64IsDrawingTextureBuffer = false; + + TXTRBUF_DUMP(TRACE4("SetCImg : Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", + g_CI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth)); + + DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG, + { + DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", + dwNewAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth); + } + ); + return; + } + + SetImgInfo newCI; + newCI.bpl = dwBpl; + newCI.dwAddr = dwNewAddr; + newCI.dwFormat = dwFmt; + newCI.dwSize = dwSiz; + newCI.dwWidth = dwWidth; + + g_pFrameBufferManager->Set_CI_addr(newCI); +} + +void DLParser_SetZImg(Gfx *gfx) +{ + DP_Timing(DLParser_SetZImg); + LOG_UCODE(" Image: 0x%08x", RSPSegmentAddr(gfx->words.w1)); + + uint32 dwFmt = gfx->setimg.fmt; + uint32 dwSiz = gfx->setimg.siz; + uint32 dwWidth = gfx->setimg.width + 1; + uint32 dwAddr = RSPSegmentAddr((gfx->setimg.addr)); + + if( dwAddr != g_ZI_saves[0].CI_Info.dwAddr ) + { + g_ZI_saves[1].CI_Info.dwAddr = g_ZI.dwAddr; + g_ZI_saves[1].CI_Info.dwFormat = g_ZI.dwFormat; + g_ZI_saves[1].CI_Info.dwSize = g_ZI.dwSize; + g_ZI_saves[1].CI_Info.dwWidth = g_ZI.dwWidth; + g_ZI_saves[1].updateAtFrame = g_ZI_saves[0].updateAtFrame; + + g_ZI_saves[0].CI_Info.dwAddr = g_ZI.dwAddr = dwAddr; + g_ZI_saves[0].CI_Info.dwFormat = g_ZI.dwFormat = dwFmt; + g_ZI_saves[0].CI_Info.dwSize = g_ZI.dwSize = dwSiz; + g_ZI_saves[0].CI_Info.dwWidth = g_ZI.dwWidth = dwWidth; + g_ZI_saves[0].updateAtFrame = status.gDlistCount; + } + else + { + g_ZI.dwAddr = dwAddr; + g_ZI.dwFormat = dwFmt; + g_ZI.dwSize = dwSiz; + g_ZI.dwWidth = dwWidth; + } + + DEBUGGER_IF_DUMP((pauseAtNext) , + {DebuggerAppendMsg("SetZImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", + g_ZI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth);} + ); + + DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG, + { + DebuggerAppendMsg("Pause after SetZImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", + g_ZI.dwAddr, pszImgFormat[dwFmt], pszImgSize[dwSiz], dwWidth); + } + ); +} + +bool IsUsedAsDI(uint32 addr) +{ + if( addr == g_ZI_saves[0].CI_Info.dwAddr ) + return true; + else if( addr == g_ZI_saves[1].CI_Info.dwAddr && status.gDlistCount - g_ZI_saves[1].updateAtFrame < 10 + && g_ZI_saves[1].CI_Info.dwAddr != 0 ) + return true; + else + return false; +} + +void DLParser_SetCombine(Gfx *gfx) +{ + DP_Timing(DLParser_SetCombine); + uint32 dwMux0 = (gfx->words.w0)&0x00FFFFFF; + uint32 dwMux1 = (gfx->words.w1); + CRender::g_pRender->SetMux(dwMux0, dwMux1); +} + +void DLParser_SetFillColor(Gfx *gfx) +{ + DP_Timing(DLParser_SetFillColor); + gRDP.fillColor = Convert555ToRGBA(gfx->setcolor.fillcolor); + gRDP.originalFillColor = (gfx->setcolor.color); + + LOG_UCODE(" Color5551=0x%04x = 0x%08x", (uint16)gfx->words.w1, gRDP.fillColor); + +} + +void DLParser_SetFogColor(Gfx *gfx) +{ + DP_Timing(DLParser_SetFogColor); + CRender::g_pRender->SetFogColor( gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a ); + FOG_DUMP(TRACE1("Set Fog color: %08X", gfx->setcolor.color)); +} + +void DLParser_SetBlendColor(Gfx *gfx) +{ + DP_Timing(DLParser_SetBlendColor); + CRender::g_pRender->SetAlphaRef(gfx->setcolor.a); +} + + +void DLParser_SetPrimColor(Gfx *gfx) +{ + DP_Timing(DLParser_SetPrimColor); + SetPrimitiveColor( COLOR_RGBA(gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a), + gfx->setcolor.prim_min_level, gfx->setcolor.prim_level); +} + +void DLParser_SetEnvColor(Gfx *gfx) +{ + DP_Timing(DLParser_SetEnvColor); + SetEnvColor( COLOR_RGBA(gfx->setcolor.r, gfx->setcolor.g, gfx->setcolor.b, gfx->setcolor.a) ); +} + + +void RDP_DLParser_Process(void) +{ + status.gRDPTime = (uint32) SDL_GetTicks(); + + status.gDlistCount++; + + uint32 start = *(g_GraphicsInfo.DPC_START_REG); + uint32 end = *(g_GraphicsInfo.DPC_END_REG); + + gDlistStackPointer=0; + gDlistStack[gDlistStackPointer].pc = start; + gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT; + + // Check if we need to purge (every 5 milliseconds) + if (status.gRDPTime - status.lastPurgeTimeTime > 5) + { + gTextureManager.PurgeOldTextures(); + status.lastPurgeTimeTime = status.gRDPTime; + } + + // Lock the graphics context here. + CRender::g_pRender->SetFillMode(RICE_FILLMODE_SOLID); + + SetVIScales(); + + CRender::g_pRender->RenderReset(); + CRender::g_pRender->BeginRendering(); + CRender::g_pRender->SetViewport(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, 0x3FF); + + while( gDlistStack[gDlistStackPointer].pc < end ) + { + Gfx *pgfx = (Gfx*)&g_pRDRAMu32[(gDlistStack[gDlistStackPointer].pc>>2)]; + gDlistStack[gDlistStackPointer].pc += 8; + currentUcodeMap[pgfx->words.w0 >>24](pgfx); + } + + CRender::g_pRender->EndRendering(); +} + +void RDP_TriFill(Gfx *gfx) +{ +} + +void RDP_TriFillZ(Gfx *gfx) +{ +} + +void RDP_TriTxtr(Gfx *gfx) +{ +} + +void RDP_TriTxtrZ(Gfx *gfx) +{ +} + +void RDP_TriShade(Gfx *gfx) +{ +} + +void RDP_TriShadeZ(Gfx *gfx) +{ +} + +void RDP_TriShadeTxtr(Gfx *gfx) +{ +} + +void RDP_TriShadeTxtrZ(Gfx *gfx) +{ +} + +static int crc_table_empty = 1; +static unsigned int crc_table[256]; +static void make_crc_table(void); + +static void make_crc_table() +{ + unsigned int c; + int n, k; + unsigned int poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const uint8 p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; (unsigned int)n < sizeof(p)/sizeof(uint8); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (unsigned int)n; + for (k = 0; k < 8; k++) + c = (c & 1) ? (poly ^ (c >> 1)) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +unsigned int ComputeCRC32(unsigned int crc, const uint8 *buf, unsigned int len) +{ + if (buf == NULL) + return 0L; + + if (crc_table_empty) + make_crc_table(); + + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} + +Matrix matToLoad; +void LoadMatrix(uint32 addr) +{ + const float fRecip = 1.0f / 65536.0f; + if (addr + 64 > g_dwRamSize) + { + TRACE1("Mtx: Address invalid (0x%08x)", addr); + return; + } + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + int hi = *(short *)(g_pRDRAMu8 + ((addr+(i<<3)+(j<<1) )^0x2)); + int lo = *(unsigned short *)(g_pRDRAMu8 + ((addr+(i<<3)+(j<<1) + 32)^0x2)); + matToLoad.m[i][j] = (float)((hi<<16) | lo) * fRecip; + } + } + + +#ifdef DEBUGGER + LOG_UCODE( + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n" + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n" + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n" + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n", + matToLoad.m[0][0], matToLoad.m[0][1], matToLoad.m[0][2], matToLoad.m[0][3], + matToLoad.m[1][0], matToLoad.m[1][1], matToLoad.m[1][2], matToLoad.m[1][3], + matToLoad.m[2][0], matToLoad.m[2][1], matToLoad.m[2][2], matToLoad.m[2][3], + matToLoad.m[3][0], matToLoad.m[3][1], matToLoad.m[3][2], matToLoad.m[3][3]); +#endif // DEBUGGER +} +