2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //****************************************************************
22 // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
23 // Project started on December 29th, 2001
26 // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
27 // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
29 // Official Glide64 development channel: #Glide64 on EFnet
31 // Original author: Dave2001 (Dave2999@hotmail.com)
32 // Other authors: Gonetz, Gugaman
34 //****************************************************************
37 BOOL billboarding
= 0;
39 DWORD dma_offset_mtx
= 0;
40 DWORD dma_offset_vtx
= 0;
42 static void uc5_dma_offsets ()
44 dma_offset_mtx
= rdp
.cmd0
& 0x00FFFFFF;
45 dma_offset_vtx
= rdp
.cmd1
& 0x00FFFFFF;
47 FRDP("uc5:dma_offsets - mtx: %08lx, vtx: %08lx\n", dma_offset_mtx
, dma_offset_vtx
);
50 static void uc5_matrix ()
52 // Use segment offset to get the address
53 DWORD addr
= dma_offset_mtx
+ (segoffset(rdp
.cmd1
) & BMASK
);
55 BYTE n
= (BYTE
)((rdp
.cmd0
>> 16) & 0xF);
60 n
= (BYTE
)((rdp
.cmd0
>> 22) & 0x3);
65 multiply
= (BYTE
)((rdp
.cmd0
>> 23) & 0x1);
70 FRDP("uc5:matrix - #%d, addr: %08lx\n", n
, addr
);
74 int x
,y
; // matrix index
78 __declspec( align(16) ) float m
[4][4];
79 for (x
=0; x
<16; x
+=4) { // Adding 4 instead of one, just to remove mult. later
82 (((__int32
)((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
)^1]) << 16) |
83 ((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
+16)^1]
87 __declspec( align(16) ) float m_src
[4][4];
88 memcpy (m_src
, rdp
.dkrproj
[0], 64);
89 MulMatrices(m
, m_src
, rdp
.dkrproj
[n
]);
93 for (x
=0; x
<16; x
+=4) { // Adding 4 instead of one, just to remove mult. later
95 rdp
.dkrproj
[n
][x
>>2][y
] = (float)(
96 (((__int32
)((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
)^1]) << 16) |
97 ((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
+16)^1]
102 rdp
.update
|= UPDATE_MULT_MAT
;
104 #ifdef EXTREME_LOGGING
105 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[n
][0][0], rdp
.dkrproj
[n
][0][1], rdp
.dkrproj
[n
][0][2], rdp
.dkrproj
[n
][0][3]);
106 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[n
][1][0], rdp
.dkrproj
[n
][1][1], rdp
.dkrproj
[n
][1][2], rdp
.dkrproj
[n
][1][3]);
107 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[n
][2][0], rdp
.dkrproj
[n
][2][1], rdp
.dkrproj
[n
][2][2], rdp
.dkrproj
[n
][2][3]);
108 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[n
][3][0], rdp
.dkrproj
[n
][3][1], rdp
.dkrproj
[n
][3][2], rdp
.dkrproj
[n
][3][3]);
110 for (int i
=0; i
<3; i
++)
112 FRDP ("proj %d\n", i
);
113 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[i
][0][0], rdp
.dkrproj
[i
][0][1], rdp
.dkrproj
[i
][0][2], rdp
.dkrproj
[i
][0][3]);
114 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[i
][1][0], rdp
.dkrproj
[i
][1][1], rdp
.dkrproj
[i
][1][2], rdp
.dkrproj
[i
][1][3]);
115 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[i
][2][0], rdp
.dkrproj
[i
][2][1], rdp
.dkrproj
[i
][2][2], rdp
.dkrproj
[i
][2][3]);
116 FRDP ("{%f,%f,%f,%f}\n", rdp
.dkrproj
[i
][3][0], rdp
.dkrproj
[i
][3][1], rdp
.dkrproj
[i
][3][2], rdp
.dkrproj
[i
][3][3]);
121 static void uc5_vertex ()
123 DWORD addr
= dma_offset_vtx
+ (segoffset(rdp
.cmd1
) & BMASK
);
125 // | cccc cccc 1111 1??? 0000 0002 2222 2222 | cmd1 = address |
127 // 1 = method #1 of getting count
128 // 2 = method #2 of getting count
129 // ? = unknown, but used
132 int n
= ((rdp
.cmd0
>> 19) & 0x1F);// + 1;
135 //int n = ((rdp.cmd0 & 0x1FF) - 8) / 18; // same thing!
137 if (rdp
.cmd0
& 0x00010000)
145 int first
= ((rdp
.cmd0
>> 9) & 0x1F) + vtx_last
;
146 FRDP ("uc5:vertex - addr: %08lx, first: %d, count: %d, matrix: %08lx\n", addr
, first
, n
, cur_mtx
);
152 for (int i
=first
; i
<first
+n
; i
++)
154 start
= (i
-first
) * 10;
155 VERTEX
*v
= &rdp
.vtx
[i
];
156 x
= (float)((short*)gfx
.RDRAM
)[(((addr
+start
) >> 1) + 0)^1];
157 y
= (float)((short*)gfx
.RDRAM
)[(((addr
+start
) >> 1) + 1)^1];
158 z
= (float)((short*)gfx
.RDRAM
)[(((addr
+start
) >> 1) + 2)^1];
160 v
->x
= x
*rdp
.dkrproj
[prj
][0][0] + y
*rdp
.dkrproj
[prj
][1][0] + z
*rdp
.dkrproj
[prj
][2][0] + rdp
.dkrproj
[prj
][3][0];
161 v
->y
= x
*rdp
.dkrproj
[prj
][0][1] + y
*rdp
.dkrproj
[prj
][1][1] + z
*rdp
.dkrproj
[prj
][2][1] + rdp
.dkrproj
[prj
][3][1];
162 v
->z
= x
*rdp
.dkrproj
[prj
][0][2] + y
*rdp
.dkrproj
[prj
][1][2] + z
*rdp
.dkrproj
[prj
][2][2] + rdp
.dkrproj
[prj
][3][2];
163 v
->w
= x
*rdp
.dkrproj
[prj
][0][3] + y
*rdp
.dkrproj
[prj
][1][3] + z
*rdp
.dkrproj
[prj
][2][3] + rdp
.dkrproj
[prj
][3][3];
167 v
->x
+= rdp
.vtx
[0].x
;
168 v
->y
+= rdp
.vtx
[0].y
;
169 v
->z
+= rdp
.vtx
[0].z
;
170 v
->w
+= rdp
.vtx
[0].w
;
173 #ifdef EXTREME_LOGGING
174 FRDP ("v%d - x: %f, y: %f, z: %f, w: %f\n", i
, v
->x
, v
->y
, v
->z
, v
->w
);
177 v
->oow
= 1.0f
/ v
->w
;
178 v
->x_w
= v
->x
* v
->oow
;
179 v
->y_w
= v
->y
* v
->oow
;
180 v
->z_w
= v
->z
* v
->oow
;
182 v
->uv_calculated
= 0xFFFFFFFF;
183 v
->screen_translated
= 0;
184 v
->shade_mods_allowed
= 1;
187 if (v
->x
< -v
->w
) v
->scr_off
|= 1;
188 if (v
->x
> v
->w
) v
->scr_off
|= 2;
189 if (v
->y
< -v
->w
) v
->scr_off
|= 4;
190 if (v
->y
> v
->w
) v
->scr_off
|= 8;
191 if (v
->w
< 0.1f
) v
->scr_off
|= 16;
193 v
->r
= ((BYTE
*)gfx
.RDRAM
)[(addr
+start
+ 6)^3];
194 v
->g
= ((BYTE
*)gfx
.RDRAM
)[(addr
+start
+ 7)^3];
195 v
->b
= ((BYTE
*)gfx
.RDRAM
)[(addr
+start
+ 8)^3];
196 v
->a
= ((BYTE
*)gfx
.RDRAM
)[(addr
+start
+ 9)^3];
199 #ifdef EXTREME_LOGGING
200 FRDP ("vtx%d: x: %f, y: %f, z: %f, w: %f\n", i
, v
->x
, v
->y
, v
->z
, v
->w
);
207 static void uc5_tridma ()
209 vtx_last
= 0; // we've drawn something, so the vertex index needs resetting
210 if (rdp
.skip_drawing
)
213 // | cccc cccc 2222 0000 1111 1111 1111 0000 | cmd1 = address |
214 // c = tridma command
215 // 1 = method #1 of getting count
216 // 2 = method #2 of getting count
219 DWORD addr
= segoffset(rdp
.cmd1
) & BMASK
;
220 int num
= (rdp
.cmd0
& 0xFFF0) >> 4;
221 //int num = ((rdp.cmd0 & 0x00F00000) >> 20) + 1; // same thing!
222 FRDP("uc5:tridma #%d - addr: %08lx, count: %d\n", rdp
.tri_n
, addr
, num
);
224 int start
, v0
, v1
, v2
, flags
;
225 for (int i
=0; i
<num
; i
++)
228 v0
= gfx
.RDRAM
[addr
+start
];
229 v1
= gfx
.RDRAM
[addr
+start
+1];
230 v2
= gfx
.RDRAM
[addr
+start
+2];
232 FRDP("tri #%d - %d, %d, %d\n", rdp
.tri_n
, v0
, v1
, v2
);
240 flags
= gfx
.RDRAM
[addr
+start
+3];
242 if (flags
& 0x40) { // no cull
243 rdp
.flags
&= ~CULLMASK
;
244 grCullMode (GR_CULL_DISABLE
);
247 rdp
.flags
&= ~CULLMASK
;
248 if (rdp
.view_scale
[0] < 0) {
249 rdp
.flags
|= CULL_BACK
; // agh, backwards culling
250 grCullMode (GR_CULL_POSITIVE
);
253 rdp
.flags
|= CULL_FRONT
;
254 grCullMode (GR_CULL_NEGATIVE
);
259 v
[0]->ou
= (float)((short*)gfx
.RDRAM
)[((addr
+start
) >> 1) + 5] / 32.0f
;
260 v
[0]->ov
= (float)((short*)gfx
.RDRAM
)[((addr
+start
) >> 1) + 4] / 32.0f
;
261 v
[1]->ou
= (float)((short*)gfx
.RDRAM
)[((addr
+start
) >> 1) + 3] / 32.0f
;
262 v
[1]->ov
= (float)((short*)gfx
.RDRAM
)[((addr
+start
) >> 1) + 2] / 32.0f
;
263 v
[2]->ou
= (float)((short*)gfx
.RDRAM
)[((addr
+start
) >> 1) + 1] / 32.0f
;
264 v
[2]->ov
= (float)((short*)gfx
.RDRAM
)[((addr
+start
) >> 1) + 0] / 32.0f
;
266 v
[0]->uv_calculated
= 0xFFFFFFFF;
267 v
[1]->uv_calculated
= 0xFFFFFFFF;
268 v
[2]->uv_calculated
= 0xFFFFFFFF;
282 static void uc5_dl_in_mem ()
284 DWORD addr
= segoffset(rdp
.cmd1
) & BMASK
;
285 int count
= (rdp
.cmd0
& 0x00FF0000) >> 16;
286 FRDP ("uc5:dl_in_mem - addr: %08lx, count: %d\n", addr
, count
);
289 RDP_E ("** DL stack overflow **\n");
290 RDP ("** DL stack overflow **\n");
293 rdp
.pc_i
++; // go to the next PC in the stack
294 rdp
.pc
[rdp
.pc_i
] = addr
; // jump to the address
295 rdp
.dl_count
= count
+ 1;
298 static void uc5_moveword()
300 RDP("uc5:moveword ");
302 // Find which command this is (lowest byte of cmd0)
303 switch (rdp
.cmd0
& 0xFF)
305 case 0x02: // moveword matrix 2 billboard
306 billboarding
= (rdp
.cmd1
& 1);
307 FRDP ("matrix billboard - %s\n", str_offon
[billboarding
]);
310 case 0x04: // clip (verified same)
311 FRDP ("clip %08lx, %08lx\n", rdp
.cmd0
, rdp
.cmd1
);
314 case 0x06: // segment (verified same)
315 FRDP ("segment: %08lx -> seg%d\n", rdp
.cmd1
, (rdp
.cmd0
>> 10) & 0x0F);
316 rdp
.segment
[(rdp
.cmd0
>> 10) & 0x0F] = rdp
.cmd1
;
321 rdp
.fog_multiplier
= (short)(rdp
.cmd1
>> 16);
322 rdp
.fog_offset
= (short)(rdp
.cmd1
& 0x0000FFFF);
323 FRDP ("fog: multiplier: %f, offset: %f\n", rdp
.fog_multiplier
, rdp
.fog_offset
);
324 // rdp.update |= UPDATE_FOG_ENABLED;
328 case 0x0a: // moveword matrix select
329 cur_mtx
= (rdp
.cmd1
>> 6) & 3;
330 FRDP ("matrix select - mtx: %d\n", cur_mtx
);
334 FRDP ("(unknown) %02lx - IGNORED\n", rdp
.cmd0
&0xFF);
338 static void uc5_setgeometrymode()
340 FRDP("uc0:setgeometrymode %08lx\n", rdp
.cmd1
);
342 rdp
.geom_mode
|= rdp
.cmd1
;
344 if (rdp
.cmd1
& 0x00000001) // Z-Buffer enable
346 if (!(rdp
.flags
& ZBUF_ENABLED
))
348 rdp
.flags
|= ZBUF_ENABLED
;
349 rdp
.update
|= UPDATE_ZBUF_ENABLED
;
354 if (rdp
.cmd1
& 0x00010000) // Fog enable
356 if (!(rdp
.flags
& FOG_ENABLED
))
358 rdp
.flags
|= FOG_ENABLED
;
359 rdp
.update
|= UPDATE_FOG_ENABLED
;
364 static void uc5_cleargeometrymode()
366 FRDP("uc0:cleargeometrymode %08lx\n", rdp
.cmd1
);
368 rdp
.geom_mode
&= (~rdp
.cmd1
);
370 if (rdp
.cmd1
& 0x00000001) // Z-Buffer enable
372 if (rdp
.flags
& ZBUF_ENABLED
)
374 rdp
.flags
^= ZBUF_ENABLED
;
375 rdp
.update
|= UPDATE_ZBUF_ENABLED
;
379 if (rdp
.cmd1
& 0x00010000) // Fog enable
381 if (rdp
.flags
& FOG_ENABLED
)
383 rdp
.flags
^= FOG_ENABLED
;
384 rdp
.update
|= UPDATE_FOG_ENABLED
;