| 1 | /****************************************************************************** |
| 2 | * Arachnoid Graphics Plugin for Mupen64Plus |
| 3 | * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/ |
| 4 | * |
| 5 | * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU General Public License |
| 9 | * as published by the Free Software Foundation; either version 2 |
| 10 | * of the License, or (at your option) any later version. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License |
| 18 | * along with this program; if not, write to the Free Software |
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 20 | *****************************************************************************/ |
| 21 | |
| 22 | #include "GBI.h" |
| 23 | #include "GBIDefs.h" |
| 24 | #include "RSP.h" |
| 25 | #include "RDP.h" |
| 26 | #include "UCodeSelector.h" |
| 27 | #include "UCodeIdentificationData.h" |
| 28 | #include "OpenGLManager.h" |
| 29 | #include "Logger.h" |
| 30 | #include "m64p.h" |
| 31 | |
| 32 | //----------------------------------------------------------------------------- |
| 33 | //! Static Variables |
| 34 | //----------------------------------------------------------------------------- |
| 35 | unsigned int GBI::G_MOVEMEM, GBI::G_MOVEWORD; |
| 36 | unsigned int GBI::G_RDPHALF_1, GBI::G_RDPHALF_2, GBI::G_RDPHALF_CONT; |
| 37 | unsigned int GBI::G_SPNOOP; |
| 38 | unsigned int GBI::G_SETOTHERMODE_H, GBI::G_SETOTHERMODE_L; |
| 39 | unsigned int GBI::G_DL, GBI::G_ENDDL, GBI::G_CULLDL, GBI::G_BRANCH_Z; |
| 40 | unsigned int GBI::G_LOAD_UCODE; |
| 41 | |
| 42 | unsigned int GBI::G_MTX, GBI::G_POPMTX; |
| 43 | unsigned int GBI::G_GEOMETRYMODE, GBI::G_SETGEOMETRYMODE, GBI::G_CLEARGEOMETRYMODE; |
| 44 | unsigned int GBI::G_TEXTURE; |
| 45 | unsigned int GBI::G_DMA_IO, GBI::G_DMA_DL, GBI::G_DMA_TRI, GBI::G_DMA_MTX, GBI::G_DMA_VTX, GBI::G_DMA_OFFSETS; |
| 46 | unsigned int GBI::G_SPECIAL_1, GBI::G_SPECIAL_2, GBI::G_SPECIAL_3; |
| 47 | unsigned int GBI::G_VTX, GBI::G_MODIFYVTX, GBI::G_VTXCOLORBASE; |
| 48 | unsigned int GBI::G_TRI1, GBI::G_TRI2, GBI::G_TRI4; |
| 49 | unsigned int GBI::G_QUAD, GBI::G_LINE3D; |
| 50 | unsigned int GBI::G_RESERVED0, GBI::G_RESERVED1, GBI::G_RESERVED2, GBI::G_RESERVED3; |
| 51 | unsigned int GBI::G_SPRITE2D_BASE; |
| 52 | unsigned int GBI::G_BG_1CYC, GBI::G_BG_COPY; |
| 53 | unsigned int GBI::G_OBJ_RECTANGLE, GBI::G_OBJ_SPRITE, GBI::G_OBJ_MOVEMEM; |
| 54 | unsigned int GBI::G_SELECT_DL, GBI::G_OBJ_RENDERMODE, GBI::G_OBJ_RECTANGLE_R; |
| 55 | unsigned int GBI::G_OBJ_LOADTXTR, GBI::G_OBJ_LDTX_SPRITE, GBI::G_OBJ_LDTX_RECT, GBI::G_OBJ_LDTX_RECT_R; |
| 56 | unsigned int GBI::G_RDPHALF_0; |
| 57 | |
| 58 | unsigned int GBI::G_MTX_STACKSIZE; |
| 59 | unsigned int GBI::G_MTX_MODELVIEW; |
| 60 | unsigned int GBI::G_MTX_PROJECTION; |
| 61 | unsigned int GBI::G_MTX_MUL; |
| 62 | unsigned int GBI::G_MTX_LOAD; |
| 63 | unsigned int GBI::G_MTX_NOPUSH; |
| 64 | unsigned int GBI::G_MTX_PUSH; |
| 65 | |
| 66 | unsigned int GBI::G_TEXTURE_ENABLE; |
| 67 | unsigned int GBI::G_SHADING_SMOOTH; |
| 68 | unsigned int GBI::G_CULL_FRONT; |
| 69 | unsigned int GBI::G_CULL_BACK; |
| 70 | unsigned int GBI::G_CULL_BOTH; |
| 71 | unsigned int GBI::G_CLIPPING; |
| 72 | |
| 73 | unsigned int GBI::G_MV_VIEWPORT; |
| 74 | |
| 75 | unsigned int GBI::G_MWO_aLIGHT_1, GBI::G_MWO_bLIGHT_1; |
| 76 | unsigned int GBI::G_MWO_aLIGHT_2, GBI::G_MWO_bLIGHT_2; |
| 77 | unsigned int GBI::G_MWO_aLIGHT_3, GBI::G_MWO_bLIGHT_3; |
| 78 | unsigned int GBI::G_MWO_aLIGHT_4, GBI::G_MWO_bLIGHT_4; |
| 79 | unsigned int GBI::G_MWO_aLIGHT_5, GBI::G_MWO_bLIGHT_5; |
| 80 | unsigned int GBI::G_MWO_aLIGHT_6, GBI::G_MWO_bLIGHT_6; |
| 81 | unsigned int GBI::G_MWO_aLIGHT_7, GBI::G_MWO_bLIGHT_7; |
| 82 | unsigned int GBI::G_MWO_aLIGHT_8, GBI::G_MWO_bLIGHT_8; |
| 83 | |
| 84 | //----------------------------------------------------------------------------- |
| 85 | //! Constructor |
| 86 | //----------------------------------------------------------------------------- |
| 87 | GBI::GBI() |
| 88 | { |
| 89 | m_ucodeSelector = 0; |
| 90 | } |
| 91 | |
| 92 | //----------------------------------------------------------------------------- |
| 93 | //! Destructor |
| 94 | //----------------------------------------------------------------------------- |
| 95 | GBI::~GBI() |
| 96 | { |
| 97 | dispose(); |
| 98 | } |
| 99 | |
| 100 | //----------------------------------------------------------------------------- |
| 101 | //* Initialize |
| 102 | //----------------------------------------------------------------------------- |
| 103 | bool GBI::initialize(RSP* rsp, RDP* rdp, Memory* memory, DisplayListParser* dlp) |
| 104 | { |
| 105 | m_rsp = rsp; |
| 106 | m_rdp = rdp; |
| 107 | m_memory = memory; |
| 108 | |
| 109 | //Reset Binary Interface |
| 110 | for(int i=0; i<256; ++i) |
| 111 | { |
| 112 | m_cmds[i] = (GBIFunc)GBI::unknownInstruction; |
| 113 | } |
| 114 | |
| 115 | //Add RDP Instructions |
| 116 | m_rdpInsructions.initialize(m_rdp, dlp); |
| 117 | |
| 118 | m_cmds[G_SETCIMG] = (GBIFunc)RDPInstructions::RDP_SetCImg; |
| 119 | m_cmds[G_SETZIMG] = (GBIFunc)RDPInstructions::RDP_SetZImg; |
| 120 | m_cmds[G_SETTIMG] = (GBIFunc)RDPInstructions::RDP_SetTImg; |
| 121 | m_cmds[G_SETTILE] = (GBIFunc)RDPInstructions::RDP_SetTile; |
| 122 | m_cmds[G_LOADTILE] = (GBIFunc)RDPInstructions::RDP_LoadTile; |
| 123 | m_cmds[G_LOADBLOCK] = (GBIFunc)RDPInstructions::RDP_LoadBlock; |
| 124 | m_cmds[G_SETTILESIZE] = (GBIFunc)RDPInstructions::RDP_SetTileSize; |
| 125 | m_cmds[G_LOADTLUT] = (GBIFunc)RDPInstructions::RDP_LoadTLUT; |
| 126 | m_cmds[G_FILLRECT] = (GBIFunc)RDPInstructions::RDP_FillRect; |
| 127 | m_cmds[G_TEXRECTFLIP] = (GBIFunc)RDPInstructions::RDP_TexRectFlip; |
| 128 | m_cmds[G_TEXRECT] = (GBIFunc)RDPInstructions::RDP_TexRect; |
| 129 | m_cmds[G_SETENVCOLOR] = (GBIFunc)RDPInstructions::RDP_SetEnvColor; |
| 130 | m_cmds[G_SETPRIMCOLOR] = (GBIFunc)RDPInstructions::RDP_SetPrimColor; |
| 131 | m_cmds[G_SETBLENDCOLOR] = (GBIFunc)RDPInstructions::RDP_SetBlendColor; |
| 132 | m_cmds[G_SETFOGCOLOR] = (GBIFunc)RDPInstructions::RDP_SetFogColor; |
| 133 | m_cmds[G_SETFILLCOLOR] = (GBIFunc)RDPInstructions::RDP_SetFillColor; |
| 134 | m_cmds[G_SETCOMBINE] = (GBIFunc)RDPInstructions::RDP_SetCombine; |
| 135 | m_cmds[G_RDPSETOTHERMODE] = (GBIFunc)RDPInstructions::RDP_SetOtherMode; |
| 136 | m_cmds[G_SETPRIMDEPTH] = (GBIFunc)RDPInstructions::RDP_SetPrimDepth; |
| 137 | m_cmds[G_SETSCISSOR] = (GBIFunc)RDPInstructions::RDP_SetScissor; |
| 138 | m_cmds[G_SETCONVERT] = (GBIFunc)RDPInstructions::RDP_SetConvert; |
| 139 | m_cmds[G_SETKEYR] = (GBIFunc)RDPInstructions::RDP_SetKeyR; |
| 140 | m_cmds[G_SETKEYGB] = (GBIFunc)RDPInstructions::RDP_SetKeyGB; |
| 141 | m_cmds[G_NOOP] = (GBIFunc)RDPInstructions::RDP_NoOp; |
| 142 | m_cmds[G_RDPFULLSYNC] = (GBIFunc)RDPInstructions::RDP_FullSync; |
| 143 | m_cmds[G_RDPTILESYNC] = (GBIFunc)RDPInstructions::RDP_TileSync; |
| 144 | m_cmds[G_RDPPIPESYNC] = (GBIFunc)RDPInstructions::RDP_PipeSync; |
| 145 | m_cmds[G_RDPLOADSYNC] = (GBIFunc)RDPInstructions::RDP_LoadSync; |
| 146 | |
| 147 | m_ucodeSelector = new UCodeSelector(); |
| 148 | if ( !m_ucodeSelector->initialize(memory) ) { |
| 149 | return false; |
| 150 | } |
| 151 | |
| 152 | //Initilize Ucode |
| 153 | |
| 154 | m_ucode0.initialize(m_rsp, m_rdp, memory, dlp); //F3D |
| 155 | m_ucode1.initialize(this, m_rsp, m_rdp, memory); //F3DEX |
| 156 | m_ucode2.initialize(this, m_rsp, m_rdp, memory, dlp); //Golden Eye |
| 157 | m_ucode4.initialize(this, m_rsp); //Wave Race 64 |
| 158 | m_ucode5.initialize(this, m_rsp, m_rdp, memory, dlp); //F3DEX2 |
| 159 | m_ucode6.initialize(this, m_rsp, m_rdp, memory, dlp); //Diddy Kong Racing |
| 160 | m_ucode7.initialize(m_rsp); |
| 161 | m_ucode9.initialize(m_rsp); //Perfect Dark |
| 162 | m_ucode10.initialize(this, m_rsp, m_rdp, memory, dlp); |
| 163 | |
| 164 | m_previusUCodeStart = -1; |
| 165 | |
| 166 | return true; |
| 167 | } |
| 168 | |
| 169 | //----------------------------------------------------------------------------- |
| 170 | // Dispose |
| 171 | //----------------------------------------------------------------------------- |
| 172 | void GBI::dispose() |
| 173 | { |
| 174 | if ( m_ucodeSelector ) { delete m_ucodeSelector; m_ucodeSelector = 0; } |
| 175 | |
| 176 | m_previusUCodeStart = -1; |
| 177 | } |
| 178 | |
| 179 | //----------------------------------------------------------------------------- |
| 180 | // Select UCode |
| 181 | //----------------------------------------------------------------------------- |
| 182 | void GBI::selectUCode( unsigned int ucStart, |
| 183 | unsigned int ucDStart, |
| 184 | unsigned int ucSize, |
| 185 | unsigned int ucDSize) |
| 186 | { |
| 187 | if ( m_previusUCodeStart == ucStart ) |
| 188 | { |
| 189 | return; //Already have correct ucode no need to find one |
| 190 | } |
| 191 | m_previusUCodeStart = ucStart; |
| 192 | |
| 193 | //Identify ucode |
| 194 | unsigned int ucode = m_ucodeSelector->checkUCode(ucStart, ucDStart, ucSize, ucDSize); |
| 195 | |
| 196 | //Unsupported ucodes |
| 197 | if ( ucode >= 6 || ucode == 3 ) |
| 198 | { |
| 199 | //MessageBox(0, |
| 200 | // "This graphics plugin does not support this game, please try another.", |
| 201 | // "Arachnoid Graphics Plugin", |
| 202 | // MB_OK|MB_SETFOREGROUND ); |
| 203 | } |
| 204 | |
| 205 | //if ( ucode == 5 ) |
| 206 | //{ |
| 207 | // OpenGLManager::getSingleton().setForceDisableCulling(true); //Do not support Face Culling? |
| 208 | //} |
| 209 | |
| 210 | //Set Ucode |
| 211 | switch ( ucode ) |
| 212 | { |
| 213 | case 0 : m_ucode0.initializeGBI(this); break; //F3D - Super Mario 64 |
| 214 | case 1 : m_ucode1.initializeGBI(); break; //F3DEX - Mario Kart, Star Fox 64, Bomberman 64, ... |
| 215 | case 2 : m_ucode2.initializeGBI(); break; // - Golden Eye |
| 216 | case 3 : //S2DEX - Chou Snobow Kids, V-Rally Edition 99, Zelda Majoras Mask |
| 217 | case 4 : m_ucode4.initializeGBI(); break; // - Wave Racer 64 |
| 218 | case 5 : m_ucode5.initializeGBI(); break; //F3DEX2 - Donkey Kong 64, Fighter's Destiny 2, Mario Golf 64, F-Zero X, Paper Mario, ... |
| 219 | case 6 : m_ucode6.initializeGBI(); break; // - Diddy Kong Racing |
| 220 | case 7 : m_ucode7.initializeGBI(this); break; // - Yoshi's Story |
| 221 | case 8 : // - Puzzle Master 64 |
| 222 | case 9 : m_ucode9.initializeGBI(this); break; // - Perfect Dark |
| 223 | case 10 : m_ucode10.initializeGBI(); // - Conker The Bad Fur Day |
| 224 | case 11 : m_ucode6.initializeGBI(); break; // - Jet Force Gemini |
| 225 | case 12 : m_ucode1.initializeGBI(); break; // - 1080 |
| 226 | default : |
| 227 | //m_ucode5.initializeGBI(this); break; //F3DEX2 |
| 228 | //m_ucode1.initializeGBI(this); |
| 229 | m_ucode0.initializeGBI(this); |
| 230 | break; |
| 231 | } |
| 232 | |
| 233 | } |
| 234 | |
| 235 | //----------------------------------------------------------------------------- |
| 236 | //! Unknown Instruction |
| 237 | //! This function will be called when the GBI can't find the correct function |
| 238 | //! to call. |
| 239 | //----------------------------------------------------------------------------- |
| 240 | void GBI::unknownInstruction(MicrocodeArgument* arg) |
| 241 | { |
| 242 | static bool warned = false; |
| 243 | if ( !warned ) { |
| 244 | Logger::getSingleton().printMsg("GBI - Unknown Function", M64MSG_WARNING); |
| 245 | warned = true; |
| 246 | } |
| 247 | } |