Added missing launcher
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / DisplayListParser.cpp
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 "DisplayListParser.h"
23 #include "Memory.h"
24 #include "GBI.h"
25 #include "RSP.h"
26 #include "RDP.h"
27 #include "OpenGLRenderer.h"
28 #include "GBIDefs.h"
29
30 //-----------------------------------------------------------------------------
31 //* Task
32 //! Definition of tasks that needs to be performed  by the RSP
33 //! Used to process the dlist by the RSP (Reality Signal Processor)
34 //! Placed in DMEM at adress 0x04000fc0
35 //-----------------------------------------------------------------------------
36 typedef struct 
37 {
38     unsigned int type;
39     unsigned int flags;
40     unsigned int ucode_boot;
41     unsigned int ucode_boot_size;
42     unsigned int ucode;
43     unsigned int ucode_size;
44     unsigned int ucode_data;
45     unsigned int ucode_data_size;
46     unsigned int dram_stack;
47     unsigned int dram_stack_size;
48     unsigned int output_buff;
49     unsigned int output_buff_size;
50     unsigned int data_ptr;
51     unsigned int data_size;
52     unsigned int yield_data_ptr;
53     unsigned int yield_data_size;
54 } Task_t;
55
56 typedef union {
57     Task_t t;
58     unsigned long long force_structure_alignment;
59 } Task;
60
61 //-----------------------------------------------------------------------------
62 //! Constructor
63 //-----------------------------------------------------------------------------
64 DisplayListParser::DisplayListParser()
65 {
66 }
67
68 //-----------------------------------------------------------------------------
69 //! Destructor
70 //-----------------------------------------------------------------------------
71 DisplayListParser::~DisplayListParser()
72 {
73 }
74
75 //-----------------------------------------------------------------------------
76 //! Initialize
77 //-----------------------------------------------------------------------------
78 bool DisplayListParser::initialize(RSP* rsp, RDP* rdp, GBI* gbi, Memory* memory)
79 {
80     //Save pointers
81     m_rsp    = rsp;
82     m_rdp    = rdp;
83     m_gbi    = gbi;
84     m_memory = memory;
85
86     //Reset display list
87     m_DListStackPointer = 0;
88     for (int i=0; i<MAX_DL_STACK_SIZE; ++i)
89     {
90         m_DlistStack[i].pc = 0;
91         m_DlistStack[i].countdown = MAX_DL_COUNT;
92     }
93     return true;
94 }
95
96 //-----------------------------------------------------------------------------
97 //* Process Display List
98 //! Parses the display list
99 //-----------------------------------------------------------------------------
100 void DisplayListParser::processDisplayList()
101 {
102     Task* task = (Task*)( m_memory->getDMEM(TASK_ADDRESS_RELATIVE_DMEM));
103
104
105     //Select UCode
106     m_gbi->selectUCode(task->t.ucode, task->t.ucode_data, task->t.ucode_size, task->t.ucode_data_size);
107
108     //Parse DList
109     m_DListStackPointer = 0;
110     m_DlistStack[m_DListStackPointer].pc = (unsigned int)task->t.data_ptr;
111     m_DlistStack[m_DListStackPointer].countdown = MAX_DL_COUNT;
112
113     // The main loop
114     while( m_DListStackPointer >= 0 )
115     {
116         //Cast memory pointer
117         //uint32* RDRAMu32            = (unsigned int*)graphicsInfo.RDRAM;
118         unsigned int* RDRAMu32 = m_memory->getRDRAMint32();            
119
120         //Get ucode argument from memory (vertices, textures, matrices...)
121         MicrocodeArgument* ucodeArg = (MicrocodeArgument*)&RDRAMu32[(m_DlistStack[m_DListStackPointer].pc>>2)];
122
123         //Increment program counter
124         m_DlistStack[m_DListStackPointer].pc += 8;
125
126         //Call function to execute command
127         m_gbi->m_cmds[(ucodeArg->cmd)](ucodeArg);
128
129         //Get next command        
130         MicrocodeArgument* ucodeNext =  (MicrocodeArgument*)&RDRAMu32[(m_DlistStack[m_DListStackPointer].pc>>2)];
131         
132         //If this was a rendering command
133         if ( ucodeArg->cmd == GBI::G_TRI1 ||  
134              ucodeArg->cmd == GBI::G_TRI2 || 
135              ucodeArg->cmd == GBI::G_TRI4 || 
136              ucodeArg->cmd == GBI::G_QUAD || 
137              ucodeArg->cmd == GBI::G_DMA_TRI ) 
138         {
139             //If next is not a rendering command
140             if (  ucodeNext->cmd != GBI::G_TRI1 &&  
141                   ucodeNext->cmd != GBI::G_TRI2 && 
142                   ucodeNext->cmd != GBI::G_TRI4 && 
143                   ucodeNext->cmd != GBI::G_QUAD && 
144                   ucodeNext->cmd != GBI::G_DMA_TRI ) 
145             {
146                 OpenGLRenderer::getSingleton().render();
147             }
148         }
149
150         //??
151         if ( m_DListStackPointer >= 0 && --m_DlistStack[m_DListStackPointer].countdown < 0 )
152         {
153             m_DListStackPointer--;
154         }
155     }
156
157     //Trigger interupts
158     m_rdp->triggerInterrupt();
159     m_rsp->triggerInterrupt();
160 }
161
162 //-----------------------------------------------------------------------------
163 //! Get next word
164 //-----------------------------------------------------------------------------
165 unsigned int DisplayListParser::getNextWord()
166 {
167     unsigned int word = *(unsigned int*)m_memory->getRDRAM( this->getPC() + 4 );
168     this->increasePC(8);
169     return word;
170 }
171
172 //-----------------------------------------------------------------------------
173 //!< @param segmentAddress Used to retrive RDRAM address witch is used to set program counter
174 //-----------------------------------------------------------------------------
175 void DisplayListParser::displayList(unsigned int segmentAddress)
176 {
177     unsigned int address = m_memory->getRDRAMAddress(segmentAddress);
178
179     if ( (address + 8) > m_memory->getRDRAMSize() ) {
180         return;
181     }  
182
183     if ( m_DListStackPointer < (MAX_DL_STACK_SIZE - 1))
184     {
185         m_DListStackPointer++;
186         m_DlistStack[m_DListStackPointer].pc = address;
187         m_DlistStack[m_DListStackPointer].countdown = MAX_DL_COUNT;
188     }
189 }
190
191 //-----------------------------------------------------------------------------
192 //! Branch Display List
193 //-----------------------------------------------------------------------------
194 void DisplayListParser::branchDisplayList(unsigned int dl)
195 {
196     unsigned int address = m_memory->getRDRAMAddress( dl );
197
198     if ( (address + 8) > m_memory->getRDRAMSize() ) {
199         return;
200     }  
201
202     m_DlistStack[m_DListStackPointer].pc = address;
203     m_DlistStack[m_DListStackPointer].countdown = MAX_DL_COUNT;
204 }
205
206 //-----------------------------------------------------------------------------
207 //! DMA Display List
208 //-----------------------------------------------------------------------------
209 void DisplayListParser::DMADisplayList( unsigned int w0, unsigned int w1 )
210 {
211     //unsigned int dwAddr = (w1);//RSPSegmentAddr((gfx->words.w1));
212     unsigned int dwAddr = m_memory->getRDRAMAddress(w1);//RSPSegmentAddr((gfx->words.w1));
213
214     {
215         m_DListStackPointer++;
216         m_DlistStack[m_DListStackPointer].pc = dwAddr;
217         m_DlistStack[m_DListStackPointer].countdown = (((w0)>>16)&0xFF);
218     }
219 }