Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/DepthBufferRender.cpp
2 views
1
/*
2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
* Copyright (c) 2008 Günther <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public
17
* Licence along with this program; if not, write to the Free
18
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA
20
*/
21
22
//****************************************************************
23
//
24
// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
25
// Project started on December 29th, 2001
26
//
27
// To modify Glide64:
28
// * 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.
29
// * 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.
30
//
31
// Official Glide64 development channel: #Glide64 on EFnet
32
//
33
//****************************************************************
34
//
35
// Software rendering into N64 depth buffer
36
// Idea and N64 depth value format by Orkin
37
// Polygon rasterization algorithm is taken from FATMAP2 engine by Mats Byggmastar, [email protected]
38
//
39
// Created by Gonetz, Dec 2004
40
//
41
//****************************************************************
42
43
#include "Gfx1.3.h"
44
#include "rdp.h"
45
#include "DepthBufferRender.h"
46
47
WORD * zLUT = 0;
48
49
void ZLUT_init()
50
{
51
if (zLUT)
52
return;
53
zLUT = new WORD[0x40000];
54
for(int i=0; i<0x40000; i++)
55
{
56
DWORD exponent = 0;
57
DWORD testbit = 1 << 17;
58
while((i & testbit) && (exponent < 7))
59
{
60
exponent++;
61
testbit = 1 << (17 - exponent);
62
}
63
64
DWORD mantissa = (i >> (6 - (6 < exponent ? 6 : exponent))) & 0x7ff;
65
zLUT[i] = (WORD)(((exponent << 11) | mantissa) << 2);
66
}
67
/*
68
for(i=0; i<0x40000; i++)
69
{
70
int j = i + 1;
71
WORD z = zLUT[i];
72
while (zLUT[i] == zLUT[j])
73
j++;
74
int w = (j - i) >> 2;
75
if (w > 0)
76
{
77
int k;
78
for (k = 1; k < 4; k++)
79
for (int t = 0; t < w; t++)
80
zLUT[i+k*w+t] = z + k;
81
i = j - 1;
82
}
83
}
84
*/
85
}
86
87
void ZLUT_release()
88
{
89
delete[] zLUT;
90
zLUT = 0;
91
}
92
93
static vertexi * max_vtx; // Max y vertex (ending vertex)
94
static vertexi * start_vtx, * end_vtx; // First and last vertex in array
95
static vertexi * right_vtx, * left_vtx; // Current right and left vertex
96
97
static int right_height, left_height;
98
static int right_x, right_dxdy, left_x, left_dxdy;
99
static int left_z, left_dzdy;
100
101
__inline int iceil(int x)
102
{
103
x += 0xffff;
104
return (x >> 16);
105
}
106
107
__inline int imul16(int x, int y) // (x * y) >> 16
108
{
109
return (((long long)x) * ((long long)y)) >> 16;
110
}
111
112
__inline int imul14(int x, int y) // (x * y) >> 14
113
{
114
return (((long long)x) * ((long long)y)) >> 14;
115
}
116
117
/*
118
int idiv16(int x, int y); // (x << 16) / y
119
#pragma aux idiv16 = \
120
" mov edx,eax "\
121
" sar edx,16 "\
122
" shl eax,16 "\
123
" idiv ebx "\
124
parm [eax] [ebx] modify exact [eax edx] value [eax]
125
*/
126
__inline int idiv16(int x, int y) // (x << 16) / y
127
{
128
//x = (((long long)x) << 16) / ((long long)y);
129
#if !defined(__GNUC__) && !defined(NO_ASM)
130
__asm {
131
mov eax, x
132
mov ebx, y
133
mov edx,eax
134
sar edx,16
135
shl eax,16
136
idiv ebx
137
mov x, eax
138
}
139
#elif !defined(NO_ASM)
140
int reminder;
141
asm ("idivl %[divisor]"
142
: "=a" (x), "=d" (reminder)
143
: [divisor] "g" (y), "d" (x >> 16), "a" (x << 16));
144
#endif
145
return x;
146
}
147
148
149
static void RightSection(void)
150
{
151
// Walk backwards trough the vertex array
152
153
vertexi * v2, * v1 = right_vtx;
154
if(right_vtx > start_vtx) v2 = right_vtx-1;
155
else v2 = end_vtx; // Wrap to end of array
156
right_vtx = v2;
157
158
// v1 = top vertex
159
// v2 = bottom vertex
160
161
// Calculate number of scanlines in this section
162
163
right_height = iceil(v2->y) - iceil(v1->y);
164
if(right_height <= 0) return;
165
166
// Guard against possible div overflows
167
168
if(right_height > 1) {
169
// OK, no worries, we have a section that is at least
170
// one pixel high. Calculate slope as usual.
171
172
int height = v2->y - v1->y;
173
right_dxdy = idiv16(v2->x - v1->x, height);
174
}
175
else {
176
// Height is less or equal to one pixel.
177
// Calculate slope = width * 1/height
178
// using 18:14 bit precision to avoid overflows.
179
180
int inv_height = (0x10000 << 14) / (v2->y - v1->y);
181
right_dxdy = imul14(v2->x - v1->x, inv_height);
182
}
183
184
// Prestep initial values
185
186
int prestep = (iceil(v1->y) << 16) - v1->y;
187
right_x = v1->x + imul16(prestep, right_dxdy);
188
}
189
190
static void LeftSection(void)
191
{
192
// Walk forward trough the vertex array
193
194
vertexi * v2, * v1 = left_vtx;
195
if(left_vtx < end_vtx) v2 = left_vtx+1;
196
else v2 = start_vtx; // Wrap to start of array
197
left_vtx = v2;
198
199
// v1 = top vertex
200
// v2 = bottom vertex
201
202
// Calculate number of scanlines in this section
203
204
left_height = iceil(v2->y) - iceil(v1->y);
205
if(left_height <= 0) return;
206
207
// Guard against possible div overflows
208
209
if(left_height > 1) {
210
// OK, no worries, we have a section that is at least
211
// one pixel high. Calculate slope as usual.
212
213
int height = v2->y - v1->y;
214
left_dxdy = idiv16(v2->x - v1->x, height);
215
left_dzdy = idiv16(v2->z - v1->z, height);
216
}
217
else {
218
// Height is less or equal to one pixel.
219
// Calculate slope = width * 1/height
220
// using 18:14 bit precision to avoid overflows.
221
222
int inv_height = (0x10000 << 14) / (v2->y - v1->y);
223
left_dxdy = imul14(v2->x - v1->x, inv_height);
224
left_dzdy = imul14(v2->z - v1->z, inv_height);
225
}
226
227
// Prestep initial values
228
229
int prestep = (iceil(v1->y) << 16) - v1->y;
230
left_x = v1->x + imul16(prestep, left_dxdy);
231
left_z = v1->z + imul16(prestep, left_dzdy);
232
}
233
234
235
void Rasterize(vertexi * vtx, int vertices, int dzdx)
236
{
237
start_vtx = vtx; // First vertex in array
238
239
// Search trough the vtx array to find min y, max y
240
// and the location of these structures.
241
242
vertexi * min_vtx = vtx;
243
max_vtx = vtx;
244
245
int min_y = vtx->y;
246
int max_y = vtx->y;
247
248
vtx++;
249
250
for(int n=1; n<vertices; n++) {
251
if(vtx->y < min_y) {
252
min_y = vtx->y;
253
min_vtx = vtx;
254
}
255
else
256
if(vtx->y > max_y) {
257
max_y = vtx->y;
258
max_vtx = vtx;
259
}
260
vtx++;
261
}
262
263
// OK, now we know where in the array we should start and
264
// where to end while scanning the edges of the polygon
265
266
left_vtx = min_vtx; // Left side starting vertex
267
right_vtx = min_vtx; // Right side starting vertex
268
end_vtx = vtx-1; // Last vertex in array
269
270
// Search for the first usable right section
271
272
do {
273
if(right_vtx == max_vtx) return;
274
RightSection();
275
} while(right_height <= 0);
276
277
// Search for the first usable left section
278
279
do {
280
if(left_vtx == max_vtx) return;
281
LeftSection();
282
} while(left_height <= 0);
283
284
WORD * destptr = (WORD*)(gfx.RDRAM+rdp.zimg);
285
int y1 = iceil(min_y);
286
int shift;
287
//destptr += iceil(min_y) * rdp.zi_width;
288
289
for(;;)
290
{
291
int x1 = iceil(left_x);
292
int width = iceil(right_x) - x1;
293
294
if(width > 0) {
295
296
// Prestep initial color intensity i
297
298
if (y1 >= rdp.zi_lry) return;
299
//if (x1+width > rdp.zi_lrx) width = rdp.zi_lrx-x1;
300
int prestep = (x1 << 16) - left_x;
301
int z = left_z + imul16(prestep, dzdx);
302
303
// if (y1 > max_y) return;
304
// FRDP("Depth render. x1: %d, y1: %d, width: %d\n", x1, y1, width);
305
shift = x1 + y1*rdp.zi_width;
306
// if (shift + width > rdp.zi_nb_pixels)
307
// return;
308
//draw to depth buffer
309
int trueZ;
310
int idx;
311
WORD encodedZ;
312
for (int x = 0; x < width; x++)
313
{
314
trueZ = z/8192;
315
if (trueZ < 0) trueZ = 0;
316
else if (trueZ > 0x3FFFF) trueZ = 0x3FFFF;
317
encodedZ = zLUT[trueZ];
318
idx = (shift+x)^1;
319
if(encodedZ < destptr[idx])
320
destptr[idx] = encodedZ;
321
z += dzdx;
322
}
323
}
324
325
//destptr += rdp.zi_width;
326
y1++;
327
328
// Scan the right side
329
330
if(--right_height <= 0) { // End of this section?
331
do {
332
if(right_vtx == max_vtx) return;
333
RightSection();
334
} while(right_height <= 0);
335
}
336
else
337
right_x += right_dxdy;
338
339
// Scan the left side
340
341
if(--left_height <= 0) { // End of this section?
342
do {
343
if(left_vtx == max_vtx) return;
344
LeftSection();
345
} while(left_height <= 0);
346
}
347
else {
348
left_x += left_dxdy;
349
left_z += left_dzdy;
350
}
351
}
352
}
353
354
355