From 36f146e5dc18d3ac79727153d1b719a0757f3542 Mon Sep 17 00:00:00 2001 From: Ville Linde Date: Sun, 14 Jun 2015 03:24:28 +0300 Subject: [PATCH] model3: various improvements [Ville Linde] * Rewrote projection calculations to use projection matrix * Rewrote polygon clipping to use 4D W-space clipping * Implemented 8-bit texture uploads * Changed all scanline renderers to use rgbutil --- src/mame/drivers/model3.c | 106 ++-- src/mame/includes/model3.h | 30 +- src/mame/video/model3.c | 978 +++++++++++++++++++++++++------------ 3 files changed, 739 insertions(+), 375 deletions(-) diff --git a/src/mame/drivers/model3.c b/src/mame/drivers/model3.c index f20f4901166..95e9177da59 100644 --- a/src/mame/drivers/model3.c +++ b/src/mame/drivers/model3.c @@ -1192,7 +1192,7 @@ static void configure_fast_ram(running_machine &machine) { model3_state *state = machine.driver_data(); /* set conservative DRC options */ - machine.device("maincpu")->ppcdrc_set_options(PPCDRC_COMPATIBLE_OPTIONS - PPCDRC_ACCURATE_SINGLES); + machine.device("maincpu")->ppcdrc_set_options(PPCDRC_COMPATIBLE_OPTIONS); /* configure fast RAM regions for DRC */ machine.device("maincpu")->ppcdrc_add_fastram(0x00000000, 0x007fffff, FALSE, state->m_work_ram); @@ -1556,7 +1556,7 @@ WRITE64_MEMBER(model3_state::model3_sys_w) m_crom_bank = data >> 56; data >>= 56; - data = (~data) & 0x7; + data = (~data) & 0xf; membank("bank1")->set_base(memregion( "user1" )->base() + 0x800000 + (data * 0x800000)); /* banked CROM */ } @@ -2047,7 +2047,7 @@ INPUT_PORTS_END #define ROM_LOAD_VROM(name, offset, length, hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_SKIP(14) ) ROM_START( lemans24 ) /* step 1.5, Sega game ID# is 833-13159, ROM board ID# 834-13160 GAME BD LEMANS 24 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19887b.17", 0x600006, 0x080000, CRC(2842bb87) SHA1(2acabf3f7281acaf6bab4d3bae9701df3909cf81) ) ROM_LOAD64_WORD_SWAP( "epr-19888b.18", 0x600004, 0x080000, CRC(800d763d) SHA1(4f2865a64d6dda638840d359db3bd2f22b6d1404) ) @@ -2117,7 +2117,7 @@ ROM_END ROM_START( scud ) /* step 1.5, Sega game ID# is 833-13041, ROM board ID# 834-13072 SPG COMM AUS */ /* There is known to be a ROM board ID# 834-13034 SPG DX AUS with program roms EPR-19634 to EPR-19637 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19731.17", 0x0600006, 0x80000, CRC(3ee6447e) SHA1(124697791d90c1b352dd6e33bd3b45535aa92bb5) ) ROM_LOAD64_WORD_SWAP( "epr-19732.18", 0x0600004, 0x80000, CRC(23e864bb) SHA1(0f34d963ee681ca1006f3dec12b593d961e3e442) ) @@ -2192,7 +2192,7 @@ ROM_START( scud ) /* step 1.5, Sega game ID# is 833-13041, ROM board ID# 834-1 ROM_END ROM_START( scudj ) /* step 1.5, Sega game ID# is 833-13041, ROM board ID# 12934 SPG DX */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19610.17a", 0x0600006, 0x80000, CRC(53f5cd94) SHA1(e27609165087ef7000b61ce628883561ffe64b22) ) ROM_LOAD64_WORD_SWAP( "epr-19609.18a", 0x0600004, 0x80000, CRC(ec418b68) SHA1(8455db7e174ea00db30b7e61681ac7b7fcd9ba1c) ) @@ -2267,7 +2267,7 @@ ROM_START( scudj ) /* step 1.5, Sega game ID# is 833-13041, ROM board ID# 12934 ROM_END ROM_START( scuda ) /* step 1.5, Sega game ID# is 833-13041, ROM board ID# 834-13042 SPG FOR COMMUNICATION */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19688.17", 0x0600006, 0x80000, CRC(a4c85103) SHA1(b2e57f86d0a49e3e88fa7d6a77bbd99039c034bb) ) ROM_LOAD64_WORD_SWAP( "epr-19689.18", 0x0600004, 0x80000, CRC(cbce6d62) SHA1(b6051af013ee80406cfadb0c8acf24b8825ccaf2) ) @@ -2342,7 +2342,7 @@ ROM_START( scuda ) /* step 1.5, Sega game ID# is 833-13041, ROM board ID# 834-1 ROM_END ROM_START( scudplus ) /* step 1.5, Sega game ID# is 833-13260 SCUD PLUS, ROM board ID# 834-13261 SCUD PLUS */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20092a.17", 0x0600006, 0x80000, CRC(a94ec57e) SHA1(bda1d9cb38e10a25f7cdde38f30ae13541fdbc5e) ) ROM_LOAD64_WORD_SWAP( "epr-20093a.18", 0x0600004, 0x80000, CRC(4ed2e35d) SHA1(ac149b369db9fc80e63e1ed943d42ccd056dab1b) ) @@ -2423,7 +2423,7 @@ ROM_START( scudplus ) /* step 1.5, Sega game ID# is 833-13260 SCUD PLUS, ROM b ROM_END ROM_START( scudplusa ) /* step 1.5, Sega game ID# is 833-13260 SCUD PLUS, ROM board ID# 834-13261 SCUD PLUS */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20092.17", 0x0600006, 0x80000, CRC(6f9161c1) SHA1(b1c66eeb1bb67664aafa78ad62515204f231f09b) ) ROM_LOAD64_WORD_SWAP( "epr-20093.18", 0x0600004, 0x80000, CRC(9a85c611) SHA1(fb21c29584b205ec14f82318110ecf5821a95c23) ) @@ -2504,7 +2504,7 @@ ROM_START( scudplusa ) /* step 1.5, Sega game ID# is 833-13260 SCUD PLUS, ROM b ROM_END ROM_START( vf3 ) /* step 1.0, Sega game ID# is 833-12712, ROM board ID# 834-12821 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19227c.17", 0x600006, 0x080000, CRC(a7df4d75) SHA1(1b1186227f830556c5e2b6ca4c2bf20673b22f94) ) ROM_LOAD64_WORD_SWAP( "epr-19228c.18", 0x600004, 0x080000, CRC(9c5727e2) SHA1(f9f8b8cf27fdce08ab2975dbaa8c7a03f5c064fb) ) @@ -2579,7 +2579,7 @@ ROM_START( vf3 ) /* step 1.0, Sega game ID# is 833-12712, ROM board ID# 834-1 ROM_END ROM_START( vf3a ) /* step 1.0, Sega game ID# is 833-12712, ROM board ID# 834-12821 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr19227a.17", 0x600006, 0x080000, CRC(7139931a) SHA1(57eec80361726143017b1adbfaafbeef0bc4109d) ) ROM_LOAD64_WORD_SWAP( "epr19228a.18", 0x600004, 0x080000, CRC(82f17ab5) SHA1(64714d14e64d97ebeedd1c6e1e832969df9e2324) ) @@ -2654,7 +2654,7 @@ ROM_START( vf3a ) /* step 1.0, Sega game ID# is 833-12712, ROM board ID# 834-1 ROM_END ROM_START( vf3tb ) /* step 1.0? */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20126.17", 0x600006, 0x080000, CRC(27ecd3b0) SHA1(a9b913294ac925adb501d3b47f346006b70dfcd6) ) ROM_LOAD64_WORD_SWAP( "epr-20127.18", 0x600004, 0x080000, CRC(5c0f694b) SHA1(ca346d6b249bb7a3015f016d25bfb3050360c8ec) ) @@ -2729,7 +2729,7 @@ ROM_START( vf3tb ) /* step 1.0? */ ROM_END ROM_START( bass ) /* step 1.0, Sega game ID# is 833-13317, ROM board ID# 834-13318 BSS */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20643.17", 0x600006, 0x080000, CRC(daf02716) SHA1(b968f8ca602c78b9ca49969ff01f9440f175049a) ) ROM_LOAD64_WORD_SWAP( "epr-20644.18", 0x600004, 0x080000, CRC(c28db2b6) SHA1(0b12fe9e5189714b1aca79c4bba4be57a9e0d5fd) ) @@ -2798,7 +2798,7 @@ ROM_START( bass ) /* step 1.0, Sega game ID# is 833-13317, ROM board ID# 834-1 ROM_END ROM_START( bassdx ) /* step 1.0, Sega game ID# is 833-13476 BSS DX JPN, ROM board ID# 834-13477 BSS DX JPN */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20834.17", 0x600006, 0x080000, CRC(17f466a6) SHA1(2abdc432891cc79733fc29903df87af9eba11b32) ) ROM_LOAD64_WORD_SWAP( "epr-20835.18", 0x600004, 0x080000, CRC(f8f19bb2) SHA1(8f1704e532e494086fb5989d0c358ea0a0f6aae5) ) @@ -2892,7 +2892,7 @@ gal16v8d (sega 315-6126) */ ROM_START( getbass ) /* step 1.0, Sega game ID# is 833-13416 GET BASS STD, ROM board ID# 834-13417 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20309.17", 0x600006, 0x080000, CRC(a42e1033) SHA1(a834eb973e9529338413220a2d8e66ce98d6cb31) ) ROM_LOAD64_WORD_SWAP( "epr-20310.18", 0x600004, 0x080000, CRC(4efcddc9) SHA1(d1362c2a844b605901083e875a6aad817401eb0a) ) @@ -2964,7 +2964,7 @@ ROM_START( getbass ) /* step 1.0, Sega game ID# is 833-13416 GET BASS STD, RO ROM_END ROM_START( lostwsga ) /* Step 1.5, PCB cage labeled 834-13172 THE LOST WORLD U/R. Sega game ID# is 833-13171, ROM board ID# 834-13172 REV.A */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19939a.17", 0x600006, 0x080000, CRC(8788b939) SHA1(30932057f763545568526f85977aa0afc4b66e7d) ) ROM_LOAD64_WORD_SWAP( "epr-19938a.18", 0x600004, 0x080000, CRC(38afe27a) SHA1(718a238ee246eeed9fa698b58493806932d0e7cb) ) @@ -3039,7 +3039,7 @@ ROM_START( lostwsga ) /* Step 1.5, PCB cage labeled 834-13172 THE LOST WORLD U ROM_END ROM_START( vs2 ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20467.17", 0x400006, 0x100000, CRC(25d7ae73) SHA1(433a7c1dac1bd5524b018da2ed09f937d527ac3e) ) ROM_LOAD64_WORD_SWAP( "epr-20468.18", 0x400004, 0x100000, CRC(f0f0b6ea) SHA1(b3f545e5a4dd45b97df938093251cc7845c2a1f9) ) @@ -3114,7 +3114,7 @@ ROM_START( vs2 ) /* Step 2.0 */ ROM_END ROM_START( vs215 ) /* Step 1.5 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19900.17", 0x600006, 0x080000, CRC(8fb6045d) SHA1(88497eafc23ba70ab4a43de552a16caccd8dccbe) ) ROM_LOAD64_WORD_SWAP( "epr-19899.18", 0x600004, 0x080000, CRC(8cc2be9f) SHA1(ec82b1312c8d58adb200f4d7f6f9a9c8214415d5) ) @@ -3189,7 +3189,7 @@ ROM_START( vs215 ) /* Step 1.5 */ ROM_END ROM_START( vs215o ) /* Step 1.5, original release.. might even be for Step 1.0??? */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-19806.17", 0x600006, 0x080000, CRC(95e1b970) SHA1(bcc914088cd08cb0032349b71904757760d947f3) ) ROM_LOAD64_WORD_SWAP( "epr-19805.18", 0x600004, 0x080000, CRC(d9e40606) SHA1(b305e607ffe4226c825a73973a5c8ec1322e8b58) ) @@ -3264,7 +3264,7 @@ ROM_START( vs215o ) /* Step 1.5, original release.. might even be for Step 1.0?? ROM_END ROM_START( vs298 ) /* Step 2.0, Sega ID# 833-13346, ROM board ID# 834-13347 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20917.17", 0x400006, 0x100000, CRC(c3bbb270) SHA1(16b2342031ff72408f2290e775df5c8aa344c2e4) ) ROM_LOAD64_WORD_SWAP( "epr-20918.18", 0x400004, 0x100000, CRC(0e9cdc5b) SHA1(356816d0380c791b9d812ce17fa95123d15bb5e9) ) @@ -3342,7 +3342,7 @@ ROM_START( vs298 ) /* Step 2.0, Sega ID# 833-13346, ROM board ID# 834-13347 */ ROM_END ROM_START( vs29815 ) /* Step 1.5, ROM board ID# 834-13495 VS2 VER98 STEP 1.5 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20909.17", 0x600006, 0x080000, CRC(3dff0d7e) SHA1(c6a6a103f499cd451796ae2480b8c38c3e87a143) ) ROM_LOAD64_WORD_SWAP( "epr-20910.18", 0x600004, 0x080000, CRC(dc75a2e3) SHA1(f1b13674ae20b5b964be593171b9d6008d5a51b7) ) @@ -3417,7 +3417,7 @@ ROM_START( vs29815 ) /* Step 1.5, ROM board ID# 834-13495 VS2 VER98 STEP 1.5 ROM_END ROM_START( vs2v991 ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21535b.17", 0x400006, 0x100000, CRC(76c5fa8e) SHA1(862438198cb7fdd20beeba53e707a7c59e618ad9) ) ROM_LOAD64_WORD_SWAP( "epr-21536b.18", 0x400004, 0x100000, CRC(1f2bd190) SHA1(19843e6c5626de03eba3cba79c03ce9f2471c183) ) @@ -3495,7 +3495,7 @@ ROM_START( vs2v991 ) /* Step 2.0 */ ROM_END ROM_START( vs299b ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21550b.17", 0x400006, 0x100000, CRC(c508e488) SHA1(3134d418beaee9f824a0bd0e5441a997b5911d16) ) ROM_LOAD64_WORD_SWAP( "epr-21551b.18", 0x400004, 0x100000, CRC(0bbc40f7) SHA1(4437c7eab621349b826dcc03d1377731260417e8) ) @@ -3573,7 +3573,7 @@ ROM_START( vs299b ) /* Step 2.0 */ ROM_END ROM_START( vs299a ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21535a.17", 0x400006, 0x100000, CRC(8e4ec341) SHA1(973c71e7a48e728cbcb2465b56e90669fee0ec53) ) ROM_LOAD64_WORD_SWAP( "epr-21536a.18", 0x400004, 0x100000, CRC(95d49d6e) SHA1(80b6655c1ee0f76620e3e2e9425719819a96ccf7) ) @@ -3651,7 +3651,7 @@ ROM_START( vs299a ) /* Step 2.0 */ ROM_END ROM_START( vs299 ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21535.17", 0x400006, 0x100000, CRC(976a00bf) SHA1(d4be52ff59faa877b169f96ac509a2196cefb908) ) ROM_LOAD64_WORD_SWAP( "epr-21536.18", 0x400004, 0x100000, CRC(9af2b0d5) SHA1(6ec296014228782f372611fe774014d252956b63) ) @@ -3729,7 +3729,7 @@ ROM_START( vs299 ) /* Step 2.0 */ ROM_END ROM_START( von2 ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20683b.17", 0x000006, 0x200000, CRC(59d9c974) SHA1(c45594ed474a9e8fd074e0d9d5fa6662bc88dee6) ) ROM_LOAD64_WORD_SWAP( "epr-20684b.18", 0x000004, 0x200000, CRC(1fc15431) SHA1(c68c77dfcf5e2702214d64095ce07076d3702a5e) ) @@ -3808,7 +3808,7 @@ ROM_START( von2 ) /* Step 2.0 */ ROM_END ROM_START( von254g ) /* Step 2.0, Sega game ID# is 833-13789 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21788.17", 0x000006, 0x200000, CRC(97066bcf) SHA1(234c45ee1f23b22f61893825eebf31d867cf420f) ) ROM_LOAD64_WORD_SWAP( "epr-21789.18", 0x000004, 0x200000, CRC(3069108f) SHA1(f4e82da677458423abcf07c9c5a837005ed8f1c4) ) @@ -3887,7 +3887,7 @@ ROM_START( von254g ) /* Step 2.0, Sega game ID# is 833-13789 */ ROM_END ROM_START( skichamp ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20352.17", 0x000006, 0x200000, CRC(c92c2545) SHA1(612c39c935b403484fcda6d36fca50cc5ef726fc) ) ROM_LOAD64_WORD_SWAP( "epr-20353.19", 0x000004, 0x200000, CRC(badf5f04) SHA1(65a502a3fada114a699d0bf22e004d5bf1f5edf5) ) @@ -3959,7 +3959,7 @@ ROM_START( skichamp ) /* Step 2.0 */ ROM_END ROM_START( swtrilgy ) /* Step 2.1, Sega game ID# is 833-13586, ROM board ID# 834-13587 STAR WARS TRILOGY, Security board ID# 837-13588-COM */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21379a.17", 0x000006, 0x200000, CRC(24dc1555) SHA1(0a4b458bb09238de0f38ba2805512b5dbee7d58e) ) ROM_LOAD64_WORD_SWAP( "epr-21380a.18", 0x000004, 0x200000, CRC(780fb4e7) SHA1(6650e114bad0e4c3f67b744599dba9845da82f11) ) @@ -4034,7 +4034,7 @@ ROM_START( swtrilgy ) /* Step 2.1, Sega game ID# is 833-13586, ROM board ID# 8 ROM_END ROM_START( swtrilgya ) /* Step 2.1, Sega game ID# is 833-13586, ROM board ID# 834-13587 STAR WARS TRILOGY, Security board ID# 837-13588-COM */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21379.17", 0x000006, 0x200000, CRC(61ad51d9) SHA1(b27ea929702bb94c86d03d6c1f479af32230b4d0) ) ROM_LOAD64_WORD_SWAP( "epr-21380.18", 0x000004, 0x200000, CRC(49b182f2) SHA1(9a4e3180f2661c95976963ab17e66a5184bca9a3) ) @@ -4106,7 +4106,7 @@ ROM_START( swtrilgya ) /* Step 2.1, Sega game ID# is 833-13586, ROM board ID# 8 ROM_END ROM_START( dirtdvls ) /* Step 2.1 - Export version, Sega game ID# is 833-13427, ROM board ID# 834-13528 DRT */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21062a.17", 0x000006, 0x200000, CRC(64b55254) SHA1(0e5de3786edad77dde08652ac837dc9125e7851c) ) ROM_LOAD64_WORD_SWAP( "epr-21063a.18", 0x000004, 0x200000, CRC(6ab7eb32) SHA1(3a4226d4c786e7b64688af3b8883b4039b8c8407) ) @@ -4170,7 +4170,7 @@ ROM_START( dirtdvls ) /* Step 2.1 - Export version, Sega game ID# is 833-13427 ROM_END ROM_START( dirtdvlsa ) /* Step 2.1 - Australia version */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21058a", 0x000006, 0x200000, CRC(4d7fdc8d) SHA1(c45031b4e3ea65519de671e0e11f87e0965e3c93) ) ROM_LOAD64_WORD_SWAP( "epr-21059a", 0x000004, 0x200000, CRC(f31a2aa4) SHA1(b7398db217372885f763efdb909f3e43ccbac34a) ) @@ -4400,7 +4400,7 @@ ROM_START( dayto2pe ) /* Step 2.1, Sega game ID# is 833-13610 DAYTONA USA2 SP, ROM_END ROM_START( srally2 ) /* Step 2.0, Sega game ID# is 833-13373, ROM board ID# 834-13374 SRT TWIN */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20632.17", 0x000006, 0x200000, CRC(6829a801) SHA1(2aa3834f6a8c53f5db57ab52994b8ab3fde2d7c2) ) ROM_LOAD64_WORD_SWAP( "epr-20633.18", 0x000004, 0x200000, CRC(f5a24f24) SHA1(6f741bc53d51ff4b5535dbee35aa490f159945ec) ) @@ -4472,7 +4472,7 @@ ROM_START( srally2 ) /* Step 2.0, Sega game ID# is 833-13373, ROM board ID# 8 ROM_END ROM_START( srally2x ) /* Step 2.0 */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20502.17", 0x000006, 0x200000, CRC(af16846d) SHA1(a0babc4dc3809ca1e71eaad4dc2f8c1597575e8b) ) ROM_LOAD64_WORD_SWAP( "epr-20503.18", 0x000004, 0x200000, CRC(6e238b3d) SHA1(78da9abf39a2371d74d6b72b00f2467dfe86c4d5) ) @@ -4541,7 +4541,7 @@ ROM_START( srally2x ) /* Step 2.0 */ ROM_END ROM_START( harley ) /* Step 2.0, Sega game ID# is 833-13325, ROM board ID# 834-13326 HARLEY DAVIDSON */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20393b.17", 0x000006, 0x200000, CRC(7d712105) SHA1(35e0849f498de48fcb357495b6e8039740b8e881) ) ROM_LOAD64_WORD_SWAP( "epr-20394b.18", 0x000004, 0x200000, CRC(b4312135) SHA1(79c4306acd8c20f86d16a18de696783f7da9df84) ) @@ -4609,7 +4609,7 @@ ROM_START( harley ) /* Step 2.0, Sega game ID# is 833-13325, ROM board ID# 834-1 ROM_END ROM_START( harleya ) /* Step 2.0, Sega game ID# is 833-13325, ROM board ID# 834-13326 HARLEY DAVIDSON */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20393a.17", 0x000006, 0x200000, CRC(b5646556) SHA1(4bff0e140e1d1df7459f7194aa4a335bc4592203) ) ROM_LOAD64_WORD_SWAP( "epr-20394a.18", 0x000004, 0x200000, CRC(ce29e2b6) SHA1(482aaf5480b219b8ac6e4e36a6d64359e1834f44) ) @@ -4677,7 +4677,7 @@ ROM_START( harleya ) /* Step 2.0, Sega game ID# is 833-13325, ROM board ID# 8 ROM_END ROM_START( fvipers2 ) /* Step 2.0 - Japan version */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-20596a.17", 0x000006, 0x200000, CRC(969ab801) SHA1(a7a2aa71204d1c38a6a8c0605331fd859cb224f1) ) ROM_LOAD64_WORD_SWAP( "epr-20597a.18", 0x000004, 0x200000, CRC(6fcee322) SHA1(d65303f2551902ac5446a35656241628d67f4a63) ) @@ -4915,7 +4915,7 @@ ROM_START( spikeofe ) /* Step 2.1, Sega game ID# is 833-13746, ROM board ID# 8 ROM_END ROM_START( eca ) /* Step 2.1 Export version */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-22903.17", 0x000006, 0x200000, CRC(53882217) SHA1(163cbc92ff88671882cc1af377ceec80ba9f36db) ) ROM_LOAD64_WORD_SWAP( "epr-22904.18", 0x000004, 0x200000, CRC(0ff828a8) SHA1(2a74414891ceb5989e6ccb6e9d597f7d2e31fec4) ) // == epr-22896.18 @@ -4986,7 +4986,7 @@ ROM_START( eca ) /* Step 2.1 Export version */ ROM_END ROM_START( ecau ) /* Step 2.1, ROM board ID# 834-13946-01 ECA */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-22895.17", 0x000006, 0x200000, CRC(07df16a0) SHA1(a9ad2b229854a5f4f761565141db738adde28720) ) ROM_LOAD64_WORD_SWAP( "epr-22896.18", 0x000004, 0x200000, CRC(0ff828a8) SHA1(2a74414891ceb5989e6ccb6e9d597f7d2e31fec4) ) @@ -5057,7 +5057,7 @@ ROM_START( ecau ) /* Step 2.1, ROM board ID# 834-13946-01 ECA */ ROM_END ROM_START( ecap ) /* Step 2.1 - Proto or Location test - No security dongle */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM // Hand written SEGA labels in this form: TITLE: QQ ROM NO: IC17 CHECK SUM: 551B 9/12-'99 ROM_LOAD64_WORD_SWAP( "qq.ic17", 0x000006, 0x200000, BAD_DUMP CRC(1db889e0) SHA1(b9a5f344685e1d8b5711d8ab426bb886c1008e48) ) /* Check sum: 551B, dated "9/12-'99" */ @@ -5131,7 +5131,7 @@ ROM_START( ecap ) /* Step 2.1 - Proto or Location test - No security dongle */ ROM_END ROM_START( magtruck ) /* Step 2.1, Sega game ID# is 833-13601-01 (Export), ROM board ID# 834-13600-01 RCS EXP (Export), Security board ID# 837-13599-COM */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21435.17", 0x000006, 0x200000, CRC(9b169446) SHA1(285cbe5afd439d83c50f0499a878f71b8e5b94e5) ) ROM_LOAD64_WORD_SWAP( "epr-21433.18", 0x000004, 0x200000, CRC(60aa9d76) SHA1(b27741568a4fd0494b2254e468faea569e2d9fef) ) @@ -5261,7 +5261,7 @@ ROM_START( oceanhun ) /* Step 2.0, Sega game ID# is 833-13571, ROM board ID# 8 ROM_END ROM_START( lamachin ) /* Step 2.0, Sega game ID# is 833-13664, ROM board ID# 834-13665 L.A.MACHINEGUNS, 317-0244-COM security chip (837-13666-COM security board) */ - ROM_REGION64_BE( 0x4800000, "user1", 0 ) /* program + data ROMs */ + ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */ // CROM ROM_LOAD64_WORD_SWAP( "epr-21483.17", 0x000006, 0x200000, CRC(940637c2) SHA1(89894b603c17d27f57500ec8030eaa7e0e991479) ) ROM_LOAD64_WORD_SWAP( "epr-21484.18", 0x000004, 0x200000, CRC(58102168) SHA1(38dd9a41f653c0a84ac927b476f014c949454ffa) ) @@ -5690,6 +5690,9 @@ DRIVER_INIT_MEMBER(model3_state,scud) DRIVER_INIT_CALL(model3_15); /* TODO: network device at 0xC0000000 - FF */ 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)); + +// UINT32 *rom = (UINT32*)memregion("user1")->base(); +// rom[(0x799de8^4)/4] = 0x00050208; // secret debug menu } DRIVER_INIT_MEMBER(model3_state,scudplus) @@ -5822,6 +5825,15 @@ DRIVER_INIT_MEMBER(model3_state,harley) 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)); } +DRIVER_INIT_MEMBER(model3_state,harleya) +{ + DRIVER_INIT_CALL(model3_20); + + m_network_ram = auto_alloc_array_clear(machine(), UINT64, 0x10000); + 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)); +} + + DRIVER_INIT_MEMBER(model3_state,srally2) { DRIVER_INIT_CALL(model3_20); @@ -5937,6 +5949,16 @@ DRIVER_INIT_MEMBER(model3_state,eca) { DRIVER_INIT_CALL(model3_20); DRIVER_INIT_CALL(genprot); + + // base = 0xffc80000 + UINT32 *rom = (UINT32*)memregion("user1")->base(); + + // cabinet network error + rom[(0x4a45e4^4)/4] = 0x60000000; + + // this code sometimes gets stuck waiting for [0x1e0064], changed by the sound irq (sound FIFO overflow?) + rom[(0x5523b4^4)/4] = 0x60000000; + rom[(0x5523d4^4)/4] = 0x60000000; } DRIVER_INIT_MEMBER(model3_state,skichamp) @@ -6002,7 +6024,7 @@ GAME( 1998, vs29815, vs298, model3_15, model3, model3_state, vs29815, ROT0 /* Model 3 Step 2.0 */ 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 ) 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 ) -GAME( 1997, harleya, harley, model3_20, harley, model3_state, harley, ROT0, "Sega", "Harley-Davidson and L.A. Riders (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) +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 ) GAME( 1998, lamachin, 0, model3_20_5881, model3, model3_state, lamachin, ROT0, "Sega", "L.A. Machineguns (Japan)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) GAME( 1998, oceanhun, 0, model3_20_5881, model3, model3_state, oceanhun, ROT0, "Sega", "The Ocean Hunter", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) GAME( 1998, skichamp, 0, model3_20, skichamp, model3_state, skichamp, ROT0, "Sega", "Ski Champ (Japan)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND ) diff --git a/src/mame/includes/model3.h b/src/mame/includes/model3.h index 096691a831a..f2b63678309 100644 --- a/src/mame/includes/model3.h +++ b/src/mame/includes/model3.h @@ -22,14 +22,6 @@ struct cached_texture rgb_t data[1]; }; -struct m3_plane -{ - float x; - float y; - float z; - float d; -}; - struct m3_vertex { float x; @@ -47,9 +39,11 @@ struct m3_clip_vertex float x; float y; float z; + float w; float u; float v; float i; + float s; }; struct m3_triangle @@ -149,7 +143,7 @@ public: UINT8 m_id_data[32]; INT32 m_id_size; int m_tdo; - UINT8 m_layer_priority; + UINT16 m_layer_priority; UINT32 m_layer_modulate_r; UINT32 m_layer_modulate_g; UINT32 m_layer_modulate_b; @@ -175,12 +169,13 @@ public: int m_list_depth; MATRIX *m_matrix_stack; MATRIX m_coordinate_system; - float m_viewport_focal_length; - int m_viewport_region_x; - int m_viewport_region_y; - int m_viewport_region_width; - int m_viewport_region_height; - m3_plane m_clip_plane[5]; + MATRIX m_projection_matrix; + float m_viewport_x; + float m_viewport_y; + float m_viewport_width; + float m_viewport_height; + float m_viewport_near; + float m_viewport_far; UINT32 m_matrix_base_address; cached_texture *m_texcache[2][1024/32][2048/32]; @@ -249,6 +244,7 @@ public: DECLARE_DRIVER_INIT(daytona2); DECLARE_DRIVER_INIT(eca); DECLARE_DRIVER_INIT(srally2); + DECLARE_DRIVER_INIT(harleya); DECLARE_DRIVER_INIT(skichamp); DECLARE_DRIVER_INIT(spikeofe); DECLARE_DRIVER_INIT(scud); @@ -302,11 +298,12 @@ public: void reset_triangle_buffers(); m3_triangle* push_triangle(bool alpha); void draw_layers(bitmap_rgb32 &bitmap, const rectangle &cliprect); - void draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, int layer, int bitdepth, int sx, int sy); + void draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, int layer, int sx, int sy, int prio); void draw_3d_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect); void invalidate_texture(int page, int texx, int texy, int texwidth, int texheight); cached_texture *get_texture(int page, int texx, int texy, int texwidth, int texheight, int format); inline void write_texture16(int xpos, int ypos, int width, int height, int page, UINT16 *data); + inline void write_texture8(int xpos, int ypos, int width, int height, int page, int upper, int lower, UINT16 *data); void real3d_upload_texture(UINT32 header, UINT32 *data); void init_matrix_stack(); void get_top_matrix(MATRIX *out); @@ -316,6 +313,7 @@ public: void translate_matrix_stack(float x, float y, float z); void draw_model(UINT32 addr); UINT32 *get_memory_pointer(UINT32 address); + void set_projection(float left, float right, float top, float bottom, float near, float far); void load_matrix(int matrix_num, MATRIX *out); void traverse_list4(int lod_num, UINT32 address); void traverse_list(UINT32 address); diff --git a/src/mame/video/model3.c b/src/mame/video/model3.c index 70da1deaacf..940a015d4e7 100644 --- a/src/mame/video/model3.c +++ b/src/mame/video/model3.c @@ -5,6 +5,18 @@ #include "video/rgbutil.h" #include "includes/model3.h" +/* + TODO: + - Tilemap flash effect + - Fog + - Mipmapping + - Mipmap uploads smaller than a tile + - Some of the 4-bit and 8-bit textures need their alpha values rechecked + - Spotlights + - Recheck normal vector transform + +*/ + #define ENABLE_BILINEAR 1 #define TRI_PARAM_TEXTURE_PAGE 0x1 @@ -12,8 +24,9 @@ #define TRI_PARAM_TEXTURE_MIRROR_V 0x4 #define TRI_PARAM_TEXTURE_ENABLE 0x8 #define TRI_PARAM_ALPHA_TEST 0x10 +#define TRI_PARAM_COLOR_MOD 0x20 -#define TRI_BUFFER_SIZE 35000 +#define TRI_BUFFER_SIZE 50000 #define TRI_ALPHA_BUFFER_SIZE 15000 struct model3_polydata @@ -41,7 +54,9 @@ public: void clear_fb(); void clear_zb(); void draw_scanline_solid(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); + void draw_scanline_solid_trans(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); void draw_scanline_tex(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); + void draw_scanline_tex_colormod(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); void draw_scanline_tex_contour(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); void draw_scanline_tex_trans(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); void draw_scanline_tex_alpha(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid); @@ -136,7 +151,7 @@ void model3_state::video_start() static const gfx_layout char4_layout = { 8, 8, - 30720, + 31744, 4, { 0,1,2,3 }, { 0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4 }, @@ -147,7 +162,7 @@ void model3_state::video_start() static const gfx_layout char8_layout = { 8, 8, - 15360, + 15872, 8, { 0,1,2,3,4,5,6,7 }, { 4*8, 5*8, 6*8, 7*8, 0*8, 1*8, 2*8, 3*8 }, @@ -183,12 +198,6 @@ void model3_state::video_start() m_vid_reg0 = 0; - m_viewport_focal_length = 300.; - m_viewport_region_x = 0; - m_viewport_region_y = 0; - m_viewport_region_width = 496; - m_viewport_region_height = 384; - m_layer4[0] = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(model3_state::tile_info_layer0_4bit), this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); m_layer8[0] = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(model3_state::tile_info_layer0_8bit), this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); m_layer4[1] = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(model3_state::tile_info_layer1_4bit), this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); @@ -253,14 +262,18 @@ void model3_state::draw_texture_sheet(bitmap_ind16 &bitmap, const rectangle &cli } #endif -void model3_state::draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, int layer, int bitdepth, int sx, int sy) +void model3_state::draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, int layer, int sx, int sy, int prio) { + int bitdepth = (m_layer_priority & (0x10 << layer)) ? 1 : 0; +// int layer_prio = (m_layer_priority & (0x1 << layer)) ? 1 : 0; + tilemap_t *tmap = bitdepth ? m_layer4[layer] : m_layer8[layer]; bitmap_ind16 &pixmap = tmap->pixmap(); const pen_t *pens = m_palette->pens(); UINT32* palram = (UINT32*)&m_paletteram64[0]; UINT16* rowscroll_ram = (UINT16*)&m_m3_char_ram[0x1ec00]; + UINT32* rowmask_ram = (UINT32*)&m_m3_char_ram[0x1ee00]; int x1 = cliprect.min_x; int y1 = cliprect.min_y; @@ -287,6 +300,12 @@ void model3_state::draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, i if (rowscroll & 0x100) rowscroll |= ~0x1ff; + UINT16 rowmask; + if (prio && (layer == 1 || layer == 2)) + rowmask = BYTE_REVERSE32(rowmask_ram[(y & 0x1ff) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)]) & 0xffff; + else + rowmask = 0xffff; + int iix = ix & 0x1ff; int rx1 = x1 - (rowscroll * 2); @@ -302,10 +321,15 @@ void model3_state::draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, i for (int x = rx1; x <= rx2; x++) { - UINT16 p0 = src[iix & 0x1ff]; - if ((palram[p0^NATIVE_ENDIAN_VALUE_LE_BE(1,0)] & NATIVE_ENDIAN_VALUE_LE_BE(0x00800000,0x00008000)) == 0) + UINT32 mask = rowmask & (1 << ((iix & 0x1ff) >> 5)); + + if (mask) { - dst[x] = pens[p0]; + UINT16 p0 = src[iix & 0x1ff]; + if ((palram[p0^NATIVE_ENDIAN_VALUE_LE_BE(1,0)] & NATIVE_ENDIAN_VALUE_LE_BE(0x00800000,0x00008000)) == 0) + { + dst[x] = pens[p0]; + } } iix++; } @@ -339,26 +363,26 @@ UINT32 model3_state::screen_update_model3(screen_device &screen, bitmap_rgb32 &b // render enabled layers with priority 0 if ((layer_data[3] & 0x80000000) && (m_layer_priority & 0x8) == 0) - draw_layer(bitmap, cliprect, 3, m_layer_priority & 0x80, layer_scroll_x[3], layer_scroll_y[3]); + draw_layer(bitmap, cliprect, 3, layer_scroll_x[3], layer_scroll_y[3], 0); if ((layer_data[2] & 0x80000000) && (m_layer_priority & 0x4) == 0) - draw_layer(bitmap, cliprect, 2, m_layer_priority & 0x40, layer_scroll_x[2], layer_scroll_y[2]); + draw_layer(bitmap, cliprect, 2, layer_scroll_x[2], layer_scroll_y[2], 0); if ((layer_data[1] & 0x80000000) && (m_layer_priority & 0x2) == 0) - draw_layer(bitmap, cliprect, 1, m_layer_priority & 0x20, layer_scroll_x[1], layer_scroll_y[1]); + draw_layer(bitmap, cliprect, 1, layer_scroll_x[1], layer_scroll_y[1], 0); if ((layer_data[0] & 0x80000000) && (m_layer_priority & 0x1) == 0) - draw_layer(bitmap, cliprect, 0, m_layer_priority & 0x10, layer_scroll_x[0], layer_scroll_y[0]); + draw_layer(bitmap, cliprect, 0, layer_scroll_x[0], layer_scroll_y[0], 0); // render 3D m_renderer->draw(bitmap, cliprect); // render enabled layers with priority 1 if ((layer_data[3] & 0x80000000) && (m_layer_priority & 0x8) != 0) - draw_layer(bitmap, cliprect, 3, m_layer_priority & 0x80, layer_scroll_x[3], layer_scroll_y[3]); + draw_layer(bitmap, cliprect, 3, layer_scroll_x[3], layer_scroll_y[3], 1); if ((layer_data[2] & 0x80000000) && (m_layer_priority & 0x4) != 0) - draw_layer(bitmap, cliprect, 2, m_layer_priority & 0x40, layer_scroll_x[2], layer_scroll_y[2]); - if ((layer_data[1] & 0x80000000) && (m_layer_priority & 0x2) != 0) - draw_layer(bitmap, cliprect, 1, m_layer_priority & 0x20, layer_scroll_x[1], layer_scroll_y[1]); + draw_layer(bitmap, cliprect, 2, layer_scroll_x[2], layer_scroll_y[2], 1); if ((layer_data[0] & 0x80000000) && (m_layer_priority & 0x1) != 0) - draw_layer(bitmap, cliprect, 0, m_layer_priority & 0x10, layer_scroll_x[0], layer_scroll_y[0]); + draw_layer(bitmap, cliprect, 0, layer_scroll_x[0], layer_scroll_y[0], 1); + if ((layer_data[1] & 0x80000000) && (m_layer_priority & 0x2) != 0) + draw_layer(bitmap, cliprect, 1, layer_scroll_x[1], layer_scroll_y[1], 1); return 0; } @@ -422,7 +446,8 @@ WRITE64_MEMBER(model3_state::model3_tile_w) 0xF1180010: VBL IRQ acknowledge - 0xF1180020: -------- x------- -------- -------- Layer 3 bitdepth (0 = 8-bit, 1 = 4-bit) + 0xF1180020: xxxxxxxx -------- -------- -------- ? + -------- x------- -------- -------- Layer 3 bitdepth (0 = 8-bit, 1 = 4-bit) -------- -x------ -------- -------- Layer 2 bitdepth (0 = 8-bit, 1 = 4-bit) -------- --x----- -------- -------- Layer 1 bitdepth (0 = 8-bit, 1 = 4-bit) -------- ---x---- -------- -------- Layer 0 bitdepth (0 = 8-bit, 1 = 4-bit) @@ -571,50 +596,53 @@ cached_texture *model3_state::get_texture(int page, int texx, int texy, int texw } break; - case 1: /* 4-bit grayscale in low nibble */ + case 1: /* A4L4 interleaved */ for (x = 0; x < pixwidth; x++) { - UINT8 grayvalue = pal4bit(texsrc[x] >> 0); - alpha &= dest[x] = rgb_t(0xff, grayvalue, grayvalue, grayvalue); + UINT8 grayvalue = pal4bit(texsrc[x] & 0xf); + UINT8 a = pal4bit((texsrc[x] >> 4) & 0xf); + alpha &= dest[x] = rgb_t(a, grayvalue, grayvalue, grayvalue); } break; - case 2: /* 4-bit grayscale in 2nd nibble */ + case 2: /* A4L4? */ for (x = 0; x < pixwidth; x++) { - UINT8 grayvalue = pal4bit(texsrc[x] >> 4); - alpha &= dest[x] = rgb_t(0xff, grayvalue, grayvalue, grayvalue); + UINT8 grayvalue = pal4bit((texsrc[x] >> 0) & 0xf); + UINT8 a = pal4bit((texsrc[x] >> 4) & 0xf); + alpha &= dest[x] = rgb_t(a, grayvalue, grayvalue, grayvalue); } break; - case 3: /* 4-bit grayscale in 3rd nibble */ + case 3: /* A4L4 interleaved */ for (x = 0; x < pixwidth; x++) { - UINT8 grayvalue = pal4bit(texsrc[x] >> 8); - alpha &= dest[x] = rgb_t(0xff, grayvalue, grayvalue, grayvalue); + UINT8 grayvalue = pal4bit((texsrc[x] >> 8) & 0xf); + UINT8 a = pal4bit((texsrc[x] >> 12) & 0xf); + alpha &= dest[x] = rgb_t(a, grayvalue, grayvalue, grayvalue); } break; case 4: /* 8-bit A4L4 */ for (x = 0; x < pixwidth; x++) { - UINT8 pixdata = texsrc[x / 2] >> ((~x & 1) * 8); - alpha &= dest[x] = rgb_t(pal4bit(pixdata >> 4), pal4bit(~pixdata), pal4bit(~pixdata), pal4bit(~pixdata)); + UINT8 pixdata = texsrc[x] >> 8; + alpha &= dest[x] = rgb_t(pal4bit(pixdata), pal4bit(pixdata >> 4), pal4bit(pixdata >> 4), pal4bit(pixdata >> 4)); } break; - case 5: /* 8-bit grayscale */ + case 5: /* L8 */ for (x = 0; x < pixwidth; x++) { - UINT8 grayvalue = texsrc[x / 2] >> ((~x & 1) * 8); + UINT8 grayvalue = texsrc[x]; alpha &= dest[x] = rgb_t(0xff, grayvalue, grayvalue, grayvalue); } break; - case 6: /* 4-bit grayscale in high nibble */ + case 6: /* L8 */ for (x = 0; x < pixwidth; x++) { - UINT8 grayvalue = pal4bit(texsrc[x] >> 12); + UINT8 grayvalue = texsrc[x] >> 8; alpha &= dest[x] = rgb_t(0xff, grayvalue, grayvalue, grayvalue); } break; @@ -688,23 +716,23 @@ cached_texture *model3_state::get_texture(int page, int texx, int texy, int texw 0x01: Child node pointer (inherits parameters from this node) 0x02: Sibling node pointer - 0x03: Unknown (float) + 0x03: (float) Focal length? Affected by frustum angles and viewport size 0x04: Sun light vector Z-component (float) 0x05: Sun light vector X-component (float) 0x06: Sun light vector Y-component (float) 0x07: Sun light intensity (float) - 0x08: Far Clip plane Z - 0x09: Far Clip plane Distance - 0x0a: Near Clip plane Z - 0x0b: Near Clip plane Distance - 0x0c: Left Clip plane Z - 0x0d: Left Clip plane X - 0x0e: Top Clip plane Z - 0x0f: Top Clip plane Y - 0x10: Right Clip plane Z - 0x11: Right Clip plane X - 0x12: Bottom Clip plane Z - 0x13: Bottom Clip plane Y + 0x08: ? (float) Affected by left and right angle + 0x09: ? (float) Affected by top and bottom angle + 0x0a: ? (float) Affected by top and bottom angle + 0x0b: ? (float) Affected by left and right angle + 0x0c: (float) Frustum Left Angle Y (these angles are defined in polar coordinates) + 0x0d: (float) Frustum Left Angle X + 0x0e: (float) Frustum Top Angle Y + 0x0f: (float) Frustum Top Angle X + 0x10: (float) Frustum Right Angle Y + 0x11: (float) Frustum Right Angle X + 0x12: (float) Frustum Bottom Angle Y + 0x13: (float) Frustum Bottom Angle X 0x14: xxxxxxxx xxxxxxxx -------- -------- Viewport height (14.2 fixed-point) -------- -------- xxxxxxxx xxxxxxxx Viewport width (14.2 fixed-point) @@ -735,7 +763,7 @@ cached_texture *model3_state::get_texture(int page, int texx, int texy, int texw -------- -------- -----xxx -------- Light RGB Fog (RGB111?) -------- -------- -------- xxxxxxxx Scroll Fog (0.8 fixed-point?) What is this??? - 0x21: ? + 0x21: ? seen 8.0, 0.125, 1000000000.0 0x22: Fog Color (RGB888) 0x23: Fog Density (float) @@ -818,19 +846,24 @@ cached_texture *model3_state::get_texture(int page, int texx, int texy, int texw Polygon Data - 0x00: -------- xxxxxxxx xxxxxx-- -------- Polygon ID + 0x00: x------- -------- -------- -------- Supermodel says specular enable + -xxxxx-- -------- -------- -------- ? + ------xx xxxxxxxx xxxxxx-- -------- Polygon ID -------- -------- -------- -x------ 0 = Triangle, 1 = Quad -------- -------- -------- ----x--- Vertex 3 shared from previous polygon -------- -------- -------- -----x-- Vertex 2 shared from previous polygon -------- -------- -------- ------x- Vertex 1 shared from previous polygon -------- -------- -------- -------x Vertex 0 shared from previous polygon - xxxxxxxx -------- -------- x-xx---- ? + -------- -------- -------- x-xx---- ? -------- -------- ------xx -------- Broken polygons in srally2 set these (a way to mark them for HW to not render?) 0x01: xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal X coordinate (2.22 fixed point) -------- -------- -------- -x------ UV format (0 = 13.3, 1 = 16.0) + -------- -------- -------- ---x---- 1 = Double-sided polygon -------- -------- -------- -----x-- If set, this is the last polygon - -------- -------- -------- x-xxx-xx ? + -------- -------- -------- ------x- Poly color, 1 = RGB, 0 = color table + -------- -------- -------- x-x-x--x ? + 0x02: xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Y coordinate (2.22 fixed point) -------- -------- -------- ------x- Texture U mirror enable @@ -844,7 +877,8 @@ cached_texture *model3_state::get_texture(int page, int texx, int texy, int texw 0x04: xxxxxxxx xxxxxxxx xxxxxxxx -------- Color (RGB888) -------- -------- -------- -x------ Texture page -------- -------- -------- ---xxxxx Upper 5 bits of texture U coordinate - -------- -------- -------- x-x----- ? + -------- -------- -------- x------- ? + -------- -------- -------- --x----- ? 0x05: xxxxxxxx xxxxxxxx xxxxxxxx -------- Specular color? -------- -------- -------- x------- Low bit of texture U coordinate @@ -852,15 +886,28 @@ cached_texture *model3_state::get_texture(int page, int texx, int texy, int texw -------- -------- -------- -xx----- ? 0x06: x------- -------- -------- -------- Texture contour enable - -xxxxxxx -------- -------- -------- Specularity? + -xxxxx-- -------- -------- -------- Fixed shading? + ------x- -------- -------- -------- Enable fixed shading? + -------x -------- -------- -------- Could be high priority polygon? -------- x------- -------- -------- 1 = disable transparency? - -------- -xxxxx-- -------- -------- Polygon transparency (0 = fully transparent) + -------- -xxxxx-- -------- -------- Polygon translucency (0 = fully transparent) -------- -------x -------- -------- 1 = disable lighting - -------- -------- xxxxx--- -------- Polygon luminosity - -------- -------- -----x-- -------- Texture enable + -------- -------- xxxxx--- -------- Polygon light modifier (Amount that a luminous polygon will burn through fog. + Valid range is 0.0 to 1.0. 0.0 is completely fogged; + 1.0 has no fog.) + -------- -------- -----x-- -------- Texture enable -------- -------- ------xx x------- Texture format -------- -------- -------- -------x Alpha enable? - -------- ------x- -------- -xxxxxx- ? + -------- ------x- -------- -------- Never seen set? + -------- -------- -------- -----xx- Always set? + -------- -------- -------- -xxxx--- ? + + TODO: Bits to find (from Real3D dev guide): + SetHighPriority(): Indicates that the polygon has higher priority than others in scene + PolygonIsLayered(): Indicates a stencil polygon. + DoSmoothShading(): Indicates that the polygon will be smooth shaded + void SetNPScale ( float np_scale ) ; Sets the texture lod scale for the polygon. A value greater than 1 will increase the + range of the transition of texture level of detail. Vertex entry @@ -904,10 +951,10 @@ WRITE64_MEMBER(model3_state::real3d_polygon_ram_w) } } -static const UINT8 texture_decode[64] = +static const UINT8 texture_decode16[64] = { - 0, 1, 4, 5, 8, 9, 12, 13, - 2, 3, 6, 7, 10, 11, 14, 15, + 0, 1, 4, 5, 8, 9, 12, 13, + 2, 3, 6, 7, 10, 11, 14, 15, 16, 17, 20, 21, 24, 25, 28, 29, 18, 19, 22, 23, 26, 27, 30, 31, 32, 33, 36, 37, 40, 41, 44, 45, @@ -916,6 +963,18 @@ static const UINT8 texture_decode[64] = 50, 51, 54, 55, 58, 59, 62, 63 }; +static const UINT8 texture_decode8[32] = +{ + 1, 3, 5, 7, + 0, 2, 4, 6, + 9, 11, 13, 15, + 8, 10, 12, 14, + 17, 19, 21, 23, + 16, 18, 20, 22, + 25, 27, 29, 31, + 24, 26, 28, 30 +}; + inline void model3_state::write_texture16(int xpos, int ypos, int width, int height, int page, UINT16 *data) { int x,y,i,j; @@ -928,7 +987,7 @@ inline void model3_state::write_texture16(int xpos, int ypos, int width, int hei int b = 0; for(j=y; j < y+8; j++) { for(i=x; i < x+8; i++) { - *texture++ = data[texture_decode[b^1]]; + *texture++ = data[texture_decode16[b^1]]; ++b; } texture += 2048-8; @@ -938,28 +997,76 @@ inline void model3_state::write_texture16(int xpos, int ypos, int width, int hei } } -#ifdef UNUSED_FUNCTION -inline void model3_state::write_texture8(int xpos, int ypos, int width, int height, int page, UINT16 *data) +inline void model3_state::write_texture8(int xpos, int ypos, int width, int height, int page, int upper, int lower, UINT16 *data) { int x,y,i,j; - UINT16 color = 0x7c00; - for(y=ypos; y < ypos+(height/2); y+=4) + for(y=ypos; y < ypos+height; y+=8) { for(x=xpos; x < xpos+width; x+=8) { UINT16 *texture = &m_texture_ram[page][y*2048+x]; - for(j=y; j < y+4; j++) { - for(i=x; i < x+8; i++) { - *texture = color; + int b = 0; + for(j=y; j < y+8; j++) + { + for(i=x; i < x+8; i+=2) + { + UINT16 d = data[texture_decode8[b]]; + + if (upper) + *texture = (*texture & 0xff) | (d & 0xff00); + if (lower) + *texture = (*texture & 0xff00) | ((d >> 8) & 0xff); texture++; + + if (upper) + *texture = (*texture & 0xff) | ((d & 0xff) << 8); + if (lower) + *texture = (*texture & 0xff00) | (d & 0xff); + texture++; + + ++b; } texture += 2048-8; } + data += 32; } } } -#endif + +/* + Texture header: + + -------- -------- -------- --xxxxxx X-position + -------- -------- ----xxxx x------- Y-position + -------- -------x xx------ -------- Width + -------- ----xxx- -------- -------- Height + -------- ---x---- -------- -------- Texture page + -------- --x----- -------- -------- Write 8-bit data to the lower byte of texel + -------- -x------ -------- -------- Write 8-bit data to the upper byte of texel + -------- x------- -------- -------- Bitdepth, 0 = 8-bit, 1 = 16-bit + xxxxxxxx -------- -------- -------- Texture type + 0x00 = texture with mipmaps + 0x01 = texture without mipmaps + 0x02 = only mipmaps + 0x80 = possibly gamma table + +*/ + +static const int mipmap_coords[9][2] = +{ + { 1024, 512 }, + { 1536, 768 }, + { 1792, 896 }, + { 1920, 960 }, + { 1984, 992 }, + { 2016, 1008 }, + { 2032, 1016 }, + { 2040, 1020 }, + { 2044, 1022 }, +}; + +static const int mipmap_divider[9] = { 2, 4, 8, 16, 32, 64, 128, 256, 512 }; void model3_state::real3d_upload_texture(UINT32 header, UINT32 *data) { @@ -968,36 +1075,100 @@ void model3_state::real3d_upload_texture(UINT32 header, UINT32 *data) int xpos = (header & 0x3f) * 32; int ypos = ((header >> 7) & 0x1f) * 32; int page = (header >> 20) & 0x1; - //int bitdepth = (header >> 23) & 0x1; + int bitdepth = (header >> 23) & 0x1; + int upper_byte = (header >> 22) & 0x1; + int lower_byte = (header >> 21) & 0x1; + + //printf("write tex: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth); switch(header >> 24) { case 0x00: /* Texture with mipmaps */ - //if(bitdepth) { - write_texture16(xpos, ypos, width, height, page, (UINT16*)data); - invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7); - //} else { - /* TODO: 8-bit textures are weird. need to figure out some additional bits */ - //logerror("W: %d, H: %d, X: %d, Y: %d, P: %d, Bit: %d, : %08X, %08X\n", width, height, xpos, ypos, page, bitdepth, header & 0x00681040, header); - //write_texture8(xpos, ypos, width, height, page, (UINT16*)data); - //} + { + int x = xpos; + int y = ypos; + int w = width; + int h = height; + + int mipmap = 0; + + while (w >= 8 && h >= 8) + { + if (bitdepth) + { + write_texture16(x, y, w, h, page, (UINT16*)data); + } + else + { + //printf("write tex8: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth); + write_texture8(x, y, w, h, page, upper_byte, lower_byte, (UINT16*)data); + } + + data += (w * h * (bitdepth ? 2 : 1)) / 4; + w /= 2; + h /= 2; + + x = mipmap_coords[mipmap][0] + (xpos / mipmap_divider[mipmap]); + y = mipmap_coords[mipmap][1] + (ypos / mipmap_divider[mipmap]); + mipmap++; + } + + invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7); break; + } case 0x01: /* Texture without mipmaps */ - //if(bitdepth) { + { + if (bitdepth) + { write_texture16(xpos, ypos, width, height, page, (UINT16*)data); - invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7); - //} else { - /* TODO: 8-bit textures are weird. need to figure out some additional bits */ - //logerror("W: %d, H: %d, X: %d, Y: %d, P: %d, Bit: %d, : %08X, %08X\n", width, height, xpos, ypos, page, bitdepth, header & 0x00681040, header); - //write_texture8(xpos, ypos, width, height, page, (UINT16*)data); - //} + } + else + { + //printf("write tex8: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth); + write_texture8(xpos, ypos, width, height, page, upper_byte, lower_byte, (UINT16*)data); + } + + invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7); break; + } case 0x02: /* Only mipmaps */ + { + int x = mipmap_coords[0][0] + (xpos / mipmap_divider[0]); + int y = mipmap_coords[0][1] + (ypos / mipmap_divider[0]); + int w = width / 2; + int h = height / 2; + + int mipmap = 1; + + while (w >= 8 && h >= 8) + { + if (bitdepth) + { + write_texture16(x, y, w, h, page, (UINT16*)data); + } + else + { + //printf("write tex8: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth); + write_texture8(x, y, w, h, page, upper_byte, lower_byte, (UINT16*)data); + } + + data += (w * h * (bitdepth ? 2 : 1)) / 4; + w /= 2; + h /= 2; + + x = mipmap_coords[mipmap][0] + (xpos / mipmap_divider[mipmap]); + y = mipmap_coords[mipmap][1] + (ypos / mipmap_divider[mipmap]); + mipmap++; + } + + invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7); break; + } case 0x80: /* Gamma-table ? */ break; default: - fatalerror("Unknown texture type: %02X\n", header >> 24); + fatalerror("Unknown texture type: %02X (%08X)\n", header >> 24, header); + break; } } @@ -1022,13 +1193,6 @@ void model3_state::real3d_display_list_end() reset_triangle_buffers(); real3d_traverse_display_list(); - /* - m_renderer->draw_opaque_triangles(m_tri_buffer, m_tri_buffer_ptr); - m_renderer->draw_alpha_triangles(m_tri_alpha_buffer, m_tri_alpha_buffer_ptr); - - m_renderer->wait_for_polys(); - */ - for (int i=0; i < 4; i++) { int ticount, tiacount; @@ -1241,78 +1405,145 @@ void model3_state::translate_matrix_stack(float x, float y, float z) matrix_multiply(tm, m_matrix_stack[m_matrix_stack_ptr], &m_matrix_stack[m_matrix_stack_ptr]); } +void model3_state::set_projection(float left, float right, float top, float bottom, float near, float far) +{ + float l = near * tanf(left * 0.5f); + float r = near * tanf(right * 0.5f); + float t = near * tanf(top * 0.5f ); + float b = near * tanf(bottom * 0.5f); + + m_projection_matrix[0][0] = (2.0f * near) / (l - r); + m_projection_matrix[0][1] = 0.0f; + m_projection_matrix[0][2] = (r + l) / (r - l); + m_projection_matrix[0][3] = 0.0f; + m_projection_matrix[1][0] = 0.0f; + m_projection_matrix[1][1] = (2.0f * near) / (t - b); + m_projection_matrix[1][2] = (t + b) / (t - b); + m_projection_matrix[1][3] = 0.0f; + m_projection_matrix[2][0] = 0.0f; + m_projection_matrix[2][1] = 0.0f; + m_projection_matrix[2][2] = -(far + near) / (far - near); + m_projection_matrix[2][3] = -(2.0f * far * near) / (far - near); + m_projection_matrix[3][0] = 0.0f; + m_projection_matrix[3][1] = 0.0f; + m_projection_matrix[3][2] = -1.0f; + m_projection_matrix[3][3] = 0.0f; +} + /*****************************************************************************/ /* transformation and rasterizing */ -INLINE bool is_point_inside(float x, float y, float z, m3_plane cp) +static int clip_w(const m3_clip_vertex* v, int num_vertices, m3_clip_vertex* out) { - float s = (x * cp.x) + (y * cp.y) + (z * cp.z) + cp.d; - if (s >= 0.0f) - return true; - else - return false; -} + if (num_vertices <= 0) + return 0; -INLINE float line_plane_intersection(const m3_clip_vertex *v1, const m3_clip_vertex *v2, m3_plane cp) -{ - float x = v1->x - v2->x; - float y = v1->y - v2->y; - float z = v1->z - v2->z; - float t = ((cp.x * v1->x) + (cp.y * v1->y) + (cp.z * v1->z)) / ((cp.x * x) + (cp.y * y) + (cp.z * z)); - return t; -} + const float W_PLANE = 0.000001f; -static int clip_polygon(const m3_clip_vertex *v, int num_vertices, m3_plane cp, m3_clip_vertex *vout) -{ m3_clip_vertex clipv[10]; int clip_verts = 0; - float t; - int i; int previ = num_vertices - 1; - for (i=0; i < num_vertices; i++) + for (int i=0; i < num_vertices; i++) { - bool v1_in = is_point_inside(v[i].x, v[i].y, v[i].z, cp); - bool v2_in = is_point_inside(v[previ].x, v[previ].y, v[previ].z, cp); + int v1_side = (v[i].w < W_PLANE) ? -1 : 1; + int v2_side = (v[previ].w < W_PLANE) ? -1 : 1; - if (v1_in && v2_in) /* edge is completely inside the volume */ + if ((v1_side * v2_side) < 0) // edge goes through W plane { - clipv[clip_verts] = v[i]; + // insert vertex at intersection point + float wdiv = v[previ].w - v[i].w; + if (wdiv == 0.0f) // 0 edge means degenerate polygon + return 0; + + float t = fabs((W_PLANE - v[previ].w) / wdiv); + + clipv[clip_verts].x = v[previ].x + ((v[i].x - v[previ].x) * t); + clipv[clip_verts].y = v[previ].y + ((v[i].y - v[previ].y) * t); + clipv[clip_verts].z = v[previ].z + ((v[i].z - v[previ].z) * t); + clipv[clip_verts].w = v[previ].w + ((v[i].w - v[previ].w) * t); + clipv[clip_verts].u = v[previ].u + ((v[i].u - v[previ].u) * t); + clipv[clip_verts].v = v[previ].v + ((v[i].v - v[previ].v) * t); + clipv[clip_verts].i = v[previ].i + ((v[i].i - v[previ].i) * t); + clipv[clip_verts].s = v[previ].s + ((v[i].s - v[previ].s) * t); ++clip_verts; } - else if (!v1_in && v2_in) /* edge is entering the volume */ + if (v1_side > 0) // current point is inside { - /* insert vertex at intersection point */ - t = line_plane_intersection(&v[i], &v[previ], cp); - clipv[clip_verts].x = v[i].x + ((v[previ].x - v[i].x) * t); - clipv[clip_verts].y = v[i].y + ((v[previ].y - v[i].y) * t); - clipv[clip_verts].z = v[i].z + ((v[previ].z - v[i].z) * t); - clipv[clip_verts].u = v[i].u + ((v[previ].u - v[i].u) * t); - clipv[clip_verts].v = v[i].v + ((v[previ].v - v[i].v) * t); - clipv[clip_verts].i = v[i].i + ((v[previ].i - v[i].i) * t); - ++clip_verts; - } - else if (v1_in && !v2_in) /* edge is leaving the volume */ - { - /* insert vertex at intersection point */ - t = line_plane_intersection(&v[i], &v[previ], cp); - clipv[clip_verts].x = v[i].x + ((v[previ].x - v[i].x) * t); - clipv[clip_verts].y = v[i].y + ((v[previ].y - v[i].y) * t); - clipv[clip_verts].z = v[i].z + ((v[previ].z - v[i].z) * t); - clipv[clip_verts].u = v[i].u + ((v[previ].u - v[i].u) * t); - clipv[clip_verts].v = v[i].v + ((v[previ].v - v[i].v) * t); - clipv[clip_verts].i = v[i].i + ((v[previ].i - v[i].i) * t); - ++clip_verts; - - /* insert the existing vertex */ clipv[clip_verts] = v[i]; ++clip_verts; } previ = i; } - memcpy(&vout[0], &clipv[0], sizeof(vout[0]) * clip_verts); + + memcpy(&out[0], &clipv[0], sizeof(out[0]) * clip_verts); + return clip_verts; +} + +static int clip(const m3_clip_vertex* v, int num_vertices, m3_clip_vertex* out, int axis, int sign) +{ + if (num_vertices <= 0) + return 0; + + m3_clip_vertex clipv[10]; + int clip_verts = 0; + + int previ = num_vertices - 1; + + for (int i=0; i < num_vertices; i++) + { + int v1_side, v2_side; + float* v1a = (float*)&v[i]; + float* v2a = (float*)&v[previ]; + + float v1_axis, v2_axis; + + if (sign) // +axis + { + v1_axis = v1a[axis]; + v2_axis = v2a[axis]; + } + else // -axis + { + v1_axis = -v1a[axis]; + v2_axis = -v2a[axis]; + } + + v1_side = (v1_axis <= v[i].w) ? 1 : -1; + v2_side = (v2_axis <= v[previ].w) ? 1 : -1; + + if ((v1_side * v2_side) < 0) // edge goes through W plane + { + // insert vertex at intersection point + float wdiv = ((v[previ].w - v2_axis) - (v[i].w - v1_axis)); + + if (wdiv == 0.0f) // 0 edge means degenerate polygon + return 0; + + float t = fabs((v[previ].w - v2_axis) / wdiv); + + clipv[clip_verts].x = v[previ].x + ((v[i].x - v[previ].x) * t); + clipv[clip_verts].y = v[previ].y + ((v[i].y - v[previ].y) * t); + clipv[clip_verts].z = v[previ].z + ((v[i].z - v[previ].z) * t); + clipv[clip_verts].w = v[previ].w + ((v[i].w - v[previ].w) * t); + clipv[clip_verts].u = v[previ].u + ((v[i].u - v[previ].u) * t); + clipv[clip_verts].v = v[previ].v + ((v[i].v - v[previ].v) * t); + clipv[clip_verts].i = v[previ].i + ((v[i].i - v[previ].i) * t); + clipv[clip_verts].s = v[previ].s + ((v[i].s - v[previ].s) * t); + ++clip_verts; + } + if (v1_side > 0) // current point is inside + { + clipv[clip_verts] = v[i]; + ++clip_verts; + } + + previ = i; + } + + memcpy(&out[0], &clipv[0], sizeof(out[0]) * clip_verts); return clip_verts; } @@ -1368,7 +1599,14 @@ void model3_state::draw_model(UINT32 addr) m3_clip_vertex clip_vert[10]; MATRIX transform_matrix; - float center_x, center_y; + MATRIX vp_matrix; + MATRIX coord_matrix; + + memset(&coord_matrix, 0, sizeof(coord_matrix)); + coord_matrix[0][0] = m_coordinate_system[0][1]; + coord_matrix[1][1] = m_coordinate_system[1][2]; + coord_matrix[2][2] = -m_coordinate_system[2][0]; + coord_matrix[3][3] = 1.0f; if (m_step < 0x15) // position coordinates are 17.7 fixed-point in Step 1.0 fixed_point_fraction = 1.0f / 128.0f; @@ -1377,9 +1615,9 @@ void model3_state::draw_model(UINT32 addr) get_top_matrix(&transform_matrix); - /* current viewport center coordinates on screen */ - center_x = (float)(m_viewport_region_x + (m_viewport_region_width / 2)); - center_y = (float)(m_viewport_region_y + (m_viewport_region_height / 2)); + // make view-projection matrix + matrix_multiply(transform_matrix, coord_matrix, &transform_matrix); + matrix_multiply(transform_matrix, m_projection_matrix, &vp_matrix); memset(prev_vertex, 0, sizeof(prev_vertex)); @@ -1448,24 +1686,29 @@ void model3_state::draw_model(UINT32 addr) /* Copy current vertices as previous vertices */ memcpy(prev_vertex, vertex, sizeof(m3_vertex) * 4); - color = (header[4] >> 8) & 0xffffff; + if (header[1] & 0x2) + { + color = (header[4] >> 8) & 0xffffff; + } + else + { + int ci = (header[4] >> 8) & 0x7ff; + color = m_polygon_ram[0x400 + ci]; + } + polygon_transparency = (header[6] & 0x800000) ? 32 : ((header[6] >> 18) & 0x1f); /* transform polygon normal to view-space */ sn[0] = (normal[0] * transform_matrix[0][0]) + - (normal[1] * transform_matrix[1][0]) + - (normal[2] * transform_matrix[2][0]); - sn[1] = (normal[0] * transform_matrix[0][1]) + + (normal[1] * transform_matrix[0][1]) + + (normal[2] * transform_matrix[0][2]); + sn[1] = (normal[0] * transform_matrix[1][0]) + (normal[1] * transform_matrix[1][1]) + - (normal[2] * transform_matrix[2][1]); - sn[2] = (normal[0] * transform_matrix[0][2]) + - (normal[1] * transform_matrix[1][2]) + + (normal[2] * transform_matrix[1][2]); + sn[2] = (normal[0] * transform_matrix[2][0]) + + (normal[1] * transform_matrix[2][1]) + (normal[2] * transform_matrix[2][2]); - - sn[0] *= m_coordinate_system[0][1]; - sn[1] *= m_coordinate_system[1][2]; - sn[2] *= m_coordinate_system[2][0]; - + // TODO: depth bias // transform and light vertices for (i = 0; i < num_vertices; i++) @@ -1477,36 +1720,38 @@ void model3_state::draw_model(UINT32 addr) vect[2] = vertex[i].z; vect[3] = 1.0f; - // transform to world-space - matrix_multiply_vector(transform_matrix, vect, &p[i]); + // transform to projection space + matrix_multiply_vector(vp_matrix, vect, &p[i]); + + clip_vert[i].x = p[i][0]; + clip_vert[i].y = p[i][1]; + clip_vert[i].z = p[i][2]; + clip_vert[i].w = p[i][3]; - // apply coordinate system - clip_vert[i].x = p[i][0] * m_coordinate_system[0][1]; - clip_vert[i].y = p[i][1] * m_coordinate_system[1][2]; - clip_vert[i].z = p[i][2] * m_coordinate_system[2][0]; - clip_vert[i].u = vertex[i].u * texture_coord_scale; - clip_vert[i].v = vertex[i].v * texture_coord_scale; + clip_vert[i].u = vertex[i].u * texture_coord_scale * 256.0f; // 8 bits of subtexel accuracy for bilinear filtering + clip_vert[i].v = vertex[i].v * texture_coord_scale * 256.0f; // transform vertex normal VECTOR3 n; n[0] = (vertex[i].nx * transform_matrix[0][0]) + - (vertex[i].ny * transform_matrix[1][0]) + - (vertex[i].nz * transform_matrix[2][0]); - n[0] *= m_coordinate_system[0][1]; - n[1] = (vertex[i].nx * transform_matrix[0][1]) + + (vertex[i].ny * transform_matrix[0][1]) + + (vertex[i].nz * transform_matrix[0][2]); + n[1] = (vertex[i].nx * transform_matrix[1][0]) + (vertex[i].ny * transform_matrix[1][1]) + - (vertex[i].nz * transform_matrix[2][1]); - n[1] *= m_coordinate_system[1][2]; - n[2] = (vertex[i].nx * transform_matrix[0][2]) + - (vertex[i].ny * transform_matrix[1][2]) + + (vertex[i].nz * transform_matrix[1][2]); + n[2] = (vertex[i].nx * transform_matrix[2][0]) + + (vertex[i].ny * transform_matrix[2][1]) + (vertex[i].nz * transform_matrix[2][2]); - n[2] *= m_coordinate_system[2][0]; // lighting float intensity; if ((header[6] & 0x10000) == 0) { float dot = dot_product3(n, m_parallel_light); + + if (header[1] & 0x10) + dot = fabs(dot); + intensity = ((dot * m_parallel_light_intensity) + m_ambient_light_intensity) * 255.0f; if (intensity > 255.0f) { @@ -1519,43 +1764,55 @@ void model3_state::draw_model(UINT32 addr) } else { - // apply luminosity - intensity = ((float)((header[6] >> 11) & 0x1f) / 31.0f) * 255.0f; + intensity = 255.0f; } clip_vert[i].i = intensity; } - /* clip against view frustum */ - num_vertices = clip_polygon(clip_vert, num_vertices, m_clip_plane[0], clip_vert); - num_vertices = clip_polygon(clip_vert, num_vertices, m_clip_plane[1], clip_vert); - num_vertices = clip_polygon(clip_vert, num_vertices, m_clip_plane[2], clip_vert); - num_vertices = clip_polygon(clip_vert, num_vertices, m_clip_plane[3], clip_vert); - num_vertices = clip_polygon(clip_vert, num_vertices, m_clip_plane[4], clip_vert); + /* clip against view frustum */ + num_vertices = clip_w(clip_vert, num_vertices, clip_vert); + num_vertices = clip(clip_vert, num_vertices, clip_vert, 0, 0); // W <= -X + num_vertices = clip(clip_vert, num_vertices, clip_vert, 0, 1); // W <= +X + num_vertices = clip(clip_vert, num_vertices, clip_vert, 1, 0); // W <= -Y + num_vertices = clip(clip_vert, num_vertices, clip_vert, 1, 1); // W <= +X + num_vertices = clip(clip_vert, num_vertices, clip_vert, 2, 0); // W <= -Z + num_vertices = clip(clip_vert, num_vertices, clip_vert, 2, 1); // W <= +Z + /* divide by W, transform to screen coords */ + for(i=0; i < num_vertices; i++) + { + float oow = 1.0f / clip_vert[i].w; + + clip_vert[i].x *= oow; + clip_vert[i].y *= oow; + clip_vert[i].z *= oow; + clip_vert[i].u *= oow; + clip_vert[i].v *= oow; + + clip_vert[i].x = (((clip_vert[i].x * 0.5f) + 0.5f) * m_viewport_width) + m_viewport_x; + clip_vert[i].y = (((clip_vert[i].y * 0.5f) + 0.5f) * m_viewport_height) + m_viewport_y; + clip_vert[i].z = (((clip_vert[i].z * 0.5f) + 0.5f) * (m_viewport_far - m_viewport_near)) + m_viewport_near; + } + /* backface culling */ - if( (header[6] & 0x800000) && (!(header[1] & 0x0010)) ) { - if(sn[0]*clip_vert[0].x + sn[1]*clip_vert[0].y + sn[2]*clip_vert[0].z >0) + if( (header[6] & 0x800000) && (!(header[1] & 0x0010)) ) + { + if (sn[0]*clip_vert[0].x + sn[1]*clip_vert[0].y + sn[2]*clip_vert[0].z > 0) back_face = 1; else back_face = 0; } else + { back_face = 0; //no culling for transparent or two-sided polygons + } + + back_face = 0; if (!back_face) { - /* homogeneous Z-divide, screen-space transformation */ - for(i=0; i < num_vertices; i++) - { - float ooz = 1.0f / clip_vert[i].z; - clip_vert[i].x = ((clip_vert[i].x * ooz) * m_viewport_focal_length) + center_x; - clip_vert[i].y = ((clip_vert[i].y * ooz) * m_viewport_focal_length) + center_y; - clip_vert[i].u *= ooz; - clip_vert[i].v *= ooz; - } - - + bool colormod = false; cached_texture* texture; if (header[6] & 0x0000400) @@ -1566,6 +1823,9 @@ void model3_state::draw_model(UINT32 addr) int tex_height = (header[3] & 0x7); int tex_format = (header[6] >> 7) & 0x7; + if (tex_format != 0 && tex_format != 7) // enable color modulation if this is not a color texture + colormod = true; + if (tex_width >= 6 || tex_height >= 6) // srally2 poly ram has degenerate polys with 2k tex size (cpu bug or intended?) return; @@ -1577,8 +1837,8 @@ void model3_state::draw_model(UINT32 addr) } for (i=2; i < num_vertices; i++) - { - bool alpha = (header[6] & 0x1) || (header[6] & 0x80000000); // put to alpha buffer if there's any transparency involved + { + bool alpha = (header[6] & 0x1) || ((header[6] & 0x800000) == 0); // put to alpha buffer if there's any transparency involved m3_triangle* tri = push_triangle(alpha); // bail out if tri buffer is maxed out (happens during harley boot) @@ -1593,12 +1853,13 @@ void model3_state::draw_model(UINT32 addr) tri->transparency = polygon_transparency; tri->color = color; - tri->param = 0; - tri->param |= (header[4] & 0x40) ? TRI_PARAM_TEXTURE_PAGE : 0; - tri->param |= (header[6] & 0x00000400) ? TRI_PARAM_TEXTURE_ENABLE : 0; - tri->param |= (header[2] & 0x2) ? TRI_PARAM_TEXTURE_MIRROR_U : 0; - tri->param |= (header[2] & 0x1) ? TRI_PARAM_TEXTURE_MIRROR_V : 0; - tri->param |= (header[6] & 0x80000000) ? TRI_PARAM_ALPHA_TEST : 0; + tri->param = 0; + tri->param |= (header[4] & 0x40) ? TRI_PARAM_TEXTURE_PAGE : 0; + tri->param |= (header[6] & 0x00000400) ? TRI_PARAM_TEXTURE_ENABLE : 0; + tri->param |= (header[2] & 0x2) ? TRI_PARAM_TEXTURE_MIRROR_U : 0; + tri->param |= (header[2] & 0x1) ? TRI_PARAM_TEXTURE_MIRROR_V : 0; + tri->param |= (header[6] & 0x80000000) ? TRI_PARAM_ALPHA_TEST : 0; + tri->param |= (colormod) ? TRI_PARAM_COLOR_MOD : 0; } } } @@ -1754,8 +2015,6 @@ void model3_state::draw_viewport(int pri, UINT32 address) { const UINT32 *node = get_memory_pointer(address); UINT32 link_address; - float /*viewport_left, viewport_right, */viewport_top, viewport_bottom; - float /*fov_x,*/ fov_y; link_address = node[1]; @@ -1769,28 +2028,33 @@ void model3_state::draw_viewport(int pri, UINT32 address) return; /* set viewport parameters */ - m_viewport_region_x = (node[26] & 0xffff) >> 4; /* 12.4 fixed point */ - m_viewport_region_y = ((node[26] >> 16) & 0xffff) >> 4; - m_viewport_region_width = (node[20] & 0xffff) >> 2; /* 14.2 fixed point */ - m_viewport_region_height = ((node[20] >> 16) & 0xffff) >> 2; + m_viewport_x = (float)(node[26] & 0xffff) / 16.0f; /* 12.4 fixed point */ + m_viewport_y = (float)((node[26] >> 16) & 0xffff) / 16.0f; + m_viewport_width = (float)(node[20] & 0xffff) / 4.0f; /* 14.2 fixed point */ + m_viewport_height = (float)((node[20] >> 16) & 0xffff) / 4.0f; - /* frustum plane angles */ - //viewport_left = RADIAN_TO_DEGREE(asin(*(float *)&node[12])); - //viewport_right = RADIAN_TO_DEGREE(asin(*(float *)&node[16])); - viewport_top = RADIAN_TO_DEGREE(asin(*(float *)&node[14])); - viewport_bottom = RADIAN_TO_DEGREE(asin(*(float *)&node[18])); + m_viewport_near = 1.0f; + m_viewport_far = 100000.0f; - /* build clipping planes */ - m_clip_plane[0].x = *(float *)&node[13]; m_clip_plane[0].y = 0.0f; m_clip_plane[0].z = *(float *)&node[12]; m_clip_plane[0].d = 0.0f; - m_clip_plane[1].x = *(float *)&node[17]; m_clip_plane[1].y = 0.0f; m_clip_plane[1].z = *(float *)&node[16]; m_clip_plane[1].d = 0.0f; - m_clip_plane[2].x = 0.0f; m_clip_plane[2].y = *(float *)&node[15]; m_clip_plane[2].z = *(float *)&node[14]; m_clip_plane[2].d = 0.0f; - m_clip_plane[3].x = 0.0f; m_clip_plane[3].y = *(float *)&node[19]; m_clip_plane[3].z = *(float *)&node[18]; m_clip_plane[3].d = 0.0f; - m_clip_plane[4].x = 0.0f; m_clip_plane[4].y = 0.0f; m_clip_plane[4].z = 1.0f; m_clip_plane[4].d = 1.0f; + /* set up frustum */ + float frustum_left = atan2(*(float *)&node[12], *(float *)&node[13]); + float frustum_right = -atan2(*(float *)&node[16], -*(float *)&node[17]); + float frustum_top = atan2(*(float *)&node[14], *(float *)&node[15]); + float frustum_bottom = -atan2(*(float *)&node[18], -*(float *)&node[19]); +// float frustum_1 = atan2(*(float *)&node[9], *(float *)&node[8]); +// float frustum_2 = atan2(*(float *)&node[11], *(float *)&node[10]); + + /* + printf("%f\n", *(float *)&node[3]); + printf("0: %f, 1: %f, 2: %f, 3: %f\n", *(float *)&node[8], *(float *)&node[9], *(float *)&node[10], *(float *)&node[11]); + printf("4: %f, 5: %f, 6: %f, 7: %f\n", *(float *)&node[12], *(float *)&node[13], *(float *)&node[14], *(float *)&node[15]); + printf("8: %f, 9: %f, A: %f, B: %f\n", *(float *)&node[16], *(float *)&node[17], *(float *)&node[18], *(float *)&node[19]); + printf("fl = %f, fr = %f, ft = %f, fb = %f\n", RADIAN_TO_DEGREE(frustum_left), RADIAN_TO_DEGREE(frustum_right), RADIAN_TO_DEGREE(frustum_top), RADIAN_TO_DEGREE(frustum_bottom)); + printf("f1 = %f, f2 = %f\n", RADIAN_TO_DEGREE(frustum_1), RADIAN_TO_DEGREE(frustum_2)); + */ + + set_projection(frustum_left, frustum_right, frustum_top, frustum_bottom, m_viewport_near, m_viewport_far); - /* compute field of view */ - //fov_x = viewport_left + viewport_right; - fov_y = viewport_top + viewport_bottom; - m_viewport_focal_length = (m_viewport_region_height / 2) / tan( (fov_y * M_PI / 180.0f) / 2.0f ); m_matrix_base_address = node[22]; /* TODO: where does node[23] point to ? LOD table ? */ @@ -1798,7 +2062,7 @@ void model3_state::draw_viewport(int pri, UINT32 address) /* set lighting parameters */ m_parallel_light[0] = *(float *)&node[5]; m_parallel_light[1] = *(float *)&node[6]; - m_parallel_light[2] = -*(float *)&node[4]; + m_parallel_light[2] = *(float *)&node[4]; m_parallel_light_intensity = *(float *)&node[7]; m_ambient_light_intensity = (UINT8)(node[36] >> 8) / 256.0f; @@ -1893,10 +2157,10 @@ void model3_renderer::draw_opaque_triangles(const m3_triangle* tris, int num_tri { v[i].x = tri->v[i].x; v[i].y = tri->v[i].y; - v[i].p[0] = tri->v[i].z; - v[i].p[1] = 1.0f / tri->v[i].z; - v[i].p[2] = tri->v[i].u * 256.0f; // 8 bits of subtexel precision for bilinear filtering - v[i].p[3] = tri->v[i].v * 256.0f; + v[i].p[0] = tri->v[i].w; + v[i].p[1] = 1.0f / tri->v[i].w; + v[i].p[2] = tri->v[i].u; + v[i].p[3] = tri->v[i].v; v[i].p[4] = tri->v[i].i; } @@ -1904,8 +2168,19 @@ void model3_renderer::draw_opaque_triangles(const m3_triangle* tris, int num_tri extra.texture = tri->texture; extra.transparency = tri->transparency; extra.texture_param = tri->param; + extra.color = tri->color; - render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex), this), 5, v[0], v[1], v[2]); + if (tri->param & TRI_PARAM_ALPHA_TEST) + { + render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex_contour), this), 5, v[0], v[1], v[2]); + } + else + { + if (tri->param & TRI_PARAM_COLOR_MOD) + render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex_colormod), this), 5, v[0], v[1], v[2]); + else + render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex), this), 5, v[0], v[1], v[2]); + } } else { @@ -1913,7 +2188,7 @@ void model3_renderer::draw_opaque_triangles(const m3_triangle* tris, int num_tri { v[i].x = tri->v[i].x; v[i].y = tri->v[i].y; - v[i].p[0] = tri->v[i].z; + v[i].p[0] = tri->v[i].w; v[i].p[1] = tri->v[i].i; } @@ -1947,10 +2222,10 @@ void model3_renderer::draw_alpha_triangles(const m3_triangle* tris, int num_tris { v[i].x = tri->v[i].x; v[i].y = tri->v[i].y; - v[i].p[0] = tri->v[i].z; - v[i].p[1] = 1.0f / tri->v[i].z; - v[i].p[2] = tri->v[i].u * 256.0f; // 8 bits of subtexel precision for bilinear filtering - v[i].p[3] = tri->v[i].v * 256.0f; + v[i].p[0] = tri->v[i].w; + v[i].p[1] = 1.0f / tri->v[i].w; + v[i].p[2] = tri->v[i].u; + v[i].p[3] = tri->v[i].v; v[i].p[4] = tri->v[i].i; } @@ -1959,14 +2234,7 @@ void model3_renderer::draw_alpha_triangles(const m3_triangle* tris, int num_tris extra.transparency = tri->transparency; extra.texture_param = tri->param; - if (tri->param & TRI_PARAM_ALPHA_TEST) - { - render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex_contour), this), 5, v[0], v[1], v[2]); - } - else - { - render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex_alpha), this), 5, v[0], v[1], v[2]); - } + render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex_alpha), this), 5, v[0], v[1], v[2]); } else { @@ -1974,15 +2242,15 @@ void model3_renderer::draw_alpha_triangles(const m3_triangle* tris, int num_tris { v[i].x = tri->v[i].x; v[i].y = tri->v[i].y; - v[i].p[0] = tri->v[i].z; + v[i].p[0] = tri->v[i].w; v[i].p[1] = tri->v[i].i; } model3_polydata &extra = object_data_alloc(); extra.color = tri->color; + extra.transparency = tri->transparency; - // TODO: scanline renderer for solid /w transparency - render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_solid), this), 2, v[0], v[1], v[2]); + render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_solid_trans), this), 2, v[0], v[1], v[2]); } } } @@ -1998,36 +2266,62 @@ void model3_renderer::draw_scanline_solid(INT32 scanline, const extent_t &extent float in = extent.param[1].start; float inz = extent.param[1].dpdx; - int pr = polydata.color & 0xff0000; - int pg = polydata.color & 0xff00; - int pb = polydata.color & 0xff; - - int srctrans = polydata.transparency; - int desttrans = 32 - polydata.transparency; + rgbint color; + rgb_to_rgbint(&color, polydata.color); for (int x = extent.startx; x < extent.stopx; x++) { - if (z < zb[x]) + if (z <= zb[x]) { + rgbint c = color; int ii = (int)(in); - int r = (pr * ii) >> 8; - int g = (pg * ii) >> 8; - int b = (pb * ii) >> 8; + rgbint_scale_immediate_and_clamp(&c, ii); - if (srctrans != 0x1f) + fb[x] = 0xff000000 | rgbint_to_rgb_clamp(&c); + zb[x] = z; + } + + in += inz; + z += dz; + } +} + +void model3_renderer::draw_scanline_solid_trans(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid) +{ + UINT32 *fb = &m_fb->pix32(scanline); + float *zb = (float*)&m_zb->pix32(scanline); + + float z = extent.param[0].start; + float dz = extent.param[0].dpdx; + + float in = extent.param[1].start; + float inz = extent.param[1].dpdx; + + rgbint color; + rgb_to_rgbint(&color, polydata.color); + + int trans = (polydata.transparency << 3) | (polydata.transparency >> 2); + + for (int x = extent.startx; x < extent.stopx; x++) + { + if (z <= zb[x]) + { + rgbint c = color; + + int ii = (int)(in); + + rgbint_scale_immediate_and_clamp(&c, ii); + + if (trans != 0xff) { + rgbint fbcolor; UINT32 orig = fb[x]; - r = (r * srctrans) >> 5; - g = (g * srctrans) >> 5; - b = (b * srctrans) >> 5; - r += ((orig & 0x00ff0000) * desttrans) >> 5; - g += ((orig & 0x0000ff00) * desttrans) >> 5; - b += ((orig & 0x000000ff) * desttrans) >> 5; + rgb_to_rgbint(&fbcolor, orig); + rgbint_blend(&c, &fbcolor, trans); } - fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); - zb[x] = z; + fb[x] = 0xff000000 | rgbint_to_rgb_clamp(&c); } in += inz; @@ -2090,18 +2384,69 @@ void model3_renderer::draw_scanline_tex(INT32 scanline, const extent_t &extent, for (int x = extent.startx; x < extent.stopx; x++) { - if (z < zb[x]) + if (z <= zb[x]) { UINT32 texel; - TEX_FETCH(); + TEX_FETCH(); // TODO fetch rgbint instead - int ii = in; + rgbint color; + rgb_to_rgbint(&color, texel); - UINT32 r = ((texel & 0xff0000) * ii) >> 8; - UINT32 g = ((texel & 0xff00) * ii) >> 8; - UINT32 b = ((texel & 0xff) * ii) >> 8; + int ii = (int)(in); + rgbint_scale_immediate_and_clamp(&color, ii); - fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); + fb[x] = 0xff000000 | rgbint_to_rgb_clamp(&color); + zb[x] = z; + } + + ooz += dooz; + uoz += duoz; + voz += dvoz; + in += inz; + z += dz; + } +} + +void model3_renderer::draw_scanline_tex_colormod(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid) +{ + UINT32 *fb = &m_fb->pix32(scanline); + float *zb = (float*)&m_zb->pix32(scanline); + const cached_texture *texture = polydata.texture; + + float z = extent.param[0].start; + float dz = extent.param[0].dpdx; + float ooz = extent.param[1].start; + float dooz = extent.param[1].dpdx; + float uoz = extent.param[2].start; + float duoz = extent.param[2].dpdx; + float voz = extent.param[3].start; + float dvoz = extent.param[3].dpdx; + float in = extent.param[4].start; + float inz = extent.param[4].dpdx; + + UINT32 umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; + UINT32 vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; + UINT32 width = 6 + texture->width; + + rgbint polycolor; + rgb_to_rgbint(&polycolor, polydata.color); + + for (int x = extent.startx; x < extent.stopx; x++) + { + if (z <= zb[x]) + { + UINT32 texel; + TEX_FETCH(); // TODO fetch rgbint instead + + rgbint color; + rgb_to_rgbint(&color, texel); + + rgbint_scale_channel_and_clamp(&color, &polycolor); + + int ii = (int)(in); + rgbint_scale_immediate_and_clamp(&color, ii); + + fb[x] = 0xff000000 | rgbint_to_rgb_clamp(&color); zb[x] = z; } @@ -2134,9 +2479,12 @@ void model3_renderer::draw_scanline_tex_contour(INT32 scanline, const extent_t & UINT32 vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; UINT32 width = 6 + texture->width; + rgbint polycolor; + rgb_to_rgbint(&polycolor, polydata.color); + for (int x = extent.startx; x < extent.stopx; x++) { - if (z < zb[x]) + if (z <= zb[x]) { UINT32 texel; TEX_FETCH(); @@ -2144,19 +2492,20 @@ void model3_renderer::draw_scanline_tex_contour(INT32 scanline, const extent_t & UINT32 fa = texel >> 24; if (fa >= 0xf8) { - UINT32 r = ((texel & 0x00ff0000) * fa) >> 8; - UINT32 g = ((texel & 0x0000ff00) * fa) >> 8; - UINT32 b = ((texel & 0x000000ff) * fa) >> 8; + rgbint color; + rgb_to_rgbint(&color, texel); + + rgbint_scale_channel_and_clamp(&color, &polycolor); + int ii = (int)(in); + rgbint_scale_immediate_and_clamp(&color, ii); + + rgbint fbcolor; UINT32 orig = fb[x]; + rgb_to_rgbint(&fbcolor, orig); + rgbint_blend(&color, &fbcolor, fa); - int minalpha = 255 - fa; - - r += ((orig & 0x00ff0000) * minalpha) >> 8; - g += ((orig & 0x0000ff00) * minalpha) >> 8; - b += ((orig & 0x000000ff) * minalpha) >> 8; - - fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); + fb[x] = 0xff000000 | rgbint_to_rgb_clamp(&color); zb[x] = z; } } @@ -2186,37 +2535,37 @@ void model3_renderer::draw_scanline_tex_trans(INT32 scanline, const extent_t &ex float in = extent.param[4].start; float inz = extent.param[4].dpdx; - int srctrans = polydata.transparency; - int desttrans = 32 - polydata.transparency; + int trans = (polydata.transparency << 3) | (polydata.transparency >> 2); UINT32 umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1; UINT32 vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1; UINT32 width = 6 + texture->width; + rgbint polycolor; + rgb_to_rgbint(&polycolor, polydata.color); + for (int x = extent.startx; x < extent.stopx; x++) { - if (z < zb[x]) + if (z <= zb[x]) { UINT32 texel; TEX_FETCH(); + rgbint color; + rgb_to_rgbint(&color, texel); + + rgbint_scale_channel_and_clamp(&color, &polycolor); + int ii = (int)in; - UINT32 r = ((texel & 0x00ff0000) * ii) >> 8; - UINT32 g = ((texel & 0x0000ff00) * ii) >> 8; - UINT32 b = ((texel & 0x000000ff) * ii) >> 8; - - r = (r * srctrans) >> 5; - g = (g * srctrans) >> 5; - b = (b * srctrans) >> 5; + rgbint_scale_immediate_and_clamp(&color, ii); + rgbint fbcolor; UINT32 orig = fb[x]; + rgb_to_rgbint(&fbcolor, orig); + rgbint_blend(&color, &fbcolor, trans); - r += ((orig & 0x00ff0000) * desttrans) >> 5; - g += ((orig & 0x0000ff00) * desttrans) >> 5; - b += ((orig & 0x000000ff) * desttrans) >> 5; - - fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); + fb[x] = 0xff000000 | rgbint_to_rgb_clamp(&color); } ooz += dooz; @@ -2253,7 +2602,7 @@ void model3_renderer::draw_scanline_tex_alpha(INT32 scanline, const extent_t &ex for (int x = extent.startx; x < extent.stopx; x++) { - if (z < zb[x]) + if (z <= zb[x]) { UINT32 texel; TEX_FETCH(); @@ -2261,24 +2610,19 @@ void model3_renderer::draw_scanline_tex_alpha(INT32 scanline, const extent_t &ex UINT32 fa = texel >> 24; if (fa != 0) { + rgbint color; + rgb_to_rgbint(&color, texel); + int ii = (int)in; - UINT32 r = ((texel & 0x00ff0000) * ii) >> 8; - UINT32 g = ((texel & 0x0000ff00) * ii) >> 8; - UINT32 b = ((texel & 0x000000ff) * ii) >> 8; - - r = (r * fa) >> 8; - g = (g * fa) >> 8; - b = (b * fa) >> 8; + rgbint_scale_immediate_and_clamp(&color, ii); + rgbint fbcolor; UINT32 orig = fb[x]; + rgb_to_rgbint(&fbcolor, orig); + rgbint_blend(&color, &fbcolor, fa); - int minalpha = 255 - fa; - r += ((orig & 0x00ff0000) * minalpha) >> 8; - g += ((orig & 0x0000ff00) * minalpha) >> 8; - b += ((orig & 0x000000ff) * minalpha) >> 8; - - fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff); + fb[x] = 0xff000000 | rgbint_to_rgb_clamp(&color); } }