trunk/src/mame/video/m3raster.inc
r32673 | r32674 | |
1 | | static void draw_scanline_normal(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) |
2 | | { |
3 | | const poly_extra_data *extra = (const poly_extra_data *)extradata; |
4 | | const cached_texture *texture = extra->texture; |
5 | | bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest; |
6 | | UINT32 *p = &destmap->pix32(scanline); |
7 | | UINT32 *d = &extra->zbuffer->pix32(scanline); |
8 | | float ooz = extent->param[0].start; |
9 | | float uoz = extent->param[1].start; |
10 | | float voz = extent->param[2].start; |
11 | | float doozdx = extent->param[0].dpdx; |
12 | | float duozdx = extent->param[1].dpdx; |
13 | | float dvozdx = extent->param[2].dpdx; |
14 | | UINT32 polyi = extra->polygon_intensity; |
15 | | UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
16 | | UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
17 | | UINT32 width = 6 + texture->width; |
18 | | int x; |
19 | | |
20 | | for (x = extent->startx; x < extent->stopx; x++) |
21 | | { |
22 | | UINT32 iz = ooz * 256.0f; |
23 | | if (iz > d[x]) |
24 | | { |
25 | | float z = 1.0f / ooz; |
26 | | UINT32 u = uoz * z; |
27 | | UINT32 v = voz * z; |
28 | | UINT32 u1 = (u >> 8) & umask; |
29 | | UINT32 v1 = (v >> 8) & vmask; |
30 | | UINT32 u2 = (u1 + 1) & umask; |
31 | | UINT32 v2 = (v1 + 1) & vmask; |
32 | | UINT32 pix00 = texture->data[(v1 << width) + u1]; |
33 | | UINT32 pix01 = texture->data[(v1 << width) + u2]; |
34 | | UINT32 pix10 = texture->data[(v2 << width) + u1]; |
35 | | UINT32 pix11 = texture->data[(v2 << width) + u2]; |
36 | | UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v); |
37 | | UINT32 fr = ((texel & 0x00ff0000) * polyi) >> 8; |
38 | | UINT32 fg = ((texel & 0x0000ff00) * polyi) >> 8; |
39 | | UINT32 fb = ((texel & 0x000000ff) * polyi) >> 8; |
40 | | p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff); |
41 | | d[x] = iz; |
42 | | } |
43 | | |
44 | | ooz += doozdx; |
45 | | uoz += duozdx; |
46 | | voz += dvozdx; |
47 | | } |
48 | | } |
49 | | |
50 | | static void draw_scanline_trans(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) |
51 | | { |
52 | | const poly_extra_data *extra = (const poly_extra_data *)extradata; |
53 | | const cached_texture *texture = extra->texture; |
54 | | bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest; |
55 | | UINT32 *p = &destmap->pix32(scanline); |
56 | | UINT32 *d = &extra->zbuffer->pix32(scanline); |
57 | | float ooz = extent->param[0].start; |
58 | | float uoz = extent->param[1].start; |
59 | | float voz = extent->param[2].start; |
60 | | float doozdx = extent->param[0].dpdx; |
61 | | float duozdx = extent->param[1].dpdx; |
62 | | float dvozdx = extent->param[2].dpdx; |
63 | | UINT32 polyi = (extra->polygon_intensity * extra->polygon_transparency) >> 5; |
64 | | int desttrans = 32 - extra->polygon_transparency; |
65 | | UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
66 | | UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
67 | | UINT32 width = 6 + texture->width; |
68 | | int x; |
69 | | |
70 | | for (x = extent->startx; x < extent->stopx; x++) |
71 | | { |
72 | | UINT32 iz = ooz * 256.0f; |
73 | | if (iz > d[x]) |
74 | | { |
75 | | float z = 1.0f / ooz; |
76 | | UINT32 u = uoz * z; |
77 | | UINT32 v = voz * z; |
78 | | UINT32 u1 = (u >> 8) & umask; |
79 | | UINT32 v1 = (v >> 8) & vmask; |
80 | | UINT32 u2 = (u1 + 1) & umask; |
81 | | UINT32 v2 = (v1 + 1) & vmask; |
82 | | UINT32 pix00 = texture->data[(v1 << width) + u1]; |
83 | | UINT32 pix01 = texture->data[(v1 << width) + u2]; |
84 | | UINT32 pix10 = texture->data[(v2 << width) + u1]; |
85 | | UINT32 pix11 = texture->data[(v2 << width) + u2]; |
86 | | UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v); |
87 | | UINT32 fr = ((texel & 0x00ff0000) * polyi) >> 8; |
88 | | UINT32 fg = ((texel & 0x0000ff00) * polyi) >> 8; |
89 | | UINT32 fb = ((texel & 0x000000ff) * polyi) >> 8; |
90 | | UINT32 orig = p[x]; |
91 | | fr += ((orig & 0x00ff0000) * desttrans) >> 5; |
92 | | fg += ((orig & 0x0000ff00) * desttrans) >> 5; |
93 | | fb += ((orig & 0x000000ff) * desttrans) >> 5; |
94 | | p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff); |
95 | | d[x] = iz; |
96 | | } |
97 | | |
98 | | ooz += doozdx; |
99 | | uoz += duozdx; |
100 | | voz += dvozdx; |
101 | | } |
102 | | } |
103 | | |
104 | | |
105 | | static void draw_scanline_alpha(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) |
106 | | { |
107 | | const poly_extra_data *extra = (const poly_extra_data *)extradata; |
108 | | const cached_texture *texture = extra->texture; |
109 | | bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest; |
110 | | UINT32 *p = &destmap->pix32(scanline); |
111 | | UINT32 *d = &extra->zbuffer->pix32(scanline); |
112 | | float ooz = extent->param[0].start; |
113 | | float uoz = extent->param[1].start; |
114 | | float voz = extent->param[2].start; |
115 | | float doozdx = extent->param[0].dpdx; |
116 | | float duozdx = extent->param[1].dpdx; |
117 | | float dvozdx = extent->param[2].dpdx; |
118 | | UINT32 polyi = (extra->polygon_intensity * extra->polygon_transparency) >> 5; |
119 | | int desttrans = 32 - extra->polygon_transparency; |
120 | | UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
121 | | UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
122 | | UINT32 width = 6 + texture->width; |
123 | | int x; |
124 | | |
125 | | for (x = extent->startx; x < extent->stopx; x++) |
126 | | { |
127 | | UINT32 iz = ooz * 256.0f; |
128 | | if (iz > d[x]) |
129 | | { |
130 | | float z = 1.0f / ooz; |
131 | | UINT32 u = uoz * z; |
132 | | UINT32 v = voz * z; |
133 | | UINT32 u1 = (u >> 8) & umask; |
134 | | UINT32 v1 = (v >> 8) & vmask; |
135 | | UINT32 u2 = (u1 + 1) & umask; |
136 | | UINT32 v2 = (v1 + 1) & vmask; |
137 | | UINT32 pix00 = texture->data[(v1 << width) + u1]; |
138 | | UINT32 pix01 = texture->data[(v1 << width) + u2]; |
139 | | UINT32 pix10 = texture->data[(v2 << width) + u1]; |
140 | | UINT32 pix11 = texture->data[(v2 << width) + u2]; |
141 | | UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v); |
142 | | UINT32 fa = texel >> 24; |
143 | | if (fa != 0) |
144 | | { |
145 | | UINT32 combined = ((fa + 1) * polyi) >> 8; |
146 | | UINT32 fr = ((texel & 0x00ff0000) * combined) >> (8+9); |
147 | | UINT32 fg = ((texel & 0x0000ff00) * combined) >> (8+6); |
148 | | UINT32 fb = ((texel & 0x000000ff) * combined) >> (8+3); |
149 | | UINT32 orig = p[x]; |
150 | | combined = ((255 - fa) * desttrans) >> 5; |
151 | | fr += ((orig & 0x00ff0000) * combined) >> 8; |
152 | | fg += ((orig & 0x0000ff00) * combined) >> 8; |
153 | | fb += ((orig & 0x000000ff) * combined) >> 8; |
154 | | p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff); |
155 | | d[x] = iz; |
156 | | } |
157 | | } |
158 | | |
159 | | ooz += doozdx; |
160 | | uoz += duozdx; |
161 | | voz += dvozdx; |
162 | | } |
163 | | } |
164 | | |
165 | | |
166 | | static void draw_scanline_alpha_test(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) |
167 | | { |
168 | | const poly_extra_data *extra = (const poly_extra_data *)extradata; |
169 | | const cached_texture *texture = extra->texture; |
170 | | bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest; |
171 | | UINT32 *p = &destmap->pix32(scanline); |
172 | | UINT32 *d = &extra->zbuffer->pix32(scanline); |
173 | | float ooz = extent->param[0].start; |
174 | | float uoz = extent->param[1].start; |
175 | | float voz = extent->param[2].start; |
176 | | float doozdx = extent->param[0].dpdx; |
177 | | float duozdx = extent->param[1].dpdx; |
178 | | float dvozdx = extent->param[2].dpdx; |
179 | | UINT32 polyi = (extra->polygon_intensity * extra->polygon_transparency) >> 5; |
180 | | int desttrans = 32 - extra->polygon_transparency; |
181 | | UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
182 | | UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
183 | | UINT32 width = 6 + texture->width; |
184 | | int x; |
185 | | |
186 | | for (x = extent->startx; x < extent->stopx; x++) |
187 | | { |
188 | | UINT32 iz = ooz * 256.0f; |
189 | | if (iz > d[x]) |
190 | | { |
191 | | float z = 1.0f / ooz; |
192 | | UINT32 u = uoz * z; |
193 | | UINT32 v = voz * z; |
194 | | UINT32 u1 = (u >> 8) & umask; |
195 | | UINT32 v1 = (v >> 8) & vmask; |
196 | | UINT32 u2 = (u1 + 1) & umask; |
197 | | UINT32 v2 = (v1 + 1) & vmask; |
198 | | UINT32 pix00 = texture->data[(v1 << width) + u1]; |
199 | | UINT32 pix01 = texture->data[(v1 << width) + u2]; |
200 | | UINT32 pix10 = texture->data[(v2 << width) + u1]; |
201 | | UINT32 pix11 = texture->data[(v2 << width) + u2]; |
202 | | UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v); |
203 | | UINT32 fa = texel >> 24; |
204 | | if (fa >= 0xf8) |
205 | | { |
206 | | UINT32 combined = ((fa + 1) * polyi) >> 8; |
207 | | UINT32 fr = ((texel & 0x00ff0000) * combined) >> (8+9); |
208 | | UINT32 fg = ((texel & 0x0000ff00) * combined) >> (8+6); |
209 | | UINT32 fb = ((texel & 0x000000ff) * combined) >> (8+3); |
210 | | UINT32 orig = p[x]; |
211 | | combined = ((255 - fa) * desttrans) >> 8; |
212 | | fr += ((orig & 0x00ff0000) * combined) >> 5; |
213 | | fg += ((orig & 0x0000ff00) * combined) >> 5; |
214 | | fb += ((orig & 0x000000ff) * combined) >> 5; |
215 | | p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff); |
216 | | d[x] = iz; |
217 | | } |
218 | | } |
219 | | |
220 | | ooz += doozdx; |
221 | | uoz += duozdx; |
222 | | voz += dvozdx; |
223 | | } |
224 | | } |
225 | | |
226 | | static void draw_scanline_color(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) |
227 | | { |
228 | | const poly_extra_data *extra = (const poly_extra_data *)extradata; |
229 | | bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest; |
230 | | UINT32 *p = &destmap->pix32(scanline); |
231 | | UINT32 *d = &extra->zbuffer->pix32(scanline); |
232 | | float ooz = extent->param[0].start; |
233 | | float doozdx = extent->param[0].dpdx; |
234 | | int fr = (extra->color & 0x7c00) << 9; |
235 | | int fg = (extra->color & 0x03e0) << 6; |
236 | | int fb = (extra->color & 0x001f) << 3; |
237 | | int x; |
238 | | |
239 | | // apply intensity |
240 | | fr = (fr * extra->polygon_intensity) >> 8; |
241 | | fg = (fg * extra->polygon_intensity) >> 8; |
242 | | fb = (fb * extra->polygon_intensity) >> 8; |
243 | | |
244 | | /* simple case: no transluceny */ |
245 | | if (extra->polygon_transparency >= 32) |
246 | | { |
247 | | UINT32 color = (fr & 0x7c00) | (fg & 0x03e0) | (fb & 0x1f); |
248 | | for (x = extent->startx; x < extent->stopx; x++) |
249 | | { |
250 | | UINT32 iz = ooz * 256.0f; |
251 | | if (iz > d[x]) |
252 | | { |
253 | | p[x] = color; |
254 | | d[x] = iz; |
255 | | } |
256 | | ooz += doozdx; |
257 | | } |
258 | | } |
259 | | |
260 | | /* translucency */ |
261 | | else |
262 | | { |
263 | | int polytrans = extra->polygon_transparency; |
264 | | |
265 | | fr = (fr * polytrans) >> 5; |
266 | | fg = (fg * polytrans) >> 5; |
267 | | fb = (fb * polytrans) >> 5; |
268 | | polytrans = 32 - polytrans; |
269 | | |
270 | | for (x = extent->startx; x < extent->stopx; x++) |
271 | | { |
272 | | UINT32 iz = ooz * 256.0f; |
273 | | if (iz > d[x]) |
274 | | { |
275 | | UINT32 orig = p[x]; |
276 | | int r = fr + (((orig & 0x00ff0000) * polytrans) >> 5); |
277 | | int g = fg + (((orig & 0x0000ff00) * polytrans) >> 5); |
278 | | int b = fb + (((orig & 0x000000ff) * polytrans) >> 5); |
279 | | |
280 | | p[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); |
281 | | d[x] = iz; |
282 | | } |
283 | | ooz += doozdx; |
284 | | } |
285 | | } |
286 | | } |
trunk/src/mame/video/model3.c
r32673 | r32674 | |
1 | 1 | #include "emu.h" |
2 | | #include "video/polylgcy.h" |
| 2 | #include "video/poly.h" |
3 | 3 | #include "video/rgbutil.h" |
4 | 4 | #include "includes/model3.h" |
5 | 5 | |
| 6 | #define ENABLE_BILINEAR 1 |
6 | 7 | |
7 | | #define pz p[0] |
8 | | #define pu p[1] |
9 | | #define pv p[2] |
| 8 | #define TRI_PARAM_TEXTURE_PAGE 0x1 |
| 9 | #define TRI_PARAM_TEXTURE_MIRROR_U 0x2 |
| 10 | #define TRI_PARAM_TEXTURE_MIRROR_V 0x4 |
| 11 | #define TRI_PARAM_TEXTURE_ENABLE 0x8 |
| 12 | #define TRI_PARAM_ALPHA_TEST 0x10 |
10 | 13 | |
11 | | |
12 | | struct cached_texture |
| 14 | struct model3_polydata |
13 | 15 | { |
14 | | cached_texture *next; |
15 | | UINT8 width; |
16 | | UINT8 height; |
17 | | UINT8 format; |
18 | | UINT8 alpha; |
19 | | rgb_t data[1]; |
| 16 | cached_texture *texture; |
| 17 | UINT32 color; |
| 18 | UINT32 texture_param; |
| 19 | int transparency; |
| 20 | int intensity; |
20 | 21 | }; |
21 | 22 | |
22 | | struct poly_extra_data |
| 23 | class model3_renderer : public poly_manager<float, model3_polydata, 6, 50000> |
23 | 24 | { |
24 | | cached_texture *texture; |
25 | | bitmap_ind32 *zbuffer; |
26 | | UINT32 color; |
27 | | UINT8 texture_param; |
28 | | int polygon_transparency; |
29 | | int polygon_intensity; |
| 25 | public: |
| 26 | model3_renderer(model3_state &state, int width, int height) |
| 27 | : poly_manager<float, model3_polydata, 6, 50000>(state.machine()), m_state(state) |
| 28 | { |
| 29 | m_fb = auto_bitmap_rgb32_alloc(state.machine(), width, height); |
| 30 | m_zb = auto_bitmap_ind32_alloc(state.machine(), width, height); |
| 31 | } |
| 32 | |
| 33 | void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 34 | void draw_triangle(const m3_triangle* tri); |
| 35 | void clear_buffers(); |
| 36 | void draw_scanline_solid(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); |
| 37 | void draw_scanline_tex(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); |
| 38 | void draw_scanline_contour(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); |
| 39 | void draw_scanline_tex_trans(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); |
| 40 | void draw_scanline_tex_alpha(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); |
| 41 | |
| 42 | private: |
| 43 | model3_state &m_state; |
| 44 | bitmap_rgb32 *m_fb; |
| 45 | bitmap_ind32 *m_zb; |
30 | 46 | }; |
31 | 47 | |
32 | | #define TRI_PARAM_TEXTURE_PAGE 0x1 |
33 | | #define TRI_PARAM_TEXTURE_MIRROR_U 0x2 |
34 | | #define TRI_PARAM_TEXTURE_MIRROR_V 0x4 |
35 | | #define TRI_PARAM_TEXTURE_ENABLE 0x8 |
36 | | #define TRI_PARAM_ALPHA_TEST 0x10 |
37 | 48 | |
38 | | #define MAX_TRIANGLES 131072 |
39 | 49 | |
40 | | |
41 | 50 | /*****************************************************************************/ |
42 | 51 | |
43 | 52 | /* matrix stack */ |
44 | 53 | #define MATRIX_STACK_SIZE 256 |
45 | 54 | |
46 | 55 | |
47 | | #ifdef UNUSED_DEFINITION |
48 | | static const int num_bits[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; |
49 | | #endif |
50 | | |
51 | | |
52 | | |
53 | | |
54 | | |
55 | 56 | #define BYTE_REVERSE32(x) (((x >> 24) & 0xff) | \ |
56 | 57 | ((x >> 8) & 0xff00) | \ |
57 | 58 | ((x << 8) & 0xff0000) | \ |
r32673 | r32674 | |
119 | 120 | fclose(file); |
120 | 121 | #endif |
121 | 122 | |
122 | | invalidate_texture(0, 0, 0, 6, 5); |
123 | | invalidate_texture(1, 0, 0, 6, 5); |
124 | | poly_free(m_poly); |
| 123 | // invalidate_texture(0, 0, 0, 6, 5); |
| 124 | // invalidate_texture(1, 0, 0, 6, 5); |
125 | 125 | } |
126 | 126 | |
127 | 127 | void model3_state::video_start() |
r32673 | r32674 | |
148 | 148 | 8 * 8*8 |
149 | 149 | }; |
150 | 150 | |
151 | | m_poly = poly_alloc(machine(), 4000, sizeof(poly_extra_data), 0); |
| 151 | int width = m_screen->width(); |
| 152 | int height = m_screen->height(); |
| 153 | |
| 154 | m_renderer = auto_alloc(machine(), model3_renderer(*this, width, height)); |
| 155 | |
152 | 156 | machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(model3_state::model3_exit), this)); |
153 | 157 | |
154 | | m_screen->register_screen_bitmap(m_bitmap3d); |
155 | | m_screen->register_screen_bitmap(m_zbuffer); |
156 | | |
157 | 158 | m_m3_char_ram = auto_alloc_array_clear(machine(), UINT64, 0x100000/8); |
158 | 159 | m_m3_tile_ram = auto_alloc_array_clear(machine(), UINT64, 0x8000/8); |
159 | 160 | |
r32673 | r32674 | |
170 | 171 | /* 4MB Polygon RAM */ |
171 | 172 | m_polygon_ram = auto_alloc_array_clear(machine(), UINT32, 0x400000/4); |
172 | 173 | |
173 | | m_tick = 0; |
174 | | m_debug_layer_disable = 0; |
175 | 174 | m_vid_reg0 = 0; |
176 | 175 | |
177 | 176 | m_viewport_focal_length = 300.; |
r32673 | r32674 | |
251 | 250 | const pen_t *pens = m_palette->pens(); |
252 | 251 | |
253 | 252 | UINT32* palram = (UINT32*)&m_paletteram64[0]; |
| 253 | UINT16* rowscroll_ram = (UINT16*)&m_m3_char_ram[0x1ec00]; |
254 | 254 | |
255 | 255 | int x1 = cliprect.min_x; |
256 | 256 | int y1 = cliprect.min_y; |
r32673 | r32674 | |
273 | 273 | UINT32* dst = &bitmap.pix32(y); |
274 | 274 | UINT16* src = &pixmap.pix16(iy & 0x1ff); |
275 | 275 | |
276 | | int iix = ix; |
| 276 | int rowscroll = BYTE_REVERSE16(rowscroll_ram[((layer * 0x200) + y) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0)]) & 0x7fff; |
| 277 | if (rowscroll & 0x100) |
| 278 | rowscroll |= ~0x1ff; |
277 | 279 | |
278 | | for (int x = x1; x <= x2; x++) |
| 280 | int iix = ix & 0x1ff; |
| 281 | |
| 282 | int rx1 = x1 - (rowscroll * 2); |
| 283 | int rx2 = x2 - (rowscroll * 2); |
| 284 | |
| 285 | if (rx1 < 0) |
279 | 286 | { |
| 287 | iix += (0 - rx1); |
| 288 | rx1 = 0; |
| 289 | } |
| 290 | if (rx2 > cliprect.max_x) |
| 291 | rx2 = cliprect.max_x; |
| 292 | |
| 293 | for (int x = rx1; x <= rx2; x++) |
| 294 | { |
280 | 295 | UINT16 p0 = src[iix & 0x1ff]; |
281 | 296 | if ((palram[p0^NATIVE_ENDIAN_VALUE_LE_BE(1,0)] & NATIVE_ENDIAN_VALUE_LE_BE(0x00800000,0x00008000)) == 0) |
282 | 297 | { |
283 | | *dst = pens[p0]; |
| 298 | dst[x] = pens[p0]; |
284 | 299 | } |
285 | | dst++; |
286 | 300 | iix++; |
287 | 301 | } |
288 | 302 | |
r32673 | r32674 | |
324 | 338 | draw_layer(bitmap, cliprect, 0, m_layer_priority & 0x10, layer_scroll_x[0], layer_scroll_y[0]); |
325 | 339 | |
326 | 340 | // render 3D |
327 | | draw_3d_layer(bitmap, cliprect); |
| 341 | m_renderer->draw(bitmap, cliprect); |
328 | 342 | |
329 | 343 | // render enabled layers with priority 1 |
330 | 344 | if ((layer_data[3] & 0x80000000) && (m_layer_priority & 0x8) != 0) |
r32673 | r32674 | |
336 | 350 | if ((layer_data[0] & 0x80000000) && (m_layer_priority & 0x1) != 0) |
337 | 351 | draw_layer(bitmap, cliprect, 0, m_layer_priority & 0x10, layer_scroll_x[0], layer_scroll_y[0]); |
338 | 352 | |
339 | | m_real3d_display_list = 0; |
340 | 353 | return 0; |
341 | 354 | } |
342 | 355 | |
r32673 | r32674 | |
620 | 633 | /*****************************************************************************/ |
621 | 634 | /* Real3D Graphics stuff */ |
622 | 635 | |
| 636 | /* |
| 637 | Real3D Pro-1000 capabilities: |
| 638 | |
| 639 | Coordinate sets |
| 640 | - 4096 matrices (matrix base pointer in viewport node) |
| 641 | |
| 642 | Polygons |
| 643 | - 32MB max polygon memory. VROM in Model 3, the low 4MB of VROM is overlaid by Polygon RAM for runtime generated content. |
| 644 | |
| 645 | Texture |
| 646 | - 2 texture sheets of 2048x1024 |
| 647 | - Mipmaps located in the bottom right corner |
| 648 | - Texture size 32x32 to 1024x1024 |
| 649 | - Microtextures (is this featured in Model 3?) |
| 650 | |
| 651 | LODs |
| 652 | - 127 blend types per viewport with 4 sets of min/max angle or range (where is this in the viewport node?) |
| 653 | |
| 654 | Lighting |
| 655 | - Self-luminous lighting (enable and luminosity parameter in polygon structure) |
| 656 | - Fixed polygon shading, fixed shading weight per vertex (not found in Model 3, yet) |
| 657 | - Flat sun shading (lighting parameters in viewport node) needs a separate enable? |
| 658 | - Smooth polygon shading (lighting parameters in viewport, use vertex normals) |
| 659 | |
| 660 | Gamma table |
| 661 | - 256 entry 8-bit table, possibly in Polygon RAM |
| 662 | */ |
| 663 | |
| 664 | /* |
| 665 | Real3D Memory Structures: |
| 666 | |
| 667 | Culling Nodes: |
| 668 | - Located in Culling RAM (0x8E000000) |
| 669 | - Limit of 15 child nodes (nesting), not including polygon nodes |
| 670 | - Color table (is this featured in Model 3?) |
| 671 | |
| 672 | 0x00: -------- -------- ------xx -------- Viewport number 0-3 |
| 673 | -------- -------- -------- ---xx--- Viewport priority |
| 674 | |
| 675 | 0x01: Child node pointer (inherits parameters from this node) |
| 676 | 0x02: Sibling node pointer |
| 677 | 0x03: Unknown (float) |
| 678 | 0x04: Sun light vector Z-component (float) |
| 679 | 0x05: Sun light vector X-component (float) |
| 680 | 0x06: Sun light vector Y-component (float) |
| 681 | 0x07: Sun light intensity (float) |
| 682 | 0x08: Far Clip plane Z |
| 683 | 0x09: Far Clip plane Distance |
| 684 | 0x0a: Near Clip plane Z |
| 685 | 0x0b: Near Clip plane Distance |
| 686 | 0x0c: Left Clip plane Z |
| 687 | 0x0d: Left Clip plane X |
| 688 | 0x0e: Top Clip plane Z |
| 689 | 0x0f: Top Clip plane Y |
| 690 | 0x10: Right Clip plane Z |
| 691 | 0x11: Right Clip plane X |
| 692 | 0x12: Bottom Clip plane Z |
| 693 | 0x13: Bottom Clip plane Y |
| 694 | |
| 695 | 0x14: xxxxxxxx xxxxxxxx -------- -------- Viewport height (14.2 fixed-point) |
| 696 | -------- -------- xxxxxxxx xxxxxxxx Viewport width (14.2 fixed-point) |
| 697 | |
| 698 | 0x15: ? |
| 699 | 0x16: Matrix base pointer |
| 700 | 0x17: LOD blend type table pointer? (seems to be 8x float per entry) |
| 701 | 0x18: ? |
| 702 | 0x19: ? |
| 703 | |
| 704 | 0x1a: xxxxxxxx xxxxxxxx -------- -------- Viewport Y coordinate (12.4 fixed-point) |
| 705 | -------- -------- xxxxxxxx xxxxxxxx Viewport X coordinate (12.4 fixed-point) |
| 706 | |
| 707 | 0x1b: Copy of word 0x00 |
| 708 | 0x1c: ? |
| 709 | |
| 710 | 0x1d: xxxxxxxx xxxxxxxx -------- -------- Spotlight Y size |
| 711 | -------- -------- xxxxxxxx xxxxxxxx Spotlight Y position (13.3 fixed-point?) |
| 712 | |
| 713 | 0x1e: xxxxxxxx xxxxxxxx -------- -------- Spotlight X size |
| 714 | -------- -------- xxxxxxxx xxxxxxxx Spotlight X position (13.3 fixed-point?) |
| 715 | |
| 716 | 0x1f: Light extent (float) |
| 717 | |
| 718 | 0x20: xxxxxxxx -------- -------- -------- ? |
| 719 | -------- xxxxxxxx -------- -------- ? |
| 720 | -------- -------- --xxx--- -------- Light RGB (RGB111?) |
| 721 | -------- -------- -----xxx -------- Light RGB Fog (RGB111?) |
| 722 | -------- -------- -------- xxxxxxxx Scroll Fog (0.8 fixed-point?) What is this??? |
| 723 | |
| 724 | 0x21: ? |
| 725 | 0x22: Fog Color (RGB888) |
| 726 | 0x23: Fog Density (float) |
| 727 | |
| 728 | 0x24: xxxxxxxx xxxxxxxx -------- -------- ? |
| 729 | -------- -------- xxxxxxxx -------- Sun light ambient (0.8 fixed-point) |
| 730 | -------- -------- -------- xxxxxxxx Scroll attenuation (0.8 fixed-point) What is this??? |
| 731 | |
| 732 | 0x25: Fog offset |
| 733 | 0x26: ? |
| 734 | 0x27: ? |
| 735 | 0x28: ? |
| 736 | 0x29: ? |
| 737 | 0x2a: ? |
| 738 | 0x2b: ? |
| 739 | 0x2c: ? |
| 740 | 0x2d: ? |
| 741 | 0x2e: ? |
| 742 | 0x2f: ? |
| 743 | |
| 744 | |
| 745 | Sub types: |
| 746 | LOD Culling Node. Up to 4 LODs. |
| 747 | |
| 748 | Articulated Part Culling Node (is this used by Model 3?) |
| 749 | - An Articulated Part culling node, or six degree–of–freedom node, is used to define |
| 750 | geometry that can move relative to the parent coordinate set to which it is attached. |
| 751 | Fifteen levels of coordinate set nesting (levels of articulation) are supported. |
| 752 | |
| 753 | Animation Culling Node |
| 754 | - Animation culling nodes are used to build a culling hierarchy for an object with different |
| 755 | representations, or animation frames. which can be turned on and off by the |
| 756 | application. Each child (culling node or polygon) added to an Animation culling node |
| 757 | specifies the frame for which the child is valid. |
| 758 | |
| 759 | Instance Culling Node |
| 760 | - Instance culling nodes define the top of a shared display list segment that can be |
| 761 | referenced from other parts of the scene display list. |
| 762 | |
| 763 | Instance Reference Culling Node |
| 764 | - An Instance Reference node is considered a leaf node; its |
| 765 | "child" is the shared geometry segment. An Instance Reference may be attached to |
| 766 | a parent node and may not have any other children, but may have siblings. |
| 767 | |
| 768 | Point Light |
| 769 | - A Point Light is used to create an instance of a point luminous feature. The size, |
| 770 | feature type, and number of sides of the point light model may be customized. |
| 771 | |
| 772 | Instance Set |
| 773 | - An Instance Set is a culling node which defines a set of point features. Each feature |
| 774 | is positioned individually. This type of culling node can be used to simulate particles. |
| 775 | |
| 776 | |
| 777 | |
| 778 | Instance Node? |
| 779 | |
| 780 | 0x00: xxxxxxxx xxxxxxxx xxxxxx-- -------- Node number/ID?, num of bits unknown |
| 781 | -------- -------- -------- ---x---- This node applies translation, else matrix |
| 782 | -------- -------- -------- ----x--- LOD enable? |
| 783 | -------- -------- -------- -----x-- ? |
| 784 | -------- -------- -------- ------x- ? |
| 785 | -------- -------- -------- -------x ? |
| 786 | |
| 787 | |
| 788 | 0x01: ? (not present on Step 1.0) |
| 789 | 0x02: ? (not present on Step 1.0) Scud Race has 0x00000101 |
| 790 | |
| 791 | 0x03: --x----- -------- -------- -------- ? |
| 792 | -------- -xxxxxxx xxxx---- -------- LOD? |
| 793 | -------- -------- ----xxxx xxxxxxxx Node matrix |
| 794 | |
| 795 | 0x04: Translation X coordinate |
| 796 | 0x05: Translation Y coordinate |
| 797 | 0x06: Translation Z coordinate |
| 798 | 0x07: Child node pointer |
| 799 | 0x08: Sibling node pointer |
| 800 | |
| 801 | 0x09: xxxxxxxx xxxxxxxx -------- -------- Culling or sorting related? |
| 802 | -------- -------- xxxxxxxx xxxxxxxx Culling or sorting related? |
| 803 | |
| 804 | |
| 805 | Polygon Data |
| 806 | |
| 807 | 0x00: -------- xxxxxxxx xxxxxx-- -------- Polygon ID |
| 808 | -------- -------- -------- -x------ 0 = Triangle, 1 = Quad |
| 809 | -------- -------- -------- ----x--- Vertex 3 shared from previous polygon |
| 810 | -------- -------- -------- -----x-- Vertex 2 shared from previous polygon |
| 811 | -------- -------- -------- ------x- Vertex 1 shared from previous polygon |
| 812 | -------- -------- -------- -------x Vertex 0 shared from previous polygon |
| 813 | xxxxxxxx -------- -------- x-xx---- ? |
| 814 | -------- -------- ------xx -------- Broken polygons in srally2 set these (a way to mark them for HW to not render?) |
| 815 | |
| 816 | 0x01: xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal X coordinate (2.22 fixed point) |
| 817 | -------- -------- -------- -x------ UV format (0 = 13.3, 1 = 16.0) |
| 818 | -------- -------- -------- -----x-- If set, this is the last polygon |
| 819 | -------- -------- -------- x-xxx-xx ? |
| 820 | |
| 821 | 0x02: xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Y coordinate (2.22 fixed point) |
| 822 | -------- -------- -------- ------x- Texture U mirror enable |
| 823 | -------- -------- -------- -------x Texture V mirror enable |
| 824 | -------- -------- -------- xxxxxx-- ? |
| 825 | |
| 826 | 0x03: xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Z coordinate (2.22 fixed point) |
| 827 | -------- -------- -------- --xxx--- Texture width (in 8-pixel tiles) |
| 828 | -------- -------- -------- -----xxx Texture height (in 8-pixel tiles) |
| 829 | |
| 830 | 0x04: xxxxxxxx xxxxxxxx xxxxxxxx -------- Color (RGB888) |
| 831 | -------- -------- -------- -x------ Texture page |
| 832 | -------- -------- -------- ---xxxxx Upper 5 bits of texture U coordinate |
| 833 | -------- -------- -------- x-x----- ? |
| 834 | |
| 835 | 0x05: xxxxxxxx xxxxxxxx xxxxxxxx -------- Specular color? |
| 836 | -------- -------- -------- x------- Low bit of texture U coordinate |
| 837 | -------- -------- -------- ---xxxxx Low 5 bits of texture V coordinate |
| 838 | -------- -------- -------- -xx----- ? |
| 839 | |
| 840 | 0x06: x------- -------- -------- -------- Texture contour enable |
| 841 | -----x-- -------- -------- -------- Texture enable |
| 842 | -------- x------- -------- -------- 1 = disable transparency? |
| 843 | -------- -xxxxx-- -------- -------- Polygon transparency (0 = fully transparent) |
| 844 | -------- -------x -------- -------- 1 = disable lighting |
| 845 | -------- -------- xxxxx--- -------- Polygon luminosity |
| 846 | -------- -------- ------xx x------- Texture format |
| 847 | -------- -------- -------- -------x Alpha enable? |
| 848 | -xxxx-xx ------x- -----x-- -xxxxxx- ? |
| 849 | |
| 850 | |
| 851 | Vertex entry |
| 852 | |
| 853 | 0x00: xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex X coordinate (17.7 fixed-point in Step 1.0, 13.11 otherwise) |
| 854 | -------- -------- -------- xxxxxxxx Vertex normal X (offset from polygon normal) |
| 855 | |
| 856 | 0x01: xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex Y coordinate |
| 857 | -------- -------- -------- xxxxxxxx Vertex normal Y |
| 858 | |
| 859 | 0x02: xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex Z coordinate |
| 860 | -------- -------- -------- xxxxxxxx Vertex normal Z |
| 861 | |
| 862 | 0x03: xxxxxxxx xxxxxxxx -------- -------- Vertex U coordinate |
| 863 | -------- -------- xxxxxxxx xxxxxxxx Vertex V coordinate |
| 864 | |
| 865 | */ |
| 866 | |
| 867 | |
623 | 868 | WRITE64_MEMBER(model3_state::real3d_display_list_w) |
624 | 869 | { |
625 | | if(ACCESSING_BITS_32_63) { |
| 870 | if (ACCESSING_BITS_32_63) |
| 871 | { |
626 | 872 | m_display_list_ram[offset*2] = BYTE_REVERSE32((UINT32)(data >> 32)); |
627 | 873 | } |
628 | | if(ACCESSING_BITS_0_31) { |
| 874 | if (ACCESSING_BITS_0_31) |
| 875 | { |
629 | 876 | m_display_list_ram[(offset*2)+1] = BYTE_REVERSE32((UINT32)(data)); |
630 | 877 | } |
631 | 878 | } |
632 | 879 | |
633 | 880 | WRITE64_MEMBER(model3_state::real3d_polygon_ram_w) |
634 | 881 | { |
635 | | if(ACCESSING_BITS_32_63) { |
| 882 | if (ACCESSING_BITS_32_63) |
| 883 | { |
636 | 884 | m_polygon_ram[offset*2] = BYTE_REVERSE32((UINT32)(data >> 32)); |
637 | 885 | } |
638 | | if(ACCESSING_BITS_0_31) { |
| 886 | if (ACCESSING_BITS_0_31) |
| 887 | { |
639 | 888 | m_polygon_ram[(offset*2)+1] = BYTE_REVERSE32((UINT32)(data)); |
640 | 889 | } |
641 | 890 | } |
642 | 891 | |
643 | 892 | static const UINT8 texture_decode[64] = |
644 | 893 | { |
645 | | 0, 1, 4, 5, 8, 9, 12, 13, |
646 | | 2, 3, 6, 7, 10, 11, 14, 15, |
| 894 | 0, 1, 4, 5, 8, 9, 12, 13, |
| 895 | 2, 3, 6, 7, 10, 11, 14, 15, |
647 | 896 | 16, 17, 20, 21, 24, 25, 28, 29, |
648 | 897 | 18, 19, 22, 23, 26, 27, 30, 31, |
649 | 898 | 32, 33, 36, 37, 40, 41, 44, 45, |
r32673 | r32674 | |
753 | 1002 | } |
754 | 1003 | m_texture_fifo_pos = 0; |
755 | 1004 | |
756 | | m_zbuffer.fill(0); |
757 | | m_bitmap3d.fill(0); |
| 1005 | m_renderer->clear_buffers(); |
758 | 1006 | |
759 | 1007 | real3d_traverse_display_list(); |
760 | 1008 | } |
r32673 | r32674 | |
765 | 1013 | int d = (dst & 0xffffff) / 4; |
766 | 1014 | for (int i = 0; i < length; i += 4) |
767 | 1015 | { |
768 | | UINT32 w; |
769 | | if (byteswap) { |
770 | | w = BYTE_REVERSE32(space.read_dword(src)); |
771 | | } else { |
772 | | w = space.read_dword(src); |
773 | | } |
| 1016 | UINT32 w = space.read_dword(src); |
| 1017 | |
| 1018 | if (byteswap) |
| 1019 | w = BYTE_REVERSE32(w); |
| 1020 | |
774 | 1021 | m_display_list_ram[d++] = w; |
775 | 1022 | src += 4; |
776 | 1023 | } |
r32673 | r32674 | |
782 | 1029 | int d = (dst & 0xffffff) / 4; |
783 | 1030 | for (int i = 0; i < length; i += 4) |
784 | 1031 | { |
785 | | UINT32 w; |
786 | | if (byteswap) { |
787 | | w = BYTE_REVERSE32(space.read_dword(src)); |
788 | | } else { |
789 | | w = space.read_dword(src); |
790 | | } |
| 1032 | UINT32 w = space.read_dword(src); |
| 1033 | |
| 1034 | if (byteswap) |
| 1035 | w = BYTE_REVERSE32(w); |
| 1036 | |
791 | 1037 | m_culling_ram[d++] = w; |
792 | 1038 | src += 4; |
793 | 1039 | } |
r32673 | r32674 | |
800 | 1046 | { |
801 | 1047 | for (int i=0; i < length; i+=12) |
802 | 1048 | { |
803 | | UINT32 address, header; |
| 1049 | UINT32 address = space.read_dword(src+i+0); |
| 1050 | UINT32 header = space.read_dword(src+i+4); |
804 | 1051 | |
805 | | if (byteswap) { |
806 | | address = BYTE_REVERSE32(space.read_dword((src+i+0))); |
807 | | header = BYTE_REVERSE32(space.read_dword((src+i+4))); |
808 | | } else { |
809 | | address = space.read_dword((src+i+0)); |
810 | | header = space.read_dword((src+i+4)); |
| 1052 | if (byteswap) |
| 1053 | { |
| 1054 | address = BYTE_REVERSE32(address); |
| 1055 | header = BYTE_REVERSE32(header); |
811 | 1056 | } |
| 1057 | |
812 | 1058 | real3d_upload_texture(header, (UINT32*)&m_vrom[address]); |
813 | 1059 | } |
814 | 1060 | } |
r32673 | r32674 | |
819 | 1065 | address_space &space = m_maincpu->space(AS_PROGRAM); |
820 | 1066 | for (int i = 0; i < length; i += 4) |
821 | 1067 | { |
822 | | UINT32 w; |
823 | | if (byteswap) { |
824 | | w = BYTE_REVERSE32(space.read_dword(src)); |
825 | | } else { |
826 | | w = space.read_dword(src); |
827 | | } |
| 1068 | UINT32 w = space.read_dword(src); |
| 1069 | |
| 1070 | if (byteswap) |
| 1071 | w = BYTE_REVERSE32(w); |
| 1072 | |
828 | 1073 | m_texture_fifo[m_texture_fifo_pos] = w; |
829 | 1074 | m_texture_fifo_pos++; |
830 | 1075 | src += 4; |
r32673 | r32674 | |
837 | 1082 | int d = (dst & 0xffffff) / 4; |
838 | 1083 | for (int i = 0; i < length; i += 4) |
839 | 1084 | { |
840 | | UINT32 w; |
841 | | if (byteswap) { |
842 | | w = BYTE_REVERSE32(space.read_dword(src)); |
843 | | } else { |
844 | | w = space.read_dword(src); |
845 | | } |
| 1085 | UINT32 w = space.read_dword(src); |
| 1086 | |
| 1087 | if (byteswap) |
| 1088 | w = BYTE_REVERSE32(w); |
| 1089 | |
846 | 1090 | m_polygon_ram[d++] = w; |
847 | 1091 | src += 4; |
848 | 1092 | } |
r32673 | r32674 | |
857 | 1101 | /*****************************************************************************/ |
858 | 1102 | /* matrix and vector operations */ |
859 | 1103 | |
860 | | #ifdef UNUSED_FUNCTION |
861 | | INLINE float dot_product(VECTOR a, VECTOR b) |
862 | | { |
863 | | return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]) + (a[3] * b[3]); |
864 | | } |
865 | | #endif |
866 | | |
867 | 1104 | INLINE float dot_product3(VECTOR3 a, VECTOR3 b) |
868 | 1105 | { |
869 | 1106 | return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); |
r32673 | r32674 | |
959 | 1196 | /*****************************************************************************/ |
960 | 1197 | /* transformation and rasterizing */ |
961 | 1198 | |
962 | | #include "m3raster.inc" |
963 | | |
964 | | INLINE int is_point_inside(float x, float y, float z, PLANE cp) |
| 1199 | INLINE bool is_point_inside(float x, float y, float z, m3_plane cp) |
965 | 1200 | { |
966 | 1201 | float s = (x * cp.x) + (y * cp.y) + (z * cp.z) + cp.d; |
967 | 1202 | if (s >= 0.0f) |
968 | | return 1; |
| 1203 | return true; |
969 | 1204 | else |
970 | | return 0; |
| 1205 | return false; |
971 | 1206 | } |
972 | 1207 | |
973 | | INLINE float line_plane_intersection(const poly_vertex *v1, const poly_vertex *v2, PLANE cp) |
| 1208 | INLINE float line_plane_intersection(const m3_clip_vertex *v1, const m3_clip_vertex *v2, m3_plane cp) |
974 | 1209 | { |
975 | 1210 | float x = v1->x - v2->x; |
976 | 1211 | float y = v1->y - v2->y; |
977 | | float z = v1->pz - v2->pz; |
978 | | float t = ((cp.x * v1->x) + (cp.y * v1->y) + (cp.z * v1->pz)) / ((cp.x * x) + (cp.y * y) + (cp.z * z)); |
| 1212 | float z = v1->z - v2->z; |
| 1213 | float t = ((cp.x * v1->x) + (cp.y * v1->y) + (cp.z * v1->z)) / ((cp.x * x) + (cp.y * y) + (cp.z * z)); |
979 | 1214 | return t; |
980 | 1215 | } |
981 | 1216 | |
982 | | static int clip_polygon(const poly_vertex *v, int num_vertices, PLANE cp, poly_vertex *vout) |
| 1217 | static int clip_polygon(const m3_clip_vertex *v, int num_vertices, m3_plane cp, m3_clip_vertex *vout) |
983 | 1218 | { |
984 | | poly_vertex clipv[10]; |
| 1219 | m3_clip_vertex clipv[10]; |
985 | 1220 | int clip_verts = 0; |
986 | 1221 | float t; |
987 | 1222 | int i; |
r32673 | r32674 | |
990 | 1225 | |
991 | 1226 | for (i=0; i < num_vertices; i++) |
992 | 1227 | { |
993 | | int v1_in = is_point_inside(v[i].x, v[i].y, v[i].pz, cp); |
994 | | int v2_in = is_point_inside(v[previ].x, v[previ].y, v[previ].pz, cp); |
| 1228 | bool v1_in = is_point_inside(v[i].x, v[i].y, v[i].z, cp); |
| 1229 | bool v2_in = is_point_inside(v[previ].x, v[previ].y, v[previ].z, cp); |
995 | 1230 | |
996 | 1231 | if (v1_in && v2_in) /* edge is completely inside the volume */ |
997 | 1232 | { |
r32673 | r32674 | |
1004 | 1239 | t = line_plane_intersection(&v[i], &v[previ], cp); |
1005 | 1240 | clipv[clip_verts].x = v[i].x + ((v[previ].x - v[i].x) * t); |
1006 | 1241 | clipv[clip_verts].y = v[i].y + ((v[previ].y - v[i].y) * t); |
1007 | | clipv[clip_verts].pz = v[i].pz + ((v[previ].pz - v[i].pz) * t); |
1008 | | clipv[clip_verts].pu = v[i].pu + ((v[previ].pu - v[i].pu) * t); |
1009 | | clipv[clip_verts].pv = v[i].pv + ((v[previ].pv - v[i].pv) * t); |
| 1242 | clipv[clip_verts].z = v[i].z + ((v[previ].z - v[i].z) * t); |
| 1243 | clipv[clip_verts].u = v[i].u + ((v[previ].u - v[i].u) * t); |
| 1244 | clipv[clip_verts].v = v[i].v + ((v[previ].v - v[i].v) * t); |
| 1245 | clipv[clip_verts].i = v[i].i + ((v[previ].i - v[i].i) * t); |
1010 | 1246 | ++clip_verts; |
1011 | 1247 | } |
1012 | 1248 | else if (v1_in && !v2_in) /* edge is leaving the volume */ |
r32673 | r32674 | |
1015 | 1251 | t = line_plane_intersection(&v[i], &v[previ], cp); |
1016 | 1252 | clipv[clip_verts].x = v[i].x + ((v[previ].x - v[i].x) * t); |
1017 | 1253 | clipv[clip_verts].y = v[i].y + ((v[previ].y - v[i].y) * t); |
1018 | | clipv[clip_verts].pz = v[i].pz + ((v[previ].pz - v[i].pz) * t); |
1019 | | clipv[clip_verts].pu = v[i].pu + ((v[previ].pu - v[i].pu) * t); |
1020 | | clipv[clip_verts].pv = v[i].pv + ((v[previ].pv - v[i].pv) * t); |
| 1254 | clipv[clip_verts].z = v[i].z + ((v[previ].z - v[i].z) * t); |
| 1255 | clipv[clip_verts].u = v[i].u + ((v[previ].u - v[i].u) * t); |
| 1256 | clipv[clip_verts].v = v[i].v + ((v[previ].v - v[i].v) * t); |
| 1257 | clipv[clip_verts].i = v[i].i + ((v[previ].i - v[i].i) * t); |
1021 | 1258 | ++clip_verts; |
1022 | 1259 | |
1023 | 1260 | /* insert the existing vertex */ |
r32673 | r32674 | |
1031 | 1268 | return clip_verts; |
1032 | 1269 | } |
1033 | 1270 | |
1034 | | void model3_state::render_one(TRIANGLE *tri) |
1035 | | { |
1036 | | poly_extra_data *extra = (poly_extra_data *)poly_get_extra_data(m_poly); |
1037 | | poly_draw_scanline_func callback = NULL; |
1038 | | |
1039 | | tri->v[0].pz = 1.0f / tri->v[0].pz; |
1040 | | tri->v[1].pz = 1.0f / tri->v[1].pz; |
1041 | | tri->v[2].pz = 1.0f / tri->v[2].pz; |
1042 | | |
1043 | | extra->zbuffer = &m_zbuffer; |
1044 | | if (tri->param & TRI_PARAM_TEXTURE_ENABLE) |
1045 | | { |
1046 | | tri->v[0].pu = tri->v[0].pu * tri->v[0].pz * 256.0f; |
1047 | | tri->v[0].pv = tri->v[0].pv * tri->v[0].pz * 256.0f; |
1048 | | tri->v[1].pu = tri->v[1].pu * tri->v[1].pz * 256.0f; |
1049 | | tri->v[1].pv = tri->v[1].pv * tri->v[1].pz * 256.0f; |
1050 | | tri->v[2].pu = tri->v[2].pu * tri->v[2].pz * 256.0f; |
1051 | | tri->v[2].pv = tri->v[2].pv * tri->v[2].pz * 256.0f; |
1052 | | |
1053 | | extra->texture = get_texture((tri->param & TRI_PARAM_TEXTURE_PAGE) ? 1 : 0, tri->texture_x, tri->texture_y, tri->texture_width, tri->texture_height, tri->texture_format); |
1054 | | extra->texture_param = tri->param; |
1055 | | extra->polygon_transparency = tri->transparency; |
1056 | | extra->polygon_intensity = tri->intensity; |
1057 | | |
1058 | | if (tri->param & TRI_PARAM_ALPHA_TEST) |
1059 | | callback = draw_scanline_alpha_test; |
1060 | | else if (extra->texture->alpha == 0xff) |
1061 | | callback = (tri->transparency >= 32) ? draw_scanline_normal : draw_scanline_trans; |
1062 | | else |
1063 | | callback = draw_scanline_alpha; |
1064 | | poly_render_triangle(m_poly, &m_bitmap3d, m_clip3d, callback, 3, &tri->v[0], &tri->v[1], &tri->v[2]); |
1065 | | } |
1066 | | else |
1067 | | { |
1068 | | extra->polygon_transparency = tri->transparency; |
1069 | | extra->polygon_intensity = tri->intensity; |
1070 | | extra->color = tri->color; |
1071 | | |
1072 | | poly_render_triangle(m_poly, &m_bitmap3d, m_clip3d, draw_scanline_color, 1, &tri->v[0], &tri->v[1], &tri->v[2]); |
1073 | | } |
1074 | | } |
1075 | | |
1076 | 1271 | void model3_state::draw_model(UINT32 addr) |
1077 | 1272 | { |
| 1273 | // Polygon RAM is mapped to the low 4MB of VROM |
1078 | 1274 | UINT32 *model = (addr >= 0x100000) ? &m_vrom[addr] : &m_polygon_ram[addr]; |
| 1275 | |
1079 | 1276 | UINT32 header[7]; |
1080 | 1277 | int index = 0; |
1081 | 1278 | int last_polygon = FALSE, first_polygon = TRUE, back_face = FALSE; |
1082 | 1279 | int num_vertices; |
1083 | 1280 | int i, v, vi; |
1084 | 1281 | float fixed_point_fraction; |
1085 | | poly_vertex vertex[4]; |
1086 | | poly_vertex prev_vertex[4]; |
1087 | | poly_vertex clip_vert[10]; |
| 1282 | m3_vertex vertex[4]; |
| 1283 | m3_vertex prev_vertex[4]; |
| 1284 | m3_clip_vertex clip_vert[10]; |
1088 | 1285 | |
1089 | 1286 | MATRIX transform_matrix; |
1090 | 1287 | float center_x, center_y; |
1091 | 1288 | |
1092 | | if(m_step < 0x15) { /* position coordinates are 17.15 fixed-point in Step 1.0 */ |
1093 | | fixed_point_fraction = 1.0f / 32768.0f; |
1094 | | } else { /* 13.19 fixed-point in other Steps */ |
1095 | | fixed_point_fraction = 1.0f / 524288.0f; |
1096 | | } |
1097 | | |
| 1289 | if (m_step < 0x15) // position coordinates are 17.7 fixed-point in Step 1.0 |
| 1290 | fixed_point_fraction = 1.0f / 128.0f; |
| 1291 | else // 13.11 fixed-point in other Steps |
| 1292 | fixed_point_fraction = 1.0f / 2048.0f; |
| 1293 | |
1098 | 1294 | get_top_matrix(&transform_matrix); |
1099 | 1295 | |
1100 | 1296 | /* current viewport center coordinates on screen */ |
r32673 | r32674 | |
1110 | 1306 | VECTOR3 normal; |
1111 | 1307 | VECTOR3 sn; |
1112 | 1308 | VECTOR p[4]; |
1113 | | TRIANGLE tri; |
| 1309 | m3_triangle tri; |
1114 | 1310 | float dot; |
1115 | | int intensity; |
1116 | 1311 | int polygon_transparency; |
1117 | 1312 | |
1118 | | // |
1119 | | // Header bits: |
1120 | | // |
1121 | | // 0:00FFFC00 - polygon ID |
1122 | | // 0:00000300 - ???? |
1123 | | // 0:00000040 - if set, indicates a quad, else it's a triangle |
1124 | | // 0:00000008 - inherit vertex 3 from previous polygon |
1125 | | // 0:00000004 - inherit vertex 2 from previous polygon |
1126 | | // 0:00000002 - inherit vertex 1 from previous polygon |
1127 | | // 0:00000001 - inherit vertex 0 from previous polygon |
1128 | | // |
1129 | | // 1:FFFFFF00 - polygon normal X coordinate, 2.22 |
1130 | | // 1:00000040 - if set, U/V is as-is, else divide U/V by 8 |
1131 | | // 1:00000004 - if set, indicates last polygon in model |
1132 | | // |
1133 | | // 2:FFFFFF00 - polygon normal Y coordinate, 2.22 |
1134 | | // 2:00000002 - if set, mirror texture in U |
1135 | | // 2:00000001 - if set, mirror texture in V |
1136 | | // |
1137 | | // 3:FFFFFF00 - polygon normal Z coordinate, 2.22 |
1138 | | // 3:00000038 - texture width, in tiles |
1139 | | // 3:00000007 - texture height, in tiles |
1140 | | // |
1141 | | // 4:FFFFFF00 - RGB lighting color |
1142 | | // 4:00000040 - texture page |
1143 | | // 4:0000001F - upper 5 bits of texture X coordinate |
1144 | | // |
1145 | | // 5:00000080 - low bit of texture X coordinate |
1146 | | // 5:0000001F - low 5 bits of texture Y coordinate |
1147 | | // |
1148 | | // 6:80000000 - if set, enable alpha test |
1149 | | // 6:04000000 - if set, textures enabled |
1150 | | // 6:00800000 - if set, force transparency off |
1151 | | // 6:007C0000 - 5-bit transparency value (0 is transparent, 0x1F is nearly opaque) |
1152 | | // 6:00010000 - if set, disable lighting |
1153 | | // 6:0000F800 - 5-bit additional color control |
1154 | | // 6:00000380 - 3-bit texture format |
1155 | | // 6:00000001 - alpha enable? |
1156 | | // |
1157 | | |
1158 | 1313 | for (i = 0; i < 7; i++) |
1159 | 1314 | header[i] = model[index++]; |
1160 | 1315 | |
r32673 | r32674 | |
1168 | 1323 | if (header[1] & 0x4) |
1169 | 1324 | last_polygon = TRUE; |
1170 | 1325 | |
| 1326 | if ((header[0] & 0x300) == 0x300) // TODO: broken polygons in srally2 have these bits set |
| 1327 | return; |
| 1328 | |
1171 | 1329 | num_vertices = (header[0] & 0x40) ? 4 : 3; |
1172 | 1330 | |
1173 | 1331 | /* texture coordinates are 16.0 or 13.3 fixed-point */ |
r32673 | r32674 | |
1187 | 1345 | /* load new vertices */ |
1188 | 1346 | for ( ; vi < num_vertices; vi++) |
1189 | 1347 | { |
1190 | | if ((model[index+0] & 0xf0000000) == 0x70000000 || |
1191 | | (model[index+1] & 0xf0000000) == 0x70000000 || |
1192 | | (model[index+2] & 0xf0000000) == 0x70000000) |
1193 | | return; |
| 1348 | UINT32 xw = model[index++]; |
| 1349 | UINT32 yw = model[index++]; |
| 1350 | UINT32 zw = model[index++]; |
1194 | 1351 | |
1195 | | vertex[vi].x = (float)((INT32)model[index++]) * fixed_point_fraction; |
1196 | | vertex[vi].y = (float)((INT32)model[index++]) * fixed_point_fraction; |
1197 | | vertex[vi].pz = (float)((INT32)model[index++]) * fixed_point_fraction; |
1198 | | vertex[vi].pu = (UINT16)(model[index] >> 16); |
1199 | | vertex[vi].pv = (UINT16)(model[index++]); |
| 1352 | vertex[vi].x = (float)((INT32)(xw) >> 8) * fixed_point_fraction; |
| 1353 | vertex[vi].y = (float)((INT32)(yw) >> 8) * fixed_point_fraction; |
| 1354 | vertex[vi].z = (float)((INT32)(zw) >> 8) * fixed_point_fraction; |
| 1355 | vertex[vi].u = (UINT16)(model[index] >> 16); |
| 1356 | vertex[vi].v = (UINT16)(model[index++]); |
| 1357 | // vertex[vi].nx = normal[0] + ((float)((INT8)(xw)) / 127.0f); |
| 1358 | // vertex[vi].ny = normal[1] + ((float)((INT8)(yw)) / 127.0f); |
| 1359 | // vertex[vi].nz = normal[2] + ((float)((INT8)(zw)) / 127.0f); |
| 1360 | |
| 1361 | vertex[vi].nx = ((float)((INT8)(xw)) / 127.0f); |
| 1362 | vertex[vi].ny = ((float)((INT8)(yw)) / 127.0f); |
| 1363 | vertex[vi].nz = ((float)((INT8)(zw)) / 127.0f); |
1200 | 1364 | } |
1201 | 1365 | |
1202 | 1366 | /* Copy current vertices as previous vertices */ |
1203 | | memcpy(prev_vertex, vertex, sizeof(poly_vertex) * 4); |
| 1367 | memcpy(prev_vertex, vertex, sizeof(m3_vertex) * 4); |
1204 | 1368 | |
1205 | | color = (((header[4] >> 27) & 0x1f) << 10) | (((header[4] >> 19) & 0x1f) << 5) | ((header[4] >> 11) & 0x1f); |
| 1369 | color = (header[4] >> 8) & 0xffffff; |
1206 | 1370 | polygon_transparency = (header[6] & 0x800000) ? 32 : ((header[6] >> 18) & 0x1f); |
1207 | 1371 | |
1208 | 1372 | /* transform polygon normal to view-space */ |
r32673 | r32674 | |
1220 | 1384 | sn[1] *= m_coordinate_system[1][2]; |
1221 | 1385 | sn[2] *= m_coordinate_system[2][0]; |
1222 | 1386 | |
1223 | | /* TODO: depth bias */ |
1224 | | /* transform vertices */ |
| 1387 | // TODO: depth bias |
| 1388 | // transform and light vertices |
1225 | 1389 | for (i = 0; i < num_vertices; i++) |
1226 | 1390 | { |
1227 | 1391 | VECTOR vect; |
1228 | 1392 | |
1229 | 1393 | vect[0] = vertex[i].x; |
1230 | 1394 | vect[1] = vertex[i].y; |
1231 | | vect[2] = vertex[i].pz; |
| 1395 | vect[2] = vertex[i].z; |
1232 | 1396 | vect[3] = 1.0f; |
1233 | 1397 | |
1234 | | /* transform to world-space */ |
| 1398 | // transform to world-space |
1235 | 1399 | matrix_multiply_vector(transform_matrix, vect, &p[i]); |
1236 | 1400 | |
1237 | | /* apply coordinate system */ |
| 1401 | // apply coordinate system |
1238 | 1402 | clip_vert[i].x = p[i][0] * m_coordinate_system[0][1]; |
1239 | 1403 | clip_vert[i].y = p[i][1] * m_coordinate_system[1][2]; |
1240 | | clip_vert[i].pz = p[i][2] * m_coordinate_system[2][0]; |
1241 | | clip_vert[i].pu = vertex[i].pu * texture_coord_scale; |
1242 | | clip_vert[i].pv = vertex[i].pv * texture_coord_scale; |
| 1404 | clip_vert[i].z = p[i][2] * m_coordinate_system[2][0]; |
| 1405 | clip_vert[i].u = vertex[i].u * texture_coord_scale; |
| 1406 | clip_vert[i].v = vertex[i].v * texture_coord_scale; |
| 1407 | |
| 1408 | // transform vertex normal |
| 1409 | VECTOR3 n; |
| 1410 | n[0] = (vertex[i].nx * transform_matrix[0][0]) + |
| 1411 | (vertex[i].ny * transform_matrix[1][0]) + |
| 1412 | (vertex[i].nz * transform_matrix[2][0]); |
| 1413 | n[0] *= m_coordinate_system[0][1]; |
| 1414 | n[1] = (vertex[i].nx * transform_matrix[0][1]) + |
| 1415 | (vertex[i].ny * transform_matrix[1][1]) + |
| 1416 | (vertex[i].nz * transform_matrix[2][1]); |
| 1417 | n[1] *= m_coordinate_system[1][2]; |
| 1418 | n[2] = (vertex[i].nx * transform_matrix[0][2]) + |
| 1419 | (vertex[i].ny * transform_matrix[1][2]) + |
| 1420 | (vertex[i].nz * transform_matrix[2][2]); |
| 1421 | n[2] *= m_coordinate_system[2][0]; |
| 1422 | |
| 1423 | // lighting |
| 1424 | float intensity; |
| 1425 | if ((header[6] & 0x10000) == 0) |
| 1426 | { |
| 1427 | dot = dot_product3(n, m_parallel_light); |
| 1428 | intensity = ((dot * m_parallel_light_intensity) + m_ambient_light_intensity) * 255.0f; |
| 1429 | if (intensity > 255.0f) |
| 1430 | { |
| 1431 | intensity = 255.0f; |
| 1432 | } |
| 1433 | if (intensity < 0.0f) |
| 1434 | { |
| 1435 | intensity = 0.0f; |
| 1436 | } |
| 1437 | } |
| 1438 | else |
| 1439 | { |
| 1440 | // apply luminosity |
| 1441 | intensity = ((float)((header[6] >> 11) & 0x1f) / 31.0f) * 255.0f; |
| 1442 | } |
| 1443 | |
| 1444 | clip_vert[i].i = intensity; |
1243 | 1445 | } |
1244 | 1446 | |
1245 | 1447 | /* clip against view frustum */ |
r32673 | r32674 | |
1251 | 1453 | |
1252 | 1454 | /* backface culling */ |
1253 | 1455 | if( (header[6] & 0x800000) && (!(header[1] & 0x0010)) ) { |
1254 | | if(sn[0]*clip_vert[0].x + sn[1]*clip_vert[0].y + sn[2]*clip_vert[0].pz >0) |
| 1456 | if(sn[0]*clip_vert[0].x + sn[1]*clip_vert[0].y + sn[2]*clip_vert[0].z >0) |
1255 | 1457 | back_face = 1; |
1256 | 1458 | else |
1257 | 1459 | back_face = 0; |
r32673 | r32674 | |
1259 | 1461 | else |
1260 | 1462 | back_face = 0; //no culling for transparent or two-sided polygons |
1261 | 1463 | |
1262 | | if(!back_face) { |
| 1464 | if (!back_face) |
| 1465 | { |
1263 | 1466 | /* homogeneous Z-divide, screen-space transformation */ |
1264 | | for(i=0; i < num_vertices; i++) { |
1265 | | float ooz = 1.0f / clip_vert[i].pz; |
| 1467 | for(i=0; i < num_vertices; i++) |
| 1468 | { |
| 1469 | float ooz = 1.0f / clip_vert[i].z; |
1266 | 1470 | clip_vert[i].x = ((clip_vert[i].x * ooz) * m_viewport_focal_length) + center_x; |
1267 | 1471 | clip_vert[i].y = ((clip_vert[i].y * ooz) * m_viewport_focal_length) + center_y; |
| 1472 | clip_vert[i].u *= ooz; |
| 1473 | clip_vert[i].v *= ooz; |
1268 | 1474 | } |
1269 | 1475 | |
1270 | | // lighting |
1271 | | if ((header[6] & 0x10000) == 0) |
| 1476 | |
| 1477 | cached_texture* texture; |
| 1478 | |
| 1479 | if (header[6] & 0x4000000) |
1272 | 1480 | { |
1273 | | dot = dot_product3(sn, m_parallel_light); |
1274 | | intensity = ((dot * m_parallel_light_intensity) + m_ambient_light_intensity) * 256.0f; |
1275 | | if (intensity > 256) |
1276 | | { |
1277 | | intensity = 256; |
1278 | | } |
1279 | | if (intensity < 0) |
1280 | | { |
1281 | | intensity = 0; |
1282 | | } |
| 1481 | int tex_x = ((header[4] & 0x1f) << 1) | ((header[5] >> 7) & 0x1); |
| 1482 | int tex_y = (header[5] & 0x1f); |
| 1483 | int tex_width = ((header[3] >> 3) & 0x7); |
| 1484 | int tex_height = (header[3] & 0x7); |
| 1485 | int tex_format = (header[6] >> 7) & 0x7; |
| 1486 | |
| 1487 | if (tex_width >= 6 || tex_height >= 6) // srally2 poly ram has degenerate polys with 2k tex size (cpu bug or intended?) |
| 1488 | return; |
| 1489 | |
| 1490 | texture = get_texture((header[4] & 0x40) ? 1 : 0, tex_x, tex_y, tex_width, tex_height, tex_format); |
1283 | 1491 | } |
1284 | 1492 | else |
1285 | 1493 | { |
1286 | | // apply luminosity |
1287 | | intensity = 256; |
| 1494 | texture = NULL; |
1288 | 1495 | } |
1289 | 1496 | |
1290 | 1497 | for (i=2; i < num_vertices; i++) |
1291 | 1498 | { |
1292 | | memcpy(&tri.v[0], &clip_vert[0], sizeof(poly_vertex)); |
1293 | | memcpy(&tri.v[1], &clip_vert[i-1], sizeof(poly_vertex)); |
1294 | | memcpy(&tri.v[2], &clip_vert[i], sizeof(poly_vertex)); |
1295 | | tri.texture_x = ((header[4] & 0x1f) << 1) | ((header[5] >> 7) & 0x1); |
1296 | | tri.texture_y = (header[5] & 0x1f); |
1297 | | tri.texture_width = ((header[3] >> 3) & 0x7); |
1298 | | tri.texture_height = (header[3] & 0x7); |
1299 | | tri.texture_format = (header[6] >> 7) & 0x7; |
1300 | | tri.transparency = polygon_transparency; |
1301 | | tri.intensity = intensity; |
1302 | | tri.color = color; |
| 1499 | memcpy(&tri.v[0], &clip_vert[0], sizeof(m3_clip_vertex)); |
| 1500 | memcpy(&tri.v[1], &clip_vert[i-1], sizeof(m3_clip_vertex)); |
| 1501 | memcpy(&tri.v[2], &clip_vert[i], sizeof(m3_clip_vertex)); |
1303 | 1502 | |
| 1503 | tri.texture = texture; |
| 1504 | tri.transparency = polygon_transparency; |
| 1505 | tri.color = color >> 8; |
| 1506 | |
1304 | 1507 | tri.param = 0; |
1305 | 1508 | tri.param |= (header[4] & 0x40) ? TRI_PARAM_TEXTURE_PAGE : 0; |
1306 | 1509 | tri.param |= (header[6] & 0x4000000) ? TRI_PARAM_TEXTURE_ENABLE : 0; |
r32673 | r32674 | |
1308 | 1511 | tri.param |= (header[2] & 0x1) ? TRI_PARAM_TEXTURE_MIRROR_V : 0; |
1309 | 1512 | tri.param |= (header[6] & 0x80000000) ? TRI_PARAM_ALPHA_TEST : 0; |
1310 | 1513 | |
1311 | | render_one(&tri); |
| 1514 | m_renderer->draw_triangle(&tri); |
1312 | 1515 | } |
1313 | 1516 | } |
1314 | 1517 | } |
r32673 | r32674 | |
1521 | 1724 | { |
1522 | 1725 | init_matrix_stack(); |
1523 | 1726 | |
| 1727 | m_list_depth = 0; |
| 1728 | |
1524 | 1729 | for (int pri = 0; pri < 4; pri++) |
1525 | 1730 | draw_viewport(pri, 0x800000); |
1526 | | |
1527 | | poly_wait(m_poly, "real3d_traverse_display_list"); |
1528 | 1731 | } |
1529 | 1732 | |
1530 | | void model3_state::draw_3d_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 1733 | void model3_renderer::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect) |
1531 | 1734 | { |
1532 | 1735 | int i, j; |
1533 | 1736 | |
1534 | 1737 | for (j = cliprect.min_y; j <= cliprect.max_y; ++j) |
1535 | 1738 | { |
1536 | 1739 | UINT32 *dst = &bitmap.pix32(j); |
1537 | | UINT32 *src = &m_bitmap3d.pix32(j); |
| 1740 | UINT32 *src = &m_fb->pix32(j); |
1538 | 1741 | |
1539 | 1742 | for (i = cliprect.min_x; i <= cliprect.max_x; ++i) |
1540 | 1743 | { |
r32673 | r32674 | |
1544 | 1747 | } |
1545 | 1748 | } |
1546 | 1749 | } |
| 1750 | } |
| 1751 | |
| 1752 | void model3_renderer::clear_buffers() |
| 1753 | { |
| 1754 | rectangle cliprect; |
| 1755 | cliprect.min_x = 0; |
| 1756 | cliprect.min_y = 0; |
| 1757 | cliprect.max_x = 495; |
| 1758 | cliprect.max_y = 383; |
| 1759 | |
| 1760 | m_fb->fill(0x00000000, cliprect); |
| 1761 | |
| 1762 | float zvalue = 10000000000.0f; |
| 1763 | m_zb->fill(*(int*)&zvalue, cliprect); |
| 1764 | } |
| 1765 | |
| 1766 | void model3_renderer::draw_triangle(const m3_triangle *tri) |
| 1767 | { |
| 1768 | rectangle cliprect; |
| 1769 | cliprect.min_x = 0; |
| 1770 | cliprect.min_y = 0; |
| 1771 | cliprect.max_x = 495; |
| 1772 | cliprect.max_y = 383; |
| 1773 | |
| 1774 | vertex_t v[3]; |
| 1775 | |
| 1776 | if (tri->param & TRI_PARAM_TEXTURE_ENABLE) |
| 1777 | { |
| 1778 | for (int i=0; i < 3; i++) |
| 1779 | { |
| 1780 | v[i].x = tri->v[i].x; |
| 1781 | v[i].y = tri->v[i].y; |
| 1782 | v[i].p[0] = tri->v[i].z; |
| 1783 | v[i].p[1] = 1.0f / tri->v[i].z; |
| 1784 | v[i].p[2] = tri->v[i].u * 256.0f; // 8 bits of subtexel precision for bilinear filtering |
| 1785 | v[i].p[3] = tri->v[i].v * 256.0f; |
| 1786 | v[i].p[4] = tri->v[i].i; |
| 1787 | } |
| 1788 | |
| 1789 | model3_polydata &extra = object_data_alloc(); |
| 1790 | extra.texture = tri->texture; |
| 1791 | extra.transparency = tri->transparency; |
| 1792 | extra.intensity = tri->intensity; |
| 1793 | extra.texture_param = tri->param; |
| 1794 | |
| 1795 | render_delegate rd; |
| 1796 | if (tri->param & TRI_PARAM_ALPHA_TEST) |
| 1797 | { |
| 1798 | rd = render_delegate(FUNC(model3_renderer::draw_scanline_contour), this); |
| 1799 | } |
| 1800 | else if (extra.texture->alpha == 0xff) |
| 1801 | { |
| 1802 | if (tri->transparency >= 32) |
| 1803 | rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex), this); |
| 1804 | else |
| 1805 | rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex_trans), this); |
| 1806 | } |
| 1807 | else |
| 1808 | { |
| 1809 | rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex_alpha), this); |
| 1810 | } |
| 1811 | |
| 1812 | render_triangle(cliprect, rd, 5, v[0], v[1], v[2]); |
| 1813 | } |
| 1814 | else |
| 1815 | { |
| 1816 | for (int i=0; i < 3; i++) |
| 1817 | { |
| 1818 | v[i].x = tri->v[i].x; |
| 1819 | v[i].y = tri->v[i].y; |
| 1820 | v[i].p[0] = tri->v[i].z; |
| 1821 | v[i].p[1] = tri->v[i].i; |
| 1822 | } |
| 1823 | |
| 1824 | model3_polydata &extra = object_data_alloc(); |
| 1825 | |
| 1826 | extra.intensity = tri->intensity; |
| 1827 | extra.color = tri->color; |
| 1828 | |
| 1829 | render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_solid), this), 2, v[0], v[1], v[2]); |
| 1830 | } |
| 1831 | } |
| 1832 | |
| 1833 | void model3_renderer::draw_scanline_solid(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid) |
| 1834 | { |
| 1835 | UINT32 *fb = &m_fb->pix32(scanline); |
| 1836 | float *zb = (float*)&m_zb->pix32(scanline); |
| 1837 | |
| 1838 | float z = extent.param[0].start; |
| 1839 | float dz = extent.param[0].dpdx; |
| 1840 | |
| 1841 | float in = extent.param[1].start; |
| 1842 | float inz = extent.param[1].dpdx; |
| 1843 | |
| 1844 | int r = polydata.color & 0xff0000; |
| 1845 | int g = polydata.color & 0xff00; |
| 1846 | int b = polydata.color & 0xff; |
| 1847 | |
| 1848 | int srctrans = polydata.transparency; |
| 1849 | int desttrans = 32 - polydata.transparency; |
| 1850 | |
| 1851 | for (int x = extent.startx; x < extent.stopx; x++) |
| 1852 | { |
| 1853 | if (z < zb[x]) |
| 1854 | { |
| 1855 | int ii = (int)(in); |
| 1856 | |
| 1857 | r = (r * ii) >> 8; |
| 1858 | g = (g * ii) >> 8; |
| 1859 | b = (b * ii) >> 8; |
| 1860 | |
| 1861 | if (srctrans != 0x1f) |
| 1862 | { |
| 1863 | UINT32 orig = fb[x]; |
| 1864 | r = (r * srctrans) >> 5; |
| 1865 | g = (g * srctrans) >> 5; |
| 1866 | b = (b * srctrans) >> 5; |
| 1867 | r += ((orig & 0x00ff0000) * desttrans) >> 5; |
| 1868 | g += ((orig & 0x0000ff00) * desttrans) >> 5; |
| 1869 | b += ((orig & 0x000000ff) * desttrans) >> 5; |
| 1870 | } |
| 1871 | |
| 1872 | fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); |
| 1873 | zb[x] = z; |
| 1874 | } |
| 1875 | |
| 1876 | in += inz; |
| 1877 | z += dz; |
| 1878 | } |
| 1879 | } |
| 1880 | |
| 1881 | #define TEX_FETCH_NOFILTER() \ |
| 1882 | do { \ |
| 1883 | float intz = 1.0f / ooz; \ |
| 1884 | UINT32 u = uoz * intz; \ |
| 1885 | UINT32 v = voz * intz; \ |
| 1886 | UINT32 u1 = (u >> 8) & umask; \ |
| 1887 | UINT32 v1 = (v >> 8) & vmask; \ |
| 1888 | texel = texture->data[(v1 << width) + u1]; \ |
| 1889 | } while(0); |
| 1890 | |
| 1891 | #define TEX_FETCH_BILINEAR() \ |
| 1892 | do { \ |
| 1893 | float intz = 1.0f / ooz; \ |
| 1894 | UINT32 u = uoz * intz; \ |
| 1895 | UINT32 v = voz * intz; \ |
| 1896 | UINT32 u1 = (u >> 8) & umask; \ |
| 1897 | UINT32 v1 = (v >> 8) & vmask; \ |
| 1898 | UINT32 u2 = (u1 + 1) & umask; \ |
| 1899 | UINT32 v2 = (v1 + 1) & vmask; \ |
| 1900 | UINT32 pix00 = texture->data[(v1 << width) + u1]; \ |
| 1901 | UINT32 pix01 = texture->data[(v1 << width) + u2]; \ |
| 1902 | UINT32 pix10 = texture->data[(v2 << width) + u1]; \ |
| 1903 | UINT32 pix11 = texture->data[(v2 << width) + u2]; \ |
| 1904 | texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v); \ |
| 1905 | } while(0); |
| 1906 | |
| 1907 | #if ENABLE_BILINEAR |
| 1908 | #define TEX_FETCH() TEX_FETCH_BILINEAR() |
| 1909 | #else |
| 1910 | #define TEX_FETCH() TEX_FETCH_NOFILTER() |
| 1911 | #endif |
| 1912 | |
| 1913 | void model3_renderer::draw_scanline_tex(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid) |
| 1914 | { |
| 1915 | UINT32 *fb = &m_fb->pix32(scanline); |
| 1916 | float *zb = (float*)&m_zb->pix32(scanline); |
| 1917 | const cached_texture *texture = polydata.texture; |
| 1918 | |
| 1919 | float z = extent.param[0].start; |
| 1920 | float dz = extent.param[0].dpdx; |
| 1921 | float ooz = extent.param[1].start; |
| 1922 | float dooz = extent.param[1].dpdx; |
| 1923 | float uoz = extent.param[2].start; |
| 1924 | float duoz = extent.param[2].dpdx; |
| 1925 | float voz = extent.param[3].start; |
| 1926 | float dvoz = extent.param[3].dpdx; |
| 1927 | float in = extent.param[4].start; |
| 1928 | float inz = extent.param[4].dpdx; |
| 1929 | |
| 1930 | UINT32 umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
| 1931 | UINT32 vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
| 1932 | UINT32 width = 6 + texture->width; |
| 1933 | |
| 1934 | for (int x = extent.startx; x < extent.stopx; x++) |
| 1935 | { |
| 1936 | if (z < zb[x]) |
| 1937 | { |
| 1938 | UINT32 texel; |
| 1939 | TEX_FETCH(); |
| 1940 | |
| 1941 | int ii = in; |
| 1942 | |
| 1943 | UINT32 r = ((texel & 0xff0000) * ii) >> 8; |
| 1944 | UINT32 g = ((texel & 0xff00) * ii) >> 8; |
| 1945 | UINT32 b = ((texel & 0xff) * ii) >> 8; |
| 1946 | |
| 1947 | fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); |
| 1948 | zb[x] = z; |
| 1949 | } |
| 1950 | |
| 1951 | ooz += dooz; |
| 1952 | uoz += duoz; |
| 1953 | voz += dvoz; |
| 1954 | in += inz; |
| 1955 | z += dz; |
| 1956 | } |
| 1957 | } |
| 1958 | |
| 1959 | void model3_renderer::draw_scanline_contour(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid) |
| 1960 | { |
| 1961 | UINT32 *fb = &m_fb->pix32(scanline); |
| 1962 | float *zb = (float*)&m_zb->pix32(scanline); |
| 1963 | const cached_texture *texture = polydata.texture; |
| 1964 | |
| 1965 | float z = extent.param[0].start; |
| 1966 | float dz = extent.param[0].dpdx; |
| 1967 | float ooz = extent.param[1].start; |
| 1968 | float dooz = extent.param[1].dpdx; |
| 1969 | float uoz = extent.param[2].start; |
| 1970 | float duoz = extent.param[2].dpdx; |
| 1971 | float voz = extent.param[3].start; |
| 1972 | float dvoz = extent.param[3].dpdx; |
| 1973 | float in = extent.param[4].start; |
| 1974 | float inz = extent.param[4].dpdx; |
| 1975 | |
| 1976 | UINT32 umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
| 1977 | UINT32 vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
| 1978 | UINT32 width = 6 + texture->width; |
| 1979 | |
| 1980 | for (int x = extent.startx; x < extent.stopx; x++) |
| 1981 | { |
| 1982 | if (z < zb[x]) |
| 1983 | { |
| 1984 | UINT32 texel; |
| 1985 | TEX_FETCH(); |
| 1986 | |
| 1987 | UINT32 fa = texel >> 24; |
| 1988 | if (fa >= 0xf8) |
| 1989 | { |
| 1990 | UINT32 r = ((texel & 0x00ff0000) * fa) >> 8; |
| 1991 | UINT32 g = ((texel & 0x0000ff00) * fa) >> 8; |
| 1992 | UINT32 b = ((texel & 0x000000ff) * fa) >> 8; |
| 1993 | |
| 1994 | UINT32 orig = fb[x]; |
| 1995 | |
| 1996 | int minalpha = 255 - fa; |
| 1997 | |
| 1998 | r += ((orig & 0x00ff0000) * minalpha) >> 8; |
| 1999 | g += ((orig & 0x0000ff00) * minalpha) >> 8; |
| 2000 | b += ((orig & 0x000000ff) * minalpha) >> 8; |
| 2001 | |
| 2002 | fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); |
| 2003 | zb[x] = z; |
| 2004 | } |
| 2005 | } |
| 2006 | |
| 2007 | ooz += dooz; |
| 2008 | uoz += duoz; |
| 2009 | voz += dvoz; |
| 2010 | in += inz; |
| 2011 | z += dz; |
| 2012 | } |
| 2013 | } |
| 2014 | |
| 2015 | void model3_renderer::draw_scanline_tex_trans(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid) |
| 2016 | { |
| 2017 | UINT32 *fb = &m_fb->pix32(scanline); |
| 2018 | float *zb = (float*)&m_zb->pix32(scanline); |
| 2019 | const cached_texture *texture = polydata.texture; |
| 2020 | |
| 2021 | float z = extent.param[0].start; |
| 2022 | float dz = extent.param[0].dpdx; |
| 2023 | float ooz = extent.param[1].start; |
| 2024 | float dooz = extent.param[1].dpdx; |
| 2025 | float uoz = extent.param[2].start; |
| 2026 | float duoz = extent.param[2].dpdx; |
| 2027 | float voz = extent.param[3].start; |
| 2028 | float dvoz = extent.param[3].dpdx; |
| 2029 | float in = extent.param[4].start; |
| 2030 | float inz = extent.param[4].dpdx; |
| 2031 | |
| 2032 | int srctrans = polydata.transparency; |
| 2033 | int desttrans = 32 - polydata.transparency; |
| 2034 | |
| 2035 | UINT32 umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
| 2036 | UINT32 vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
| 2037 | UINT32 width = 6 + texture->width; |
| 2038 | |
| 2039 | for (int x = extent.startx; x < extent.stopx; x++) |
| 2040 | { |
| 2041 | if (z < zb[x]) |
| 2042 | { |
| 2043 | UINT32 texel; |
| 2044 | TEX_FETCH(); |
| 2045 | |
| 2046 | int ii = (int)in; |
| 2047 | |
| 2048 | UINT32 r = ((texel & 0x00ff0000) * ii) >> 8; |
| 2049 | UINT32 g = ((texel & 0x0000ff00) * ii) >> 8; |
| 2050 | UINT32 b = ((texel & 0x000000ff) * ii) >> 8; |
| 2051 | |
| 2052 | r = (r * srctrans) >> 5; |
| 2053 | g = (g * srctrans) >> 5; |
| 2054 | b = (b * srctrans) >> 5; |
| 2055 | |
| 2056 | UINT32 orig = fb[x]; |
| 2057 | |
| 2058 | r += ((orig & 0x00ff0000) * desttrans) >> 5; |
| 2059 | g += ((orig & 0x0000ff00) * desttrans) >> 5; |
| 2060 | b += ((orig & 0x000000ff) * desttrans) >> 5; |
| 2061 | |
| 2062 | fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); |
| 2063 | zb[x] = z; |
| 2064 | } |
| 2065 | |
| 2066 | ooz += dooz; |
| 2067 | uoz += duoz; |
| 2068 | voz += dvoz; |
| 2069 | in += inz; |
| 2070 | z += dz; |
| 2071 | } |
| 2072 | } |
| 2073 | |
| 2074 | void model3_renderer::draw_scanline_tex_alpha(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid) |
| 2075 | { |
| 2076 | UINT32 *fb = &m_fb->pix32(scanline); |
| 2077 | float *zb = (float*)&m_zb->pix32(scanline); |
| 2078 | const cached_texture *texture = polydata.texture; |
| 2079 | |
| 2080 | float z = extent.param[0].start; |
| 2081 | float dz = extent.param[0].dpdx; |
| 2082 | float ooz = extent.param[1].start; |
| 2083 | float dooz = extent.param[1].dpdx; |
| 2084 | float uoz = extent.param[2].start; |
| 2085 | float duoz = extent.param[2].dpdx; |
| 2086 | float voz = extent.param[3].start; |
| 2087 | float dvoz = extent.param[3].dpdx; |
| 2088 | float in = extent.param[4].start; |
| 2089 | float inz = extent.param[4].dpdx; |
| 2090 | |
| 2091 | // int srctrans = polydata.transparency; |
| 2092 | // int desttrans = 32 - polydata.transparency; |
| 2093 | |
| 2094 | UINT32 umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; |
| 2095 | UINT32 vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; |
| 2096 | UINT32 width = 6 + texture->width; |
| 2097 | |
| 2098 | for (int x = extent.startx; x < extent.stopx; x++) |
| 2099 | { |
| 2100 | if (z < zb[x]) |
| 2101 | { |
| 2102 | UINT32 texel; |
| 2103 | TEX_FETCH(); |
| 2104 | |
| 2105 | UINT32 fa = texel >> 24; |
| 2106 | if (fa != 0) |
| 2107 | { |
| 2108 | int ii = (int)in; |
| 2109 | |
| 2110 | UINT32 r = ((texel & 0x00ff0000) * ii) >> 8; |
| 2111 | UINT32 g = ((texel & 0x0000ff00) * ii) >> 8; |
| 2112 | UINT32 b = ((texel & 0x000000ff) * ii) >> 8; |
| 2113 | |
| 2114 | r = (r * fa) >> 8; |
| 2115 | g = (g * fa) >> 8; |
| 2116 | b = (b * fa) >> 8; |
| 2117 | |
| 2118 | UINT32 orig = fb[x]; |
| 2119 | |
| 2120 | int minalpha = 255 - fa; |
| 2121 | r += ((orig & 0x00ff0000) * minalpha) >> 8; |
| 2122 | g += ((orig & 0x0000ff00) * minalpha) >> 8; |
| 2123 | b += ((orig & 0x000000ff) * minalpha) >> 8; |
| 2124 | |
| 2125 | fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); |
| 2126 | zb[x] = z; |
| 2127 | } |
| 2128 | } |
| 2129 | |
| 2130 | ooz += dooz; |
| 2131 | uoz += duoz; |
| 2132 | voz += dvoz; |
| 2133 | in += inz; |
| 2134 | z += dz; |
| 2135 | } |
1547 | 2136 | } |
| | No newline at end of file |
trunk/src/mame/drivers/model3.c
r32673 | r32674 | |
13 | 13 | Step 2.1: 166 MHz PPC, same 3D engine as 2.0, differences unknown |
14 | 14 | |
15 | 15 | Game status: |
16 | | vf3/vf3a/vf3tb - don't boot - stuck in poly_wait() |
17 | | bass - boots and runs with 3D |
| 16 | vf3/vf3a/vf3tb - crashes |
| 17 | bass - works |
18 | 18 | getbass - I/O board error (?) |
19 | 19 | |
20 | | scud/scuda - boots and runs with 3D (scuda says "for sale and use only in Japan" but is marked Export?) |
21 | | scudj - boots but hangs up (no SCSI IRQs) |
22 | | scudp - shows initial screen, apparently won't go into test mode or advance |
23 | | lostwsga - SCSI IRQ stuck on (boots and runs with 3D if hacked) |
24 | | vs215 - boots and runs with 3D |
25 | | lemans24 - SCSI IRQ stuck on (boots if hacked) |
26 | | vs29815 - write to unknown 53c810 SCSI register |
| 20 | scud/scuda - works (scuda says "for sale and use only in Japan" but is marked Export?) |
| 21 | scudj - works |
| 22 | scudplus - works |
| 23 | lostwsga - works |
| 24 | vs215 - works |
| 25 | lemans24 - works |
| 26 | vs29815 - massive memory trashing and page faults |
27 | 27 | |
28 | | vs2 - looks like it should boot but never displays anything |
29 | | harley - boots and runs with 3D after a "NO DAUGHTER BOARD DETECTED" error |
30 | | skichamp - "NO DAUGHTER BOARD DETECTED", doesn't advance (no SCSI IRQs occur) |
31 | | srally2/sraly2dx - doesn't boot (no SCSI IRQs occur, other IRQs look fine) |
32 | | von2/von254g - SCSI IRQ stuck on (boots and runs if SCSI ack is hacked) |
33 | | fvipers2 - says "ONE PROCESSOR DETECTED" and hangs (no SCSI IRQs occur, others look fine) |
34 | | vs298/vs299/vs2v991 - hangs (no SCSI IRQs occur, others look fine) |
| 28 | vs2 - waiting for decrementer (same code as eca) |
| 29 | harley - |
| 30 | skichamp - waiting for decrementer |
| 31 | srally2/sraly2dx - works |
| 32 | von2/von254g - works |
| 33 | fvipers2 - waiting for decrementer (same code as eca) |
| 34 | vs298/vs299/vs2v991 - waiting for decrementer |
| 35 | oceanhun - same as daytona2 |
| 36 | lamachin - works |
35 | 37 | |
36 | 38 | dayto2pe - bug in DRC MMU page-fault handling, causes infinite loop at PC:0x2270 (or debug assert) |
37 | 39 | daytona2 - As above. |
38 | 40 | spikeout/spikeofe - As above. |
39 | | dirtdvls/dirtdvla - SCSI IRQ stuck on (boots partially if hacked) |
40 | | swtrilgy - doesn't boot (no SCSI IRQs occur, other IRQs look fine) |
41 | | swtrilga - SCSI IRQ stuck on |
42 | | magtruck - SCSI IRQ stuck on (boots and fails country code check (!) if hacked) |
43 | | eca/ecax - doesn't boot (a few SCSI IRQs occur but then cease, other IRQs look fine) |
| 41 | dirtdvls/dirtdvla - works |
| 42 | swtrilgy - |
| 43 | swtrilga - |
| 44 | magtruck - works |
| 45 | eca/ecax - waiting for decrementer |
44 | 46 | |
45 | 47 | =================================================================================== |
46 | 48 | |
r32673 | r32674 | |
1242 | 1244 | m_m3_step = step; // step = BCD hardware rev. 0x10 for 1.0, 0x15 for 1.5, 0x20 for 2.0, etc. |
1243 | 1245 | tap_reset(); |
1244 | 1246 | |
1245 | | if (step < 0x20) { |
1246 | | if( core_stricmp(machine().system().name, "vs215") == 0 || |
1247 | | core_stricmp(machine().system().name, "vs29815") == 0 || |
1248 | | core_stricmp(machine().system().name, "bass") == 0 ) |
| 1247 | if (step < 0x20) |
| 1248 | { |
| 1249 | if (m_step15_with_mpc106) |
1249 | 1250 | { |
1250 | 1251 | mpc106_init(machine()); |
1251 | 1252 | } |
r32673 | r32674 | |
1255 | 1256 | } |
1256 | 1257 | m_real3d_device_id = 0x16c311db; /* PCI Vendor ID (11db = SEGA), Device ID (16c3 = 315-5827) */ |
1257 | 1258 | } |
1258 | | else { |
| 1259 | else |
| 1260 | { |
1259 | 1261 | mpc106_init(machine()); |
1260 | 1262 | // some step 2+ games need the older PCI ID (obvious symptom: |
1261 | 1263 | // vbl is enabled briefly then disabled so the game hangs) |
1262 | | if (core_stricmp(machine().system().name, "magtruck") == 0 || |
1263 | | core_stricmp(machine().system().name, "von254g") == 0) |
| 1264 | if (m_step20_with_old_real3d) |
1264 | 1265 | { |
1265 | 1266 | m_real3d_device_id = 0x16c311db; /* PCI Vendor ID (11db = SEGA), Device ID (16c3 = 315-5827) */ |
1266 | 1267 | } |
r32673 | r32674 | |
5646 | 5647 | |
5647 | 5648 | DRIVER_INIT_MEMBER(model3_state,scud) |
5648 | 5649 | { |
5649 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5650 | | |
5651 | 5650 | DRIVER_INIT_CALL(model3_15); |
5652 | 5651 | /* TODO: network device at 0xC0000000 - FF */ |
5653 | 5652 | m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xf9000000, 0xf90000ff, read64_delegate(FUNC(model3_state::scsi_r),this), write64_delegate(FUNC(model3_state::scsi_w),this)); |
5654 | | |
5655 | | rom[(0x71275c^4)/4] = 0x60000000; |
5656 | | rom[(0x71277c^4)/4] = 0x60000000; |
5657 | 5653 | } |
5658 | 5654 | |
5659 | 5655 | DRIVER_INIT_MEMBER(model3_state,scudplus) |
5660 | 5656 | { |
5661 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5662 | | |
5663 | 5657 | DRIVER_INIT_CALL(model3_15); |
5664 | 5658 | /* TODO: network device at 0xC0000000 - FF */ |
5665 | 5659 | m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xc1000000, 0xc10000ff, read64_delegate(FUNC(model3_state::scsi_r),this), write64_delegate(FUNC(model3_state::scsi_w),this)); |
5666 | | |
5667 | | rom[(0x713724^4)/4] = 0x60000000; |
5668 | | rom[(0x713744^4)/4] = 0x60000000; |
5669 | | |
5670 | | rom[(0x741f48^4)/4] = 0x60000000; |
5671 | | |
5672 | | rom[(0x741f68^4)/4] = 0x60000000; |
5673 | | rom[(0x741efc^4)/4] = 0x60000000; |
5674 | 5660 | } |
5675 | 5661 | |
5676 | 5662 | DRIVER_INIT_MEMBER(model3_state,scudplusa) |
5677 | 5663 | { |
5678 | | //UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5679 | | |
5680 | 5664 | DRIVER_INIT_CALL(model3_15); |
5681 | 5665 | /* TODO: network device at 0xC0000000 - FF */ |
5682 | 5666 | m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xc1000000, 0xc10000ff, read64_delegate(FUNC(model3_state::scsi_r),this), write64_delegate(FUNC(model3_state::scsi_w),this)); |
5683 | | |
5684 | | //rom[(0x713724^4)/4] = 0x60000000; // Fix ME!!!! Needs to corrected for the non REV A version!!!! |
5685 | | //rom[(0x713744^4)/4] = 0x60000000; |
5686 | | |
5687 | | //rom[(0x741f48^4)/4] = 0x60000000; |
5688 | | |
5689 | | //rom[(0x741f68^4)/4] = 0x60000000; |
5690 | | //rom[(0x741efc^4)/4] = 0x60000000; |
5691 | 5667 | } |
5692 | 5668 | |
5693 | 5669 | DRIVER_INIT_MEMBER(model3_state,lemans24) |
5694 | 5670 | { |
5695 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5696 | 5671 | DRIVER_INIT_CALL(model3_15); |
5697 | 5672 | |
5698 | 5673 | m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xc1000000, 0xc10000ff, read64_delegate(FUNC(model3_state::scsi_r),this), write64_delegate(FUNC(model3_state::scsi_w),this)); |
5699 | | |
5700 | | rom[(0x73fe38^4)/4] = 0x38840004; /* This seems to be an actual bug in the original code */ |
5701 | | |
5702 | | rom[(0x73eb5c^4)/4] = 0x60000000; |
5703 | | rom[(0x73edd0^4)/4] = 0x60000000; |
5704 | | rom[(0x73edc4^4)/4] = 0x60000000; |
| 5674 | |
| 5675 | // rom[(0x73fe38^4)/4] = 0x38840004; /* This seems to be an actual bug in the original code */ |
5705 | 5676 | } |
5706 | 5677 | |
5707 | 5678 | DRIVER_INIT_MEMBER(model3_state,vf3) |
5708 | 5679 | { |
5709 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5680 | //UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5710 | 5681 | |
5711 | 5682 | DRIVER_INIT_CALL(model3_10); |
5712 | 5683 | |
| 5684 | /* |
5713 | 5685 | rom[(0x713c7c^4)/4] = 0x60000000; |
5714 | 5686 | rom[(0x713e54^4)/4] = 0x60000000; |
5715 | 5687 | rom[(0x7125b0^4)/4] = 0x60000000; |
5716 | 5688 | rom[(0x7125d0^4)/4] = 0x60000000; |
5717 | | |
| 5689 | */ |
5718 | 5690 | } |
5719 | 5691 | |
5720 | 5692 | DRIVER_INIT_MEMBER(model3_state,vs215) |
5721 | 5693 | { |
5722 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5694 | m_step15_with_mpc106 = true; |
5723 | 5695 | |
5724 | | rom[(0x70dde0^4)/4] = 0x60000000; |
5725 | | rom[(0x70e6f0^4)/4] = 0x60000000; |
5726 | | rom[(0x70e710^4)/4] = 0x60000000; |
5727 | | |
5728 | 5696 | interleave_vroms(machine()); |
5729 | 5697 | m_maincpu->space(AS_PROGRAM).install_read_bank(0xff000000, 0xff7fffff, "bank1" ); |
5730 | 5698 | |
r32673 | r32674 | |
5739 | 5707 | |
5740 | 5708 | DRIVER_INIT_MEMBER(model3_state,vs29815) |
5741 | 5709 | { |
| 5710 | m_step15_with_mpc106 = true; |
| 5711 | |
5742 | 5712 | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5743 | 5713 | |
5744 | 5714 | rom[(0x6028ec^4)/4] = 0x60000000; |
r32673 | r32674 | |
5758 | 5728 | |
5759 | 5729 | DRIVER_INIT_MEMBER(model3_state,bass) |
5760 | 5730 | { |
5761 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5731 | m_step15_with_mpc106 = true; |
5762 | 5732 | |
5763 | | rom[(0x7999a8^4)/4] = 0x60000000; |
5764 | | rom[(0x7999c8^4)/4] = 0x60000000; |
5765 | | |
5766 | 5733 | interleave_vroms(machine()); |
5767 | 5734 | m_maincpu->space(AS_PROGRAM).install_read_bank(0xff000000, 0xff7fffff, "bank1" ); |
5768 | 5735 | |
r32673 | r32674 | |
5865 | 5832 | |
5866 | 5833 | DRIVER_INIT_MEMBER(model3_state,harleya) |
5867 | 5834 | { |
5868 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5835 | //UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5869 | 5836 | DRIVER_INIT_CALL(model3_20); |
5870 | 5837 | |
5871 | 5838 | m_network_ram = auto_alloc_array_clear(machine(), UINT64, 0x10000); |
5872 | 5839 | m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xc0000000, 0xc00fffff, read64_delegate(FUNC(model3_state::network_r),this), write64_delegate(FUNC(model3_state::network_w),this)); |
5873 | 5840 | |
| 5841 | /* |
5874 | 5842 | rom[(0x50e8d4^4)/4] = 0x60000000; |
5875 | 5843 | rom[(0x50e8f4^4)/4] = 0x60000000; |
5876 | 5844 | rom[(0x50fb84^4)/4] = 0x60000000; |
5877 | 5845 | rom[(0x4f736c^4)/4] = 0x60000000; |
5878 | 5846 | rom[(0x4f738c^4)/4] = 0x60000000; |
| 5847 | */ |
5879 | 5848 | } |
5880 | 5849 | |
5881 | 5850 | |
5882 | 5851 | DRIVER_INIT_MEMBER(model3_state,srally2) |
5883 | | { |
5884 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5852 | { |
5885 | 5853 | DRIVER_INIT_CALL(model3_20); |
5886 | 5854 | |
| 5855 | |
| 5856 | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5887 | 5857 | rom[(0x7c0c4^4)/4] = 0x60000000; |
5888 | 5858 | rom[(0x7c0c8^4)/4] = 0x60000000; |
5889 | 5859 | rom[(0x7c0cc^4)/4] = 0x60000000; |
| 5860 | // Writes command 000023FFFFFFFFFE to JTAG, expects result 0x0040000000 (41 bits) |
| 5861 | // Writes command 000003FFFFFFFFFE |
| 5862 | // Writes command 00003FFFFFFFFFFE 248 times |
| 5863 | // Writes command 000023FFFFFFFFFE, expects result 0x01000000000 (?? bits) |
5890 | 5864 | } |
5891 | 5865 | |
5892 | 5866 | DRIVER_INIT_MEMBER(model3_state,swtrilgy) |
5893 | 5867 | { |
5894 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5868 | //UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5895 | 5869 | DRIVER_INIT_CALL(model3_20); |
5896 | 5870 | |
| 5871 | /* |
5897 | 5872 | rom[(0xf0e48^4)/4] = 0x60000000; |
5898 | 5873 | rom[(0x043dc^4)/4] = 0x48000090; |
5899 | 5874 | rom[(0x029a0^4)/4] = 0x60000000; |
5900 | 5875 | rom[(0x02a0c^4)/4] = 0x60000000; |
| 5876 | */ |
5901 | 5877 | } |
5902 | 5878 | |
5903 | 5879 | DRIVER_INIT_MEMBER(model3_state,swtrilga) |
5904 | 5880 | { |
5905 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5881 | //UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5906 | 5882 | DRIVER_INIT_CALL(model3_20); |
5907 | 5883 | |
5908 | | rom[(0xf6dd0^4)/4] = 0x60000000; |
| 5884 | //rom[(0xf6dd0^4)/4] = 0x60000000; |
5909 | 5885 | } |
5910 | 5886 | |
5911 | 5887 | DRIVER_INIT_MEMBER(model3_state,von2) |
5912 | 5888 | { |
5913 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5889 | m_step20_with_old_real3d = true; |
| 5890 | |
5914 | 5891 | DRIVER_INIT_CALL(model3_20); |
5915 | | |
5916 | | rom[(0x189168^4)/4] = 0x60000000; |
5917 | | rom[(0x1890ac^4)/4] = 0x60000000; |
5918 | | rom[(0x1890b8^4)/4] = 0x60000000; |
5919 | | rom[(0x1888a8^4)/4] = 0x60000000; |
5920 | | rom[(0x1891c8^4)/4] = 0x60000000; |
5921 | 5892 | } |
5922 | 5893 | |
5923 | 5894 | DRIVER_INIT_MEMBER(model3_state,dirtdvls) |
5924 | 5895 | { |
5925 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5926 | | DRIVER_INIT_CALL(model3_20); |
| 5896 | m_step20_with_old_real3d = true; |
5927 | 5897 | |
5928 | | rom[(0x0600a0^4)/4] = 0x60000000; |
5929 | | rom[(0x0608a4^4)/4] = 0x60000000; |
5930 | | rom[(0x0608b0^4)/4] = 0x60000000; |
5931 | | rom[(0x060960^4)/4] = 0x60000000; |
5932 | | rom[(0x0609c0^4)/4] = 0x60000000; |
5933 | | rom[(0x001e24^4)/4] = 0x60000000; |
| 5898 | DRIVER_INIT_CALL(model3_20); |
5934 | 5899 | } |
5935 | 5900 | |
5936 | 5901 | DRIVER_INIT_MEMBER(model3_state,daytona2) |
r32673 | r32674 | |
5982 | 5947 | |
5983 | 5948 | DRIVER_INIT_MEMBER(model3_state,eca) |
5984 | 5949 | { |
5985 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5950 | // UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5986 | 5951 | DRIVER_INIT_CALL(model3_20); |
5987 | 5952 | |
5988 | | |
| 5953 | /* |
5989 | 5954 | rom[(0x535560^4)/4] = 0x60000000; |
5990 | 5955 | rom[(0x535580^4)/4] = 0x60000000; |
| 5956 | */ |
5991 | 5957 | } |
5992 | 5958 | |
5993 | 5959 | DRIVER_INIT_MEMBER(model3_state,skichamp) |
5994 | 5960 | { |
5995 | | UINT32 *rom = (UINT32*)memregion("user1")->base(); |
| 5961 | //UINT32 *rom = (UINT32*)memregion("user1")->base(); |
5996 | 5962 | DRIVER_INIT_CALL(model3_20); |
5997 | 5963 | |
| 5964 | /* |
5998 | 5965 | rom[(0x5263c8^4)/4] = 0x60000000; |
5999 | 5966 | rom[(0x5263e8^4)/4] = 0x60000000; |
6000 | 5967 | rom[(0x516bbc^4)/4] = 0x60000000; |
6001 | 5968 | rom[(0x516b9c^4)/4] = 0x60000000; // decrementer |
| 5969 | */ |
6002 | 5970 | } |
6003 | 5971 | |
6004 | 5972 | DRIVER_INIT_MEMBER(model3_state,oceanhun) |
r32673 | r32674 | |
6011 | 5979 | |
6012 | 5980 | DRIVER_INIT_MEMBER(model3_state,magtruck) |
6013 | 5981 | { |
| 5982 | m_step20_with_old_real3d = true; |
| 5983 | |
6014 | 5984 | DRIVER_INIT_CALL(model3_20); |
6015 | 5985 | } |
6016 | 5986 | |
| 5987 | DRIVER_INIT_MEMBER(model3_state,lamachin) |
| 5988 | { |
| 5989 | m_step20_with_old_real3d = true; |
6017 | 5990 | |
| 5991 | DRIVER_INIT_CALL(model3_20); |
| 5992 | } |
| 5993 | |
| 5994 | |
6018 | 5995 | /* Model 3 Step 1.0 */ |
6019 | 5996 | GAME( 1996, vf3, 0, model3_10, model3, model3_state, vf3, ROT0, "Sega", "Virtua Fighter 3 (Revision C)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6020 | 5997 | GAME( 1996, vf3a, vf3, model3_10, model3, model3_state, vf3, ROT0, "Sega", "Virtua Fighter 3 (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
r32673 | r32674 | |
6039 | 6016 | GAME( 1997, vs2, 0, model3_20, model3, model3_state, vs2, ROT0, "Sega", "Virtua Striker 2 (Step 2.0)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6040 | 6017 | GAME( 1997, harley, 0, model3_20, harley, model3_state, harley, ROT0, "Sega", "Harley-Davidson and L.A. Riders (Revision B)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6041 | 6018 | GAME( 1997, harleya, harley, model3_20, harley, model3_state, harleya, ROT0, "Sega", "Harley-Davidson and L.A. Riders (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6042 | | GAME( 1998, lamachin, 0, model3_20, model3, model3_state, model3_20, ROT0, "Sega", "L.A. Machineguns", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
| 6019 | GAME( 1998, lamachin, 0, model3_20, model3, model3_state, lamachin, ROT0, "Sega", "L.A. Machineguns", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6043 | 6020 | GAME( 1998, oceanhun, 0, model3_20, model3, model3_state, oceanhun, ROT0, "Sega", "The Ocean Hunter", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6044 | 6021 | GAME( 1998, skichamp, 0, model3_20, skichamp, model3_state, skichamp, ROT0, "Sega", "Ski Champ", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6045 | 6022 | GAME( 1998, srally2, 0, model3_20, scud, model3_state, srally2, ROT0, "Sega", "Sega Rally 2", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6046 | 6023 | GAME( 1998, srally2x, 0, model3_20, scud, model3_state, srally2, ROT0, "Sega", "Sega Rally 2 DX", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6047 | 6024 | GAME( 1998, von2, 0, model3_20, model3, model3_state, von2, ROT0, "Sega", "Virtual On 2: Oratorio Tangram (Revision B)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6048 | | GAME( 1998, von254g, von2, model3_20, model3, model3_state, model3_20, ROT0, "Sega", "Virtual On 2: Oratorio Tangram (ver 5.4g)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
| 6025 | GAME( 1998, von254g, von2, model3_20, model3, model3_state, von2, ROT0, "Sega", "Virtual On 2: Oratorio Tangram (ver 5.4g)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6049 | 6026 | GAME( 1998, fvipers2, 0, model3_20, model3, model3_state, model3_20, ROT0, "Sega", "Fighting Vipers 2 (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6050 | 6027 | GAME( 1998, vs298, 0, model3_20, model3, model3_state, vs298, ROT0, "Sega", "Virtua Striker 2 '98 (Step 2.0)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |
6051 | 6028 | GAME( 1999, vs2v991, 0, model3_20, model3, model3_state, vs2v991, ROT0, "Sega", "Virtua Striker 2 '99.1 (Revision B)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) |