Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / DisplayListParser.cpp
diff --git a/source/mupen64plus-video-arachnoid/src/DisplayListParser.cpp b/source/mupen64plus-video-arachnoid/src/DisplayListParser.cpp
new file mode 100755 (executable)
index 0000000..90aec28
--- /dev/null
@@ -0,0 +1,219 @@
+/******************************************************************************
+ * Arachnoid Graphics Plugin for Mupen64Plus
+ * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
+ *
+ * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *****************************************************************************/
+
+#include "DisplayListParser.h"
+#include "Memory.h"
+#include "GBI.h"
+#include "RSP.h"
+#include "RDP.h"
+#include "OpenGLRenderer.h"
+#include "GBIDefs.h"
+
+//-----------------------------------------------------------------------------
+//* Task
+//! Definition of tasks that needs to be performed  by the RSP
+//! Used to process the dlist by the RSP (Reality Signal Processor)
+//! Placed in DMEM at adress 0x04000fc0
+//-----------------------------------------------------------------------------
+typedef struct 
+{
+    unsigned int type;
+    unsigned int flags;
+    unsigned int ucode_boot;
+    unsigned int ucode_boot_size;
+    unsigned int ucode;
+    unsigned int ucode_size;
+    unsigned int ucode_data;
+    unsigned int ucode_data_size;
+    unsigned int dram_stack;
+    unsigned int dram_stack_size;
+    unsigned int output_buff;
+    unsigned int output_buff_size;
+    unsigned int data_ptr;
+    unsigned int data_size;
+    unsigned int yield_data_ptr;
+    unsigned int yield_data_size;
+} Task_t;
+
+typedef union {
+    Task_t t;
+    unsigned long long force_structure_alignment;
+} Task;
+
+//-----------------------------------------------------------------------------
+//! Constructor
+//-----------------------------------------------------------------------------
+DisplayListParser::DisplayListParser()
+{
+}
+
+//-----------------------------------------------------------------------------
+//! Destructor
+//-----------------------------------------------------------------------------
+DisplayListParser::~DisplayListParser()
+{
+}
+
+//-----------------------------------------------------------------------------
+//! Initialize
+//-----------------------------------------------------------------------------
+bool DisplayListParser::initialize(RSP* rsp, RDP* rdp, GBI* gbi, Memory* memory)
+{
+    //Save pointers
+    m_rsp    = rsp;
+    m_rdp    = rdp;
+    m_gbi    = gbi;
+    m_memory = memory;
+
+    //Reset display list
+    m_DListStackPointer = 0;
+    for (int i=0; i<MAX_DL_STACK_SIZE; ++i)
+    {
+        m_DlistStack[i].pc = 0;
+        m_DlistStack[i].countdown = MAX_DL_COUNT;
+    }
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+//* Process Display List
+//! Parses the display list
+//-----------------------------------------------------------------------------
+void DisplayListParser::processDisplayList()
+{
+    Task* task = (Task*)( m_memory->getDMEM(TASK_ADDRESS_RELATIVE_DMEM));
+
+
+    //Select UCode
+    m_gbi->selectUCode(task->t.ucode, task->t.ucode_data, task->t.ucode_size, task->t.ucode_data_size);
+
+    //Parse DList
+    m_DListStackPointer = 0;
+    m_DlistStack[m_DListStackPointer].pc = (unsigned int)task->t.data_ptr;
+    m_DlistStack[m_DListStackPointer].countdown = MAX_DL_COUNT;
+
+    // The main loop
+    while( m_DListStackPointer >= 0 )
+    {
+        //Cast memory pointer
+        //uint32* RDRAMu32            = (unsigned int*)graphicsInfo.RDRAM;
+        unsigned int* RDRAMu32 = m_memory->getRDRAMint32();            
+
+        //Get ucode argument from memory (vertices, textures, matrices...)
+        MicrocodeArgument* ucodeArg = (MicrocodeArgument*)&RDRAMu32[(m_DlistStack[m_DListStackPointer].pc>>2)];
+
+        //Increment program counter
+        m_DlistStack[m_DListStackPointer].pc += 8;
+
+        //Call function to execute command
+        m_gbi->m_cmds[(ucodeArg->cmd)](ucodeArg);
+
+        //Get next command        
+        MicrocodeArgument* ucodeNext =  (MicrocodeArgument*)&RDRAMu32[(m_DlistStack[m_DListStackPointer].pc>>2)];
+        
+        //If this was a rendering command
+        if ( ucodeArg->cmd == GBI::G_TRI1 ||  
+             ucodeArg->cmd == GBI::G_TRI2 || 
+             ucodeArg->cmd == GBI::G_TRI4 || 
+             ucodeArg->cmd == GBI::G_QUAD || 
+             ucodeArg->cmd == GBI::G_DMA_TRI ) 
+        {
+            //If next is not a rendering command
+            if (  ucodeNext->cmd != GBI::G_TRI1 &&  
+                  ucodeNext->cmd != GBI::G_TRI2 && 
+                  ucodeNext->cmd != GBI::G_TRI4 && 
+                  ucodeNext->cmd != GBI::G_QUAD && 
+                  ucodeNext->cmd != GBI::G_DMA_TRI ) 
+            {
+                OpenGLRenderer::getSingleton().render();
+            }
+        }
+
+        //??
+        if ( m_DListStackPointer >= 0 && --m_DlistStack[m_DListStackPointer].countdown < 0 )
+        {
+            m_DListStackPointer--;
+        }
+    }
+
+    //Trigger interupts
+    m_rdp->triggerInterrupt();
+    m_rsp->triggerInterrupt();
+}
+
+//-----------------------------------------------------------------------------
+//! Get next word
+//-----------------------------------------------------------------------------
+unsigned int DisplayListParser::getNextWord()
+{
+    unsigned int word = *(unsigned int*)m_memory->getRDRAM( this->getPC() + 4 );
+    this->increasePC(8);
+    return word;
+}
+
+//-----------------------------------------------------------------------------
+//!< @param segmentAddress Used to retrive RDRAM address witch is used to set program counter
+//-----------------------------------------------------------------------------
+void DisplayListParser::displayList(unsigned int segmentAddress)
+{
+    unsigned int address = m_memory->getRDRAMAddress(segmentAddress);
+
+    if ( (address + 8) > m_memory->getRDRAMSize() ) {
+        return;
+    }  
+
+    if ( m_DListStackPointer < (MAX_DL_STACK_SIZE - 1))
+    {
+        m_DListStackPointer++;
+        m_DlistStack[m_DListStackPointer].pc = address;
+        m_DlistStack[m_DListStackPointer].countdown = MAX_DL_COUNT;
+    }
+}
+
+//-----------------------------------------------------------------------------
+//! Branch Display List
+//-----------------------------------------------------------------------------
+void DisplayListParser::branchDisplayList(unsigned int dl)
+{
+    unsigned int address = m_memory->getRDRAMAddress( dl );
+
+    if ( (address + 8) > m_memory->getRDRAMSize() ) {
+        return;
+    }  
+
+    m_DlistStack[m_DListStackPointer].pc = address;
+    m_DlistStack[m_DListStackPointer].countdown = MAX_DL_COUNT;
+}
+
+//-----------------------------------------------------------------------------
+//! DMA Display List
+//-----------------------------------------------------------------------------
+void DisplayListParser::DMADisplayList( unsigned int w0, unsigned int w1 )
+{
+    //unsigned int dwAddr = (w1);//RSPSegmentAddr((gfx->words.w1));
+    unsigned int dwAddr = m_memory->getRDRAMAddress(w1);//RSPSegmentAddr((gfx->words.w1));
+
+    {
+        m_DListStackPointer++;
+        m_DlistStack[m_DListStackPointer].pc = dwAddr;
+        m_DlistStack[m_DListStackPointer].countdown = (((w0)>>16)&0xFF);
+    }
+}