summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Ville Linde <villedevs@gmail.com>2015-06-14 03:24:28 +0300
committer Ville Linde <villedevs@gmail.com>2015-06-14 18:00:48 +0300
commit36f146e5dc18d3ac79727153d1b719a0757f3542 (patch)
tree844b07f345d83669adb2006f4e64a6a4566cef8e /src
parent08081a30313cb8d37d533731ce9dec868273d2f2 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/mame/drivers/model3.c106
-rw-r--r--src/mame/includes/model3.h30
-rw-r--r--src/mame/video/model3.c976
3 files changed, 738 insertions, 374 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<model3_state>();
/* set conservative DRC options */
- machine.device<ppc_device>("maincpu")->ppcdrc_set_options(PPCDRC_COMPATIBLE_OPTIONS - PPCDRC_ACCURATE_SINGLES);
+ machine.device<ppc_device>("maincpu")->ppcdrc_set_options(PPCDRC_COMPATIBLE_OPTIONS);
/* configure fast RAM regions for DRC */
machine.device<ppc_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);
+ clipv[clip_verts] = v[i];
++clip_verts;
}
- else if (v1_in && !v2_in) /* edge is leaving the volume */
+
+ previ = i;
+ }
+
+ 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
{
- /* 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;
+ 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;
- /* insert the existing vertex */
+ 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(&vout[0], &clipv[0], sizeof(vout[0]) * clip_verts);
+
+ 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;
-
- /* 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]));
-
- /* 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;
-
- /* 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_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;
+
+ m_viewport_near = 1.0f;
+ m_viewport_far = 100000.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);
+
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;
+ rgbint color;
+ rgb_to_rgbint(&color, polydata.color);
+
+ 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);
+
+ 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 srctrans = polydata.transparency;
- int desttrans = 32 - polydata.transparency;
+ int trans = (polydata.transparency << 3) | (polydata.transparency >> 2);
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)
+ 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);
- UINT32 orig = fb[x];
-
- int minalpha = 255 - fa;
+ int ii = (int)(in);
+ rgbint_scale_immediate_and_clamp(&color, ii);
- r += ((orig & 0x00ff0000) * minalpha) >> 8;
- g += ((orig & 0x0000ff00) * minalpha) >> 8;
- b += ((orig & 0x000000ff) * minalpha) >> 8;
+ rgbint fbcolor;
+ UINT32 orig = fb[x];
+ rgb_to_rgbint(&fbcolor, orig);
+ rgbint_blend(&color, &fbcolor, fa);
- 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();
- int ii = (int)in;
+ rgbint color;
+ rgb_to_rgbint(&color, texel);
+
+ rgbint_scale_channel_and_clamp(&color, &polycolor);
- UINT32 r = ((texel & 0x00ff0000) * ii) >> 8;
- UINT32 g = ((texel & 0x0000ff00) * ii) >> 8;
- UINT32 b = ((texel & 0x000000ff) * ii) >> 8;
+ int ii = (int)in;
- 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)
{
- int ii = (int)in;
+ rgbint color;
+ rgb_to_rgbint(&color, texel);
- UINT32 r = ((texel & 0x00ff0000) * ii) >> 8;
- UINT32 g = ((texel & 0x0000ff00) * ii) >> 8;
- UINT32 b = ((texel & 0x000000ff) * ii) >> 8;
+ int ii = (int)in;
- 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);
}
}