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 | //----------------------------------------------------------------------------- |
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 | } |