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
CommitLineData
22726e4d 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//-----------------------------------------------------------------------------
36typedef 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
56typedef union {
57 Task_t t;
58 unsigned long long force_structure_alignment;
59} Task;
60
61//-----------------------------------------------------------------------------
62//! Constructor
63//-----------------------------------------------------------------------------
64DisplayListParser::DisplayListParser()
65{
66}
67
68//-----------------------------------------------------------------------------
69//! Destructor
70//-----------------------------------------------------------------------------
71DisplayListParser::~DisplayListParser()
72{
73}
74
75//-----------------------------------------------------------------------------
76//! Initialize
77//-----------------------------------------------------------------------------
78bool 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//-----------------------------------------------------------------------------
100void 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//-----------------------------------------------------------------------------
165unsigned 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//-----------------------------------------------------------------------------
175void 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//-----------------------------------------------------------------------------
194void 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//-----------------------------------------------------------------------------
209void 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}