trunk/src/mame/video/midzeus.c
r249100 | r249101 | |
8 | 8 | |
9 | 9 | #include "emu.h" |
10 | 10 | #include "includes/midzeus.h" |
11 | | #include "video/polylgcy.h" |
| 11 | #include "video/poly.h" |
12 | 12 | #include "video/rgbutil.h" |
13 | 13 | |
14 | 14 | |
r249100 | r249101 | |
63 | 63 | }; |
64 | 64 | |
65 | 65 | |
| 66 | class midzeus_renderer : public poly_manager<float, mz_poly_extra_data, 4, 10000> |
| 67 | { |
| 68 | public: |
| 69 | midzeus_renderer(midzeus_state &state); |
| 70 | |
| 71 | void render_poly(INT32 scanline, const extent_t& extent, const mz_poly_extra_data& object, int threadid); |
| 72 | void render_poly_solid_fixedz(INT32 scanline, const extent_t& extent, const mz_poly_extra_data& object, int threadid); |
| 73 | |
| 74 | void zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT32 texdata, int logit); |
| 75 | void zeus_draw_debug_quad(const rectangle& rect, const vertex_t* vert); |
| 76 | |
| 77 | private: |
| 78 | midzeus_state& m_state; |
| 79 | }; |
66 | 80 | |
| 81 | typedef midzeus_renderer::vertex_t poly_vertex; |
| 82 | |
| 83 | |
67 | 84 | /************************************* |
68 | 85 | * |
69 | 86 | * Global variables |
70 | 87 | * |
71 | 88 | *************************************/ |
72 | 89 | |
73 | | static legacy_poly_manager *poly; |
| 90 | static midzeus_renderer *poly; |
74 | 91 | static UINT8 log_fifo; |
75 | 92 | |
76 | 93 | static UINT32 zeus_fifo[20]; |
r249100 | r249101 | |
102 | 119 | INLINE UINT8 get_texel_8bit(const void *base, int y, int x, int width); |
103 | 120 | INLINE UINT8 get_texel_alt_8bit(const void *base, int y, int x, int width); |
104 | 121 | |
105 | | static void render_poly(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid); |
106 | | static void render_poly_solid_fixedz(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid); |
107 | 122 | |
108 | | |
109 | 123 | /************************************* |
110 | 124 | * |
111 | 125 | * Macros |
r249100 | r249101 | |
257 | 271 | * |
258 | 272 | *************************************/ |
259 | 273 | |
| 274 | midzeus_renderer::midzeus_renderer(midzeus_state &state) |
| 275 | : poly_manager<float, mz_poly_extra_data, 4, 10000>(state.machine()), |
| 276 | m_state(state) |
| 277 | {} |
| 278 | |
260 | 279 | VIDEO_START_MEMBER(midzeus_state,midzeus) |
261 | 280 | { |
262 | 281 | int i; |
r249100 | r249101 | |
270 | 289 | m_palette->set_pen_color(i, pal5bit(i >> 10), pal5bit(i >> 5), pal5bit(i >> 0)); |
271 | 290 | |
272 | 291 | /* initialize polygon engine */ |
273 | | poly = poly_alloc(machine(), 10000, sizeof(mz_poly_extra_data), POLYFLAG_ALLOW_QUADS); |
274 | | |
| 292 | poly = auto_alloc(machine(), midzeus_renderer(*this)); |
| 293 | |
275 | 294 | /* we need to cleanup on exit */ |
276 | 295 | machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(midzeus_state::exit_handler), this)); |
277 | 296 | |
r249100 | r249101 | |
315 | 334 | } |
316 | 335 | fclose(f); |
317 | 336 | #endif |
318 | | |
319 | | poly_free(poly); |
320 | 337 | } |
321 | 338 | |
322 | 339 | |
r249100 | r249101 | |
331 | 348 | { |
332 | 349 | int x, y; |
333 | 350 | |
334 | | poly_wait(poly, "VIDEO_UPDATE"); |
| 351 | poly->wait("VIDEO_UPDATE"); |
335 | 352 | |
336 | 353 | /* normal update case */ |
337 | 354 | if (!machine().input().code_pressed(KEYCODE_W)) |
r249100 | r249101 | |
639 | 656 | // m_zeusbase[0x46] = ??? = 0x00000000 |
640 | 657 | // m_zeusbase[0x4c] = ??? = 0x00808080 (brightness?) |
641 | 658 | // m_zeusbase[0x4e] = ??? = 0x00808080 (brightness?) |
642 | | mz_poly_extra_data *extra = (mz_poly_extra_data *)poly_get_extra_data(poly); |
| 659 | mz_poly_extra_data& extra = poly->object_data_alloc(); |
643 | 660 | poly_vertex vert[4]; |
644 | 661 | |
645 | 662 | vert[0].x = (INT16)m_zeusbase[0x08]; |
r249100 | r249101 | |
651 | 668 | vert[3].x = (INT16)m_zeusbase[0x0e]; |
652 | 669 | vert[3].y = (INT16)(m_zeusbase[0x0e] >> 16); |
653 | 670 | |
654 | | extra->solidcolor = m_zeusbase[0x00]; |
655 | | extra->zoffset = 0x7fff; |
| 671 | extra.solidcolor = m_zeusbase[0x00]; |
| 672 | extra.zoffset = 0x7fff; |
656 | 673 | |
657 | | poly_render_quad(poly, NULL, zeus_cliprect, render_poly_solid_fixedz, 0, &vert[0], &vert[1], &vert[2], &vert[3]); |
658 | | poly_wait(poly, "Normal"); |
| 674 | poly->zeus_draw_debug_quad(zeus_cliprect, vert); |
| 675 | poly->wait("Normal"); |
659 | 676 | } |
660 | 677 | else |
661 | 678 | logerror("Execute unknown command\n"); |
r249100 | r249101 | |
728 | 745 | else |
729 | 746 | src = (const UINT32 *)waveram0_ptr_from_expanded_addr(m_zeusbase[0xb4]); |
730 | 747 | |
731 | | poly_wait(poly, "vram_read"); |
| 748 | poly->wait("vram_read"); |
732 | 749 | m_zeusbase[0xb0] = WAVERAM_READ32(src, 0); |
733 | 750 | m_zeusbase[0xb2] = WAVERAM_READ32(src, 1); |
734 | 751 | } |
r249100 | r249101 | |
958 | 975 | else |
959 | 976 | { |
960 | 977 | UINT32 texdata = (m_zeusbase[0x06] << 16) | (m_zeusbase[0x00] >> 16); |
961 | | zeus_draw_quad(FALSE, data, texdata, log_fifo); |
| 978 | poly->zeus_draw_quad(FALSE, data, texdata, log_fifo); |
962 | 979 | } |
963 | 980 | break; |
964 | 981 | |
r249100 | r249101 | |
1072 | 1089 | case 0x25: /* mk4 */ |
1073 | 1090 | case 0x28: /* mk4r1 */ |
1074 | 1091 | case 0x30: /* invasn */ |
1075 | | zeus_draw_quad(TRUE, databuffer, texdata, logit); |
| 1092 | poly->zeus_draw_quad(TRUE, databuffer, texdata, logit); |
1076 | 1093 | break; |
1077 | 1094 | |
1078 | 1095 | default: |
r249100 | r249101 | |
1096 | 1113 | * |
1097 | 1114 | *************************************/ |
1098 | 1115 | |
1099 | | void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT32 texdata, int logit) |
| 1116 | void midzeus_renderer::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT32 texdata, int logit) |
1100 | 1117 | { |
1101 | | poly_draw_scanline_func callback; |
1102 | | mz_poly_extra_data *extra; |
1103 | 1118 | poly_vertex clipvert[8]; |
1104 | 1119 | poly_vertex vert[4]; |
1105 | 1120 | UINT32 ushift, vshift; |
r249100 | r249101 | |
1112 | 1127 | texbase = ((texdata >> 10) & 0x3f0000) | (texdata & 0xffff); |
1113 | 1128 | texwshift = (texdata >> 22) & 7; |
1114 | 1129 | |
1115 | | ushift = 8 - ((m_zeusbase[0x04] >> 4) & 3); |
1116 | | vshift = 8 - ((m_zeusbase[0x04] >> 6) & 3); |
| 1130 | ushift = 8 - ((m_state.m_zeusbase[0x04] >> 4) & 3); |
| 1131 | vshift = 8 - ((m_state.m_zeusbase[0x04] >> 6) & 3); |
1117 | 1132 | |
1118 | 1133 | int xy_offset = long_fmt ? 2 : 1; |
1119 | 1134 | |
r249100 | r249101 | |
1187 | 1202 | } |
1188 | 1203 | } |
1189 | 1204 | |
1190 | | numverts = poly_zclip_if_less(4, &vert[0], &clipvert[0], 4, 512.0f); |
| 1205 | numverts = poly->zclip_if_less(4, &vert[0], &clipvert[0], 4, 512.0f); |
1191 | 1206 | if (numverts < 3) |
1192 | 1207 | return; |
1193 | 1208 | |
r249100 | r249101 | |
1215 | 1230 | clipvert[i].y += 0.0005f; |
1216 | 1231 | } |
1217 | 1232 | |
1218 | | extra = (mz_poly_extra_data *)poly_get_extra_data(poly); |
| 1233 | mz_poly_extra_data& extra = poly->object_data_alloc(); |
1219 | 1234 | |
1220 | 1235 | if (ctrl_word & 0x01000000) |
1221 | 1236 | { |
1222 | 1237 | UINT32 tex_type = (texdata >> 16) & 3; |
1223 | | extra->texwidth = 512 >> texwshift; |
1224 | | extra->voffset = ctrl_word & 0xffff; |
| 1238 | extra.texwidth = 512 >> texwshift; |
| 1239 | extra.voffset = ctrl_word & 0xffff; |
1225 | 1240 | |
1226 | | extra->texbase = waveram0_ptr_from_texture_addr(texbase, extra->texwidth); |
| 1241 | extra.texbase = waveram0_ptr_from_texture_addr(texbase, extra.texwidth); |
1227 | 1242 | |
1228 | 1243 | if (tex_type == 1) |
1229 | 1244 | { |
1230 | | extra->get_texel = texdata & 0x00200000 ? get_texel_8bit : get_texel_4bit; |
| 1245 | extra.get_texel = texdata & 0x00200000 ? get_texel_8bit : get_texel_4bit; |
1231 | 1246 | } |
1232 | 1247 | else if (tex_type == 2) |
1233 | 1248 | { |
1234 | | extra->get_texel = texdata & 0x00200000 ? get_texel_alt_8bit : get_texel_alt_4bit; |
| 1249 | extra.get_texel = texdata & 0x00200000 ? get_texel_alt_8bit : get_texel_alt_4bit; |
1235 | 1250 | } |
1236 | 1251 | else |
1237 | 1252 | { |
r249100 | r249101 | |
1240 | 1255 | } |
1241 | 1256 | } |
1242 | 1257 | |
1243 | | callback = render_poly; |
| 1258 | extra.ctrl_word = ctrl_word; |
| 1259 | extra.solidcolor = m_state.m_zeusbase[0x00] & 0x7fff; |
| 1260 | extra.zoffset = m_state.m_zeusbase[0x7e] >> 16; |
| 1261 | extra.alpha = m_state.m_zeusbase[0x4e]; |
| 1262 | extra.blend = m_state.m_zeusbase[0x5c]; |
| 1263 | extra.depth_test_enable = !(m_state.m_zeusbase[0x04] & 0x800); |
| 1264 | extra.depth_write_enable = m_state.m_zeusbase[0x04] & 0x200; |
| 1265 | extra.transcolor = ((ctrl_word >> 16) & 1) ? 0 : 0x100; |
| 1266 | extra.palbase = waveram0_ptr_from_block_addr(zeus_palbase); |
1244 | 1267 | |
1245 | | extra->ctrl_word = ctrl_word; |
1246 | | extra->solidcolor = m_zeusbase[0x00] & 0x7fff; |
1247 | | extra->zoffset = m_zeusbase[0x7e] >> 16; |
1248 | | extra->alpha = m_zeusbase[0x4e]; |
1249 | | extra->blend = m_zeusbase[0x5c]; |
1250 | | extra->depth_test_enable = !(m_zeusbase[0x04] & 0x800); |
1251 | | extra->depth_write_enable = m_zeusbase[0x04] & 0x200; |
1252 | | extra->transcolor = ((ctrl_word >> 16) & 1) ? 0 : 0x100; |
1253 | | extra->palbase = waveram0_ptr_from_block_addr(zeus_palbase); |
| 1268 | // Note: Before being upgraded to the new polygon rasterizing code, this function call was |
| 1269 | // a poly_render_quad_fan. It appears as though the new code defaults to a fan if |
| 1270 | // the template argument is 4, but keep an eye out for missing quads. |
| 1271 | poly->render_polygon<4>(zeus_cliprect, |
| 1272 | render_delegate(FUNC(midzeus_renderer::render_poly), this), |
| 1273 | 4, |
| 1274 | clipvert); |
| 1275 | } |
1254 | 1276 | |
1255 | | poly_render_quad_fan(poly, NULL, zeus_cliprect, callback, 4, numverts, &clipvert[0]); |
| 1277 | void midzeus_renderer::zeus_draw_debug_quad(const rectangle& rect, const vertex_t *vert) |
| 1278 | { |
| 1279 | poly->render_polygon<4>(rect, render_delegate(FUNC(midzeus_renderer::render_poly_solid_fixedz), this), 0, vert); |
1256 | 1280 | } |
1257 | 1281 | |
1258 | 1282 | |
1259 | | |
1260 | 1283 | /************************************* |
1261 | 1284 | * |
1262 | 1285 | * Rasterizers |
1263 | 1286 | * |
1264 | 1287 | *************************************/ |
1265 | 1288 | |
1266 | | static void render_poly(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) |
| 1289 | void midzeus_renderer::render_poly(INT32 scanline, const extent_t& extent, const mz_poly_extra_data& object, int threadid) |
1267 | 1290 | { |
1268 | | const mz_poly_extra_data *extra = (const mz_poly_extra_data *)extradata; |
1269 | | INT32 curz = extent->param[0].start; |
1270 | | INT32 curu = extent->param[1].start; |
1271 | | INT32 curv = extent->param[2].start; |
1272 | | INT32 curi = extent->param[3].start; |
1273 | | INT32 dzdx = extent->param[0].dpdx; |
1274 | | INT32 dudx = extent->param[1].dpdx; |
1275 | | INT32 dvdx = extent->param[2].dpdx; |
1276 | | INT32 didx = extent->param[3].dpdx; |
1277 | | const void *texbase = extra->texbase; |
1278 | | const void *palbase = extra->palbase; |
1279 | | UINT16 transcolor = extra->transcolor; |
1280 | | UINT32 texwidth = extra->texwidth; |
| 1291 | INT32 curz = extent.param[0].start; |
| 1292 | INT32 curu = extent.param[1].start; |
| 1293 | INT32 curv = extent.param[2].start; |
| 1294 | INT32 curi = extent.param[3].start; |
| 1295 | INT32 dzdx = extent.param[0].dpdx; |
| 1296 | INT32 dudx = extent.param[1].dpdx; |
| 1297 | INT32 dvdx = extent.param[2].dpdx; |
| 1298 | INT32 didx = extent.param[3].dpdx; |
| 1299 | const void *texbase = object.texbase; |
| 1300 | const void *palbase = object.palbase; |
| 1301 | UINT16 transcolor = object.transcolor; |
| 1302 | UINT32 texwidth = object.texwidth; |
1281 | 1303 | |
1282 | | for (UINT32 x = extent->startx; x < extent->stopx; x++) |
| 1304 | for (UINT32 x = extent.startx; x < extent.stopx; x++) |
1283 | 1305 | { |
1284 | 1306 | UINT16 *depthptr = WAVERAM_PTRDEPTH(zeus_renderbase, scanline, x); |
1285 | | INT32 depth = (curz >> 16) + extra->zoffset; |
| 1307 | INT32 depth = (curz >> 16) + object.zoffset; |
1286 | 1308 | |
1287 | 1309 | if (depth > 0x7fff) |
1288 | 1310 | depth = 0x7fff; |
r249100 | r249101 | |
1291 | 1313 | |
1292 | 1314 | bool depth_pass; |
1293 | 1315 | |
1294 | | if (extra->depth_test_enable) |
| 1316 | if (object.depth_test_enable) |
1295 | 1317 | depth_pass = depth >= 0 && depth <= *depthptr; |
1296 | 1318 | else |
1297 | 1319 | depth_pass = true; |
r249100 | r249101 | |
1302 | 1324 | |
1303 | 1325 | bool src_valid = true; |
1304 | 1326 | |
1305 | | if ((extra->ctrl_word & 0x000c0000) == 0x000c0000) |
| 1327 | if ((object.ctrl_word & 0x000c0000) == 0x000c0000) |
1306 | 1328 | { |
1307 | | src.set_r(pal5bit(extra->solidcolor >> 10)); |
1308 | | src.set_g(pal5bit(extra->solidcolor >> 5)); |
1309 | | src.set_b(pal5bit(extra->solidcolor)); |
| 1329 | src.set_r(pal5bit(object.solidcolor >> 10)); |
| 1330 | src.set_g(pal5bit(object.solidcolor >> 5)); |
| 1331 | src.set_b(pal5bit(object.solidcolor)); |
1310 | 1332 | } |
1311 | 1333 | else |
1312 | 1334 | { |
1313 | 1335 | UINT32 u0 = curu >> 8; |
1314 | | UINT32 v0 = extra->voffset + (curv >> 8); |
| 1336 | UINT32 v0 = object.voffset + (curv >> 8); |
1315 | 1337 | UINT32 u1 = u0 + 1; |
1316 | 1338 | UINT32 v1 = v0 + 1; |
1317 | 1339 | |
1318 | 1340 | UINT8 texels[4]; |
1319 | 1341 | |
1320 | | texels[0] = extra->get_texel(texbase, v0, u0, texwidth); |
1321 | | texels[1] = extra->get_texel(texbase, v0, u1, texwidth); |
1322 | | texels[2] = extra->get_texel(texbase, v1, u0, texwidth); |
1323 | | texels[3] = extra->get_texel(texbase, v1, u1, texwidth); |
| 1342 | texels[0] = object.get_texel(texbase, v0, u0, texwidth); |
| 1343 | texels[1] = object.get_texel(texbase, v0, u1, texwidth); |
| 1344 | texels[2] = object.get_texel(texbase, v1, u0, texwidth); |
| 1345 | texels[3] = object.get_texel(texbase, v1, u1, texwidth); |
1324 | 1346 | |
1325 | 1347 | if (texels[0] != transcolor) |
1326 | 1348 | { |
1327 | | rgb_t color[4]; |
| 1349 | rgb_t color[4] = {0, 0, 0, 0}; |
1328 | 1350 | |
1329 | 1351 | for (UINT32 i = 0; i < 4; ++i) |
1330 | 1352 | { |
r249100 | r249101 | |
1357 | 1379 | UINT32 outg = 0; |
1358 | 1380 | UINT32 outb = 0; |
1359 | 1381 | |
1360 | | UINT32 srca = extra->alpha & 0xff; |
1361 | | UINT32 dsta = (extra->alpha >> 8) & 0xff; |
| 1382 | UINT32 srca = object.alpha & 0xff; |
| 1383 | UINT32 dsta = (object.alpha >> 8) & 0xff; |
1362 | 1384 | |
1363 | 1385 | // Destination enable? |
1364 | | if (extra->blend & 0x00800000) |
| 1386 | if (object.blend & 0x00800000) |
1365 | 1387 | { |
1366 | 1388 | UINT16 dst = WAVERAM_READPIX(zeus_renderbase, scanline, x); |
1367 | 1389 | |
r249100 | r249101 | |
1374 | 1396 | dstb = (dstb << 3) | (dstb >> 2); |
1375 | 1397 | } |
1376 | 1398 | |
1377 | | switch (extra->blend) |
| 1399 | switch (object.blend) |
1378 | 1400 | { |
1379 | 1401 | case BLEND_OPAQUE1: |
1380 | 1402 | { |
r249100 | r249101 | |
1459 | 1481 | |
1460 | 1482 | WAVERAM_WRITEPIX(zeus_renderbase, scanline, x, (outr << 10) | (outg << 5) | outb); |
1461 | 1483 | |
1462 | | if (extra->depth_write_enable) |
| 1484 | if (object.depth_write_enable) |
1463 | 1485 | *depthptr = depth; |
1464 | 1486 | } |
1465 | 1487 | } |
r249100 | r249101 | |
1473 | 1495 | |
1474 | 1496 | |
1475 | 1497 | |
1476 | | static void render_poly_solid_fixedz(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) |
| 1498 | void midzeus_renderer::render_poly_solid_fixedz(INT32 scanline, const extent_t& extent, const mz_poly_extra_data& object, int threadid) |
1477 | 1499 | { |
1478 | | const mz_poly_extra_data *extra = (const mz_poly_extra_data *)extradata; |
1479 | | UINT16 color = extra->solidcolor; |
1480 | | UINT16 depth = extra->zoffset; |
| 1500 | UINT16 color = object.solidcolor; |
| 1501 | UINT16 depth = object.zoffset; |
1481 | 1502 | int x; |
1482 | 1503 | |
1483 | | for (x = extent->startx; x < extent->stopx; x++) |
| 1504 | for (x = extent.startx; x < extent.stopx; x++) |
1484 | 1505 | waveram_plot_depth(scanline, x, color, depth); |
1485 | 1506 | } |
1486 | 1507 | |