summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitattributes1
-rw-r--r--src/mame/drivers/model3.c173
-rw-r--r--src/mame/includes/model3.h103
-rw-r--r--src/mame/machine/model3.c125
-rw-r--r--src/mame/mame.mak1
-rw-r--r--src/mame/video/m3raster.inc286
-rw-r--r--src/mame/video/model3.c1111
7 files changed, 1072 insertions, 728 deletions
diff --git a/.gitattributes b/.gitattributes
index c6e588d4dee..1b2384f8062 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7597,7 +7597,6 @@ src/mame/video/lvcards.c svneol=native#text/plain
src/mame/video/lwings.c svneol=native#text/plain
src/mame/video/m10.c svneol=native#text/plain
src/mame/video/m107.c svneol=native#text/plain
-src/mame/video/m3raster.inc svneol=native#text/plain
src/mame/video/m52.c svneol=native#text/plain
src/mame/video/m57.c svneol=native#text/plain
src/mame/video/m58.c svneol=native#text/plain
diff --git a/src/mame/drivers/model3.c b/src/mame/drivers/model3.c
index 5a66ad1cae1..c0e838e7f69 100644
--- a/src/mame/drivers/model3.c
+++ b/src/mame/drivers/model3.c
@@ -13,34 +13,36 @@
Step 2.1: 166 MHz PPC, same 3D engine as 2.0, differences unknown
Game status:
- vf3/vf3a/vf3tb - don't boot - stuck in poly_wait()
- bass - boots and runs with 3D
+ vf3/vf3a/vf3tb - crashes
+ bass - works
getbass - I/O board error (?)
- scud/scuda - boots and runs with 3D (scuda says "for sale and use only in Japan" but is marked Export?)
- scudj - boots but hangs up (no SCSI IRQs)
- scudp - shows initial screen, apparently won't go into test mode or advance
- lostwsga - SCSI IRQ stuck on (boots and runs with 3D if hacked)
- vs215 - boots and runs with 3D
- lemans24 - SCSI IRQ stuck on (boots if hacked)
- vs29815 - write to unknown 53c810 SCSI register
-
- vs2 - looks like it should boot but never displays anything
- harley - boots and runs with 3D after a "NO DAUGHTER BOARD DETECTED" error
- skichamp - "NO DAUGHTER BOARD DETECTED", doesn't advance (no SCSI IRQs occur)
- srally2/sraly2dx - doesn't boot (no SCSI IRQs occur, other IRQs look fine)
- von2/von254g - SCSI IRQ stuck on (boots and runs if SCSI ack is hacked)
- fvipers2 - says "ONE PROCESSOR DETECTED" and hangs (no SCSI IRQs occur, others look fine)
- vs298/vs299/vs2v991 - hangs (no SCSI IRQs occur, others look fine)
+ scud/scuda - works (scuda says "for sale and use only in Japan" but is marked Export?)
+ scudj - works
+ scudplus - works
+ lostwsga - works
+ vs215 - works
+ lemans24 - works
+ vs29815 - massive memory trashing and page faults
+
+ vs2 - waiting for decrementer (same code as eca)
+ harley -
+ skichamp - waiting for decrementer
+ srally2/sraly2dx - works
+ von2/von254g - works
+ fvipers2 - waiting for decrementer (same code as eca)
+ vs298/vs299/vs2v991 - waiting for decrementer
+ oceanhun - same as daytona2
+ lamachin - works
dayto2pe - bug in DRC MMU page-fault handling, causes infinite loop at PC:0x2270 (or debug assert)
daytona2 - As above.
spikeout/spikeofe - As above.
- dirtdvls/dirtdvla - SCSI IRQ stuck on (boots partially if hacked)
- swtrilgy - doesn't boot (no SCSI IRQs occur, other IRQs look fine)
- swtrilga - SCSI IRQ stuck on
- magtruck - SCSI IRQ stuck on (boots and fails country code check (!) if hacked)
- eca/ecax - doesn't boot (a few SCSI IRQs occur but then cease, other IRQs look fine)
+ dirtdvls/dirtdvla - works
+ swtrilgy -
+ swtrilga -
+ magtruck - works
+ eca/ecax - waiting for decrementer
===================================================================================
@@ -1242,10 +1244,9 @@ void model3_state::model3_init(int step)
m_m3_step = step; // step = BCD hardware rev. 0x10 for 1.0, 0x15 for 1.5, 0x20 for 2.0, etc.
tap_reset();
- if (step < 0x20) {
- if( core_stricmp(machine().system().name, "vs215") == 0 ||
- core_stricmp(machine().system().name, "vs29815") == 0 ||
- core_stricmp(machine().system().name, "bass") == 0 )
+ if (step < 0x20)
+ {
+ if (m_step15_with_mpc106)
{
mpc106_init(machine());
}
@@ -1255,12 +1256,12 @@ void model3_state::model3_init(int step)
}
m_real3d_device_id = 0x16c311db; /* PCI Vendor ID (11db = SEGA), Device ID (16c3 = 315-5827) */
}
- else {
+ else
+ {
mpc106_init(machine());
// some step 2+ games need the older PCI ID (obvious symptom:
// vbl is enabled briefly then disabled so the game hangs)
- if (core_stricmp(machine().system().name, "magtruck") == 0 ||
- core_stricmp(machine().system().name, "von254g") == 0)
+ if (m_step20_with_old_real3d)
{
m_real3d_device_id = 0x16c311db; /* PCI Vendor ID (11db = SEGA), Device ID (16c3 = 315-5827) */
}
@@ -5646,84 +5647,51 @@ DRIVER_INIT_MEMBER(model3_state,lostwsga)
DRIVER_INIT_MEMBER(model3_state,scud)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
-
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));
-
- rom[(0x71275c^4)/4] = 0x60000000;
- rom[(0x71277c^4)/4] = 0x60000000;
}
DRIVER_INIT_MEMBER(model3_state,scudplus)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
-
DRIVER_INIT_CALL(model3_15);
/* TODO: network device at 0xC0000000 - FF */
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xc1000000, 0xc10000ff, read64_delegate(FUNC(model3_state::scsi_r),this), write64_delegate(FUNC(model3_state::scsi_w),this));
-
- rom[(0x713724^4)/4] = 0x60000000;
- rom[(0x713744^4)/4] = 0x60000000;
-
- rom[(0x741f48^4)/4] = 0x60000000;
-
- rom[(0x741f68^4)/4] = 0x60000000;
- rom[(0x741efc^4)/4] = 0x60000000;
}
DRIVER_INIT_MEMBER(model3_state,scudplusa)
{
- //UINT32 *rom = (UINT32*)memregion("user1")->base();
-
DRIVER_INIT_CALL(model3_15);
/* TODO: network device at 0xC0000000 - FF */
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xc1000000, 0xc10000ff, read64_delegate(FUNC(model3_state::scsi_r),this), write64_delegate(FUNC(model3_state::scsi_w),this));
-
- //rom[(0x713724^4)/4] = 0x60000000; // Fix ME!!!! Needs to corrected for the non REV A version!!!!
- //rom[(0x713744^4)/4] = 0x60000000;
-
- //rom[(0x741f48^4)/4] = 0x60000000;
-
- //rom[(0x741f68^4)/4] = 0x60000000;
- //rom[(0x741efc^4)/4] = 0x60000000;
}
DRIVER_INIT_MEMBER(model3_state,lemans24)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
DRIVER_INIT_CALL(model3_15);
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xc1000000, 0xc10000ff, read64_delegate(FUNC(model3_state::scsi_r),this), write64_delegate(FUNC(model3_state::scsi_w),this));
-
- rom[(0x73fe38^4)/4] = 0x38840004; /* This seems to be an actual bug in the original code */
-
- rom[(0x73eb5c^4)/4] = 0x60000000;
- rom[(0x73edd0^4)/4] = 0x60000000;
- rom[(0x73edc4^4)/4] = 0x60000000;
+
+// rom[(0x73fe38^4)/4] = 0x38840004; /* This seems to be an actual bug in the original code */
}
DRIVER_INIT_MEMBER(model3_state,vf3)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+ //UINT32 *rom = (UINT32*)memregion("user1")->base();
DRIVER_INIT_CALL(model3_10);
+ /*
rom[(0x713c7c^4)/4] = 0x60000000;
rom[(0x713e54^4)/4] = 0x60000000;
rom[(0x7125b0^4)/4] = 0x60000000;
rom[(0x7125d0^4)/4] = 0x60000000;
-
+ */
}
DRIVER_INIT_MEMBER(model3_state,vs215)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
-
- rom[(0x70dde0^4)/4] = 0x60000000;
- rom[(0x70e6f0^4)/4] = 0x60000000;
- rom[(0x70e710^4)/4] = 0x60000000;
+ m_step15_with_mpc106 = true;
interleave_vroms(machine());
m_maincpu->space(AS_PROGRAM).install_read_bank(0xff000000, 0xff7fffff, "bank1" );
@@ -5739,6 +5707,8 @@ DRIVER_INIT_MEMBER(model3_state,vs215)
DRIVER_INIT_MEMBER(model3_state,vs29815)
{
+ m_step15_with_mpc106 = true;
+
UINT32 *rom = (UINT32*)memregion("user1")->base();
rom[(0x6028ec^4)/4] = 0x60000000;
@@ -5758,10 +5728,7 @@ DRIVER_INIT_MEMBER(model3_state,vs29815)
DRIVER_INIT_MEMBER(model3_state,bass)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
-
- rom[(0x7999a8^4)/4] = 0x60000000;
- rom[(0x7999c8^4)/4] = 0x60000000;
+ m_step15_with_mpc106 = true;
interleave_vroms(machine());
m_maincpu->space(AS_PROGRAM).install_read_bank(0xff000000, 0xff7fffff, "bank1" );
@@ -5865,72 +5832,70 @@ DRIVER_INIT_MEMBER(model3_state,harley)
DRIVER_INIT_MEMBER(model3_state,harleya)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+ //UINT32 *rom = (UINT32*)memregion("user1")->base();
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));
+ /*
rom[(0x50e8d4^4)/4] = 0x60000000;
rom[(0x50e8f4^4)/4] = 0x60000000;
rom[(0x50fb84^4)/4] = 0x60000000;
rom[(0x4f736c^4)/4] = 0x60000000;
rom[(0x4f738c^4)/4] = 0x60000000;
+ */
}
DRIVER_INIT_MEMBER(model3_state,srally2)
-{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+{
DRIVER_INIT_CALL(model3_20);
+
+ UINT32 *rom = (UINT32*)memregion("user1")->base();
rom[(0x7c0c4^4)/4] = 0x60000000;
rom[(0x7c0c8^4)/4] = 0x60000000;
rom[(0x7c0cc^4)/4] = 0x60000000;
+ // Writes command 000023FFFFFFFFFE to JTAG, expects result 0x0040000000 (41 bits)
+ // Writes command 000003FFFFFFFFFE
+ // Writes command 00003FFFFFFFFFFE 248 times
+ // Writes command 000023FFFFFFFFFE, expects result 0x01000000000 (?? bits)
}
DRIVER_INIT_MEMBER(model3_state,swtrilgy)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+ //UINT32 *rom = (UINT32*)memregion("user1")->base();
DRIVER_INIT_CALL(model3_20);
+ /*
rom[(0xf0e48^4)/4] = 0x60000000;
rom[(0x043dc^4)/4] = 0x48000090;
rom[(0x029a0^4)/4] = 0x60000000;
rom[(0x02a0c^4)/4] = 0x60000000;
+ */
}
DRIVER_INIT_MEMBER(model3_state,swtrilga)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+ //UINT32 *rom = (UINT32*)memregion("user1")->base();
DRIVER_INIT_CALL(model3_20);
- rom[(0xf6dd0^4)/4] = 0x60000000;
+ //rom[(0xf6dd0^4)/4] = 0x60000000;
}
DRIVER_INIT_MEMBER(model3_state,von2)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+ m_step20_with_old_real3d = true;
+
DRIVER_INIT_CALL(model3_20);
-
- rom[(0x189168^4)/4] = 0x60000000;
- rom[(0x1890ac^4)/4] = 0x60000000;
- rom[(0x1890b8^4)/4] = 0x60000000;
- rom[(0x1888a8^4)/4] = 0x60000000;
- rom[(0x1891c8^4)/4] = 0x60000000;
}
DRIVER_INIT_MEMBER(model3_state,dirtdvls)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
- DRIVER_INIT_CALL(model3_20);
+ m_step20_with_old_real3d = true;
- rom[(0x0600a0^4)/4] = 0x60000000;
- rom[(0x0608a4^4)/4] = 0x60000000;
- rom[(0x0608b0^4)/4] = 0x60000000;
- rom[(0x060960^4)/4] = 0x60000000;
- rom[(0x0609c0^4)/4] = 0x60000000;
- rom[(0x001e24^4)/4] = 0x60000000;
+ DRIVER_INIT_CALL(model3_20);
}
DRIVER_INIT_MEMBER(model3_state,daytona2)
@@ -5982,23 +5947,26 @@ DRIVER_INIT_MEMBER(model3_state,spikeofe)
DRIVER_INIT_MEMBER(model3_state,eca)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+// UINT32 *rom = (UINT32*)memregion("user1")->base();
DRIVER_INIT_CALL(model3_20);
-
+ /*
rom[(0x535560^4)/4] = 0x60000000;
rom[(0x535580^4)/4] = 0x60000000;
+ */
}
DRIVER_INIT_MEMBER(model3_state,skichamp)
{
- UINT32 *rom = (UINT32*)memregion("user1")->base();
+ //UINT32 *rom = (UINT32*)memregion("user1")->base();
DRIVER_INIT_CALL(model3_20);
+ /*
rom[(0x5263c8^4)/4] = 0x60000000;
rom[(0x5263e8^4)/4] = 0x60000000;
rom[(0x516bbc^4)/4] = 0x60000000;
rom[(0x516b9c^4)/4] = 0x60000000; // decrementer
+ */
}
DRIVER_INIT_MEMBER(model3_state,oceanhun)
@@ -6011,6 +5979,15 @@ DRIVER_INIT_MEMBER(model3_state,oceanhun)
DRIVER_INIT_MEMBER(model3_state,magtruck)
{
+ m_step20_with_old_real3d = true;
+
+ DRIVER_INIT_CALL(model3_20);
+}
+
+DRIVER_INIT_MEMBER(model3_state,lamachin)
+{
+ m_step20_with_old_real3d = true;
+
DRIVER_INIT_CALL(model3_20);
}
@@ -6039,13 +6016,13 @@ GAME( 1998, vs29815, vs298, model3_15, model3, model3_state, vs29815, ROT0
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, 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, model3, model3_state, model3_20, ROT0, "Sega", "L.A. Machineguns", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
+GAME( 1998, lamachin, 0, model3_20, model3, model3_state, lamachin, ROT0, "Sega", "L.A. Machineguns", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, oceanhun, 0, model3_20, 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", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, srally2, 0, model3_20, scud, model3_state, srally2, ROT0, "Sega", "Sega Rally 2", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, srally2x, 0, model3_20, scud, model3_state, srally2, ROT0, "Sega", "Sega Rally 2 DX", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, von2, 0, model3_20, model3, model3_state, von2, ROT0, "Sega", "Virtual On 2: Oratorio Tangram (Revision B)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
-GAME( 1998, von254g, von2, model3_20, model3, model3_state, model3_20, ROT0, "Sega", "Virtual On 2: Oratorio Tangram (ver 5.4g)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
+GAME( 1998, von254g, von2, model3_20, model3, model3_state, von2, ROT0, "Sega", "Virtual On 2: Oratorio Tangram (ver 5.4g)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, fvipers2, 0, model3_20, model3, model3_state, model3_20, ROT0, "Sega", "Fighting Vipers 2 (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, vs298, 0, model3_20, model3, model3_state, vs298, ROT0, "Sega", "Virtua Striker 2 '98 (Step 2.0)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1999, vs2v991, 0, model3_20, model3, model3_state, vs2v991, ROT0, "Sega", "Virtua Striker 2 '99.1 (Revision B)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
diff --git a/src/mame/includes/model3.h b/src/mame/includes/model3.h
index 3eecdda208d..39722e92eba 100644
--- a/src/mame/includes/model3.h
+++ b/src/mame/includes/model3.h
@@ -1,4 +1,4 @@
-#include "video/polylgcy.h"
+#include "video/poly.h"
#include "bus/scsi/scsi.h"
#include "machine/53c810.h"
#include "audio/dsbz80.h"
@@ -9,11 +9,58 @@ typedef float MATRIX[4][4];
typedef float VECTOR[4];
typedef float VECTOR3[3];
-struct PLANE {
- float x,y,z,d;
+struct cached_texture
+{
+ cached_texture *next;
+ UINT8 width;
+ UINT8 height;
+ UINT8 format;
+ UINT8 alpha;
+ rgb_t data[1];
+};
+
+struct m3_plane
+{
+ float x;
+ float y;
+ float z;
+ float d;
+};
+
+struct m3_vertex
+{
+ float x;
+ float y;
+ float z;
+ float u;
+ float v;
+ float nx;
+ float ny;
+ float nz;
+};
+
+struct m3_clip_vertex
+{
+ float x;
+ float y;
+ float z;
+ float u;
+ float v;
+ float i;
+};
+
+struct m3_triangle
+{
+ m3_clip_vertex v[3];
+
+ cached_texture *texture;
+ int param;
+ int transparency;
+ int intensity;
+ int color;
};
-struct cached_texture;
+class model3_renderer;
class model3_state : public driver_device
{
@@ -31,18 +78,11 @@ public:
m_dsbz80(*this, DSBZ80_TAG),
m_soundram(*this, "soundram"),
m_gfxdecode(*this, "gfxdecode"),
- m_palette(*this, "palette") { }
-
- struct TRIANGLE
+ m_palette(*this, "palette")
{
- poly_vertex v[3];
- UINT8 texture_x, texture_y;
- UINT8 texture_width, texture_height;
- UINT8 transparency;
- UINT8 texture_format, param;
- int intensity;
- UINT32 color;
- };
+ m_step15_with_mpc106 = false;
+ m_step20_with_old_real3d = false;
+ }
required_device<cpu_device> m_maincpu;
optional_device<lsi53c810_device> m_lsi53c810;
@@ -54,7 +94,7 @@ public:
required_shared_ptr<UINT64> m_work_ram;
required_shared_ptr<UINT64> m_paletteram64;
optional_device<dsbz80_device> m_dsbz80; // Z80-based MPEG Digital Sound Board
- required_shared_ptr<UINT16> m_soundram;
+ required_shared_ptr<UINT16> m_soundram;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
@@ -69,13 +109,15 @@ public:
UINT8 m_scsi_irq_state;
int m_crom_bank;
int m_controls_bank;
+ bool m_step15_with_mpc106;
+ bool m_step20_with_old_real3d;
UINT32 m_real3d_device_id;
- UINT32 m_mpc105_regs[0x40];
- UINT32 m_mpc105_addr;
int m_pci_bus;
int m_pci_device;
int m_pci_function;
int m_pci_reg;
+ UINT32 m_mpc105_regs[0x40];
+ UINT32 m_mpc105_addr;
UINT32 m_mpc106_regs[0x40];
UINT32 m_mpc106_addr;
UINT32 m_dma_data;
@@ -117,19 +159,14 @@ public:
UINT32 *m_culling_ram;
UINT32 *m_polygon_ram;
int m_real3d_display_list;
- bitmap_rgb32 m_bitmap3d;
- bitmap_ind32 m_zbuffer;
rectangle m_clip3d;
rectangle *m_screen_clip;
VECTOR3 m_parallel_light;
float m_parallel_light_intensity;
float m_ambient_light_intensity;
- legacy_poly_manager *m_poly;
- int m_list_depth;
- int m_tick;
- int m_debug_layer_disable;
UINT64 m_vid_reg0;
int m_matrix_stack_ptr;
+ int m_list_depth;
MATRIX *m_matrix_stack;
MATRIX m_coordinate_system;
float m_viewport_focal_length;
@@ -137,10 +174,12 @@ public:
int m_viewport_region_y;
int m_viewport_region_width;
int m_viewport_region_height;
- PLANE m_clip_plane[5];
+ m3_plane m_clip_plane[5];
UINT32 m_matrix_base_address;
cached_texture *m_texcache[2][1024/32][2048/32];
+ model3_renderer *m_renderer;
+
DECLARE_READ32_MEMBER(rtc72421_r);
DECLARE_WRITE32_MEMBER(rtc72421_w);
DECLARE_READ64_MEMBER(model3_char_r);
@@ -219,8 +258,8 @@ public:
DECLARE_DRIVER_INIT(dayto2pe);
DECLARE_DRIVER_INIT(spikeout);
DECLARE_DRIVER_INIT(magtruck);
- DECLARE_DRIVER_INIT(model3_15);
- virtual void video_start();
+ DECLARE_DRIVER_INIT(lamachin);
+ DECLARE_DRIVER_INIT(model3_15);
DECLARE_MACHINE_START(model3_10);
DECLARE_MACHINE_RESET(model3_10);
DECLARE_MACHINE_START(model3_15);
@@ -229,7 +268,6 @@ public:
DECLARE_MACHINE_RESET(model3_20);
DECLARE_MACHINE_START(model3_21);
DECLARE_MACHINE_RESET(model3_21);
- UINT32 screen_update_model3(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
TIMER_CALLBACK_MEMBER(model3_sound_timer_tick);
TIMER_DEVICE_CALLBACK_MEMBER(model3_interrupt);
void model3_exit();
@@ -241,6 +279,8 @@ public:
void set_irq_line(UINT8 bit, int line);
void model3_init(int step);
// video
+ virtual void video_start();
+ UINT32 screen_update_model3(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
TILE_GET_INFO_MEMBER(tile_info_layer0_4bit);
TILE_GET_INFO_MEMBER(tile_info_layer1_4bit);
TILE_GET_INFO_MEMBER(tile_info_layer2_4bit);
@@ -262,7 +302,6 @@ public:
void pop_matrix_stack();
void multiply_matrix_stack(MATRIX matrix);
void translate_matrix_stack(float x, float y, float z);
- void render_one(TRIANGLE *tri);
void draw_model(UINT32 addr);
UINT32 *get_memory_pointer(UINT32 address);
void load_matrix(int matrix_num, MATRIX *out);
@@ -272,11 +311,6 @@ public:
void draw_block(UINT32 address);
void draw_viewport(int pri, UINT32 address);
void real3d_traverse_display_list();
-#ifdef UNUSED_FUNCTION
- inline void write_texture8(int xpos, int ypos, int width, int height, int page, UINT16 *data);
- void draw_texture_sheet(bitmap_ind16 &bitmap, const rectangle &cliprect);
- void copy_screen(bitmap_ind16 &bitmap, const rectangle &cliprect);
-#endif
void real3d_display_list_end();
void real3d_display_list1_dma(UINT32 src, UINT32 dst, int length, int byteswap);
void real3d_display_list2_dma(UINT32 src, UINT32 dst, int length, int byteswap);
@@ -288,4 +322,5 @@ public:
int tap_read();
void tap_write(int tck, int tms, int tdi, int trst);
void tap_reset();
+ void tap_set_asic_ids();
};
diff --git a/src/mame/machine/model3.c b/src/mame/machine/model3.c
index 6d28e7e0e6b..d679424c561 100644
--- a/src/mame/machine/model3.c
+++ b/src/mame/machine/model3.c
@@ -148,57 +148,27 @@ void model3_state::tap_write(int tck, int tms, int tdi, int trst)
switch (m_tap_state)
{
case 3: // Capture-DR
+ //printf("capture dr (IR = %08X%08X\n", (UINT32)(m_ir >> 32),(UINT32)(m_ir));
- /*
- * Read ASIC IDs.
- *
- * The ID Sequence is:
- * - Jupiter
- * - Mercury
- * - Venus
- * - Earth
- * - Mars
- * - Mars (again)
- *
- * Note that different Model 3 steps have different chip
- * revisions, hence the different IDs returned below.
- *
- * On Step 1.5 and 1.0, instruction 0x0C631F8C7FFE is used to retrieve
- * the ID codes but Step 2.0 is a little weirder. It seems to use this
- * and either the state of the TAP after reset or other instructions
- * to read the IDs as well. This can be emulated in one of 2 ways:
- * Ignore the instruction and always load up the data or load the
- * data on TAP reset and when the instruction is issued.
- */
-
- if (m_m3_step == 0x10)
+ if (m_ir == U64(0x000023fffffffffe))
{
- insert_id(0x116C7057, 1 + 0 * 32);
- insert_id(0x216C3057, 1 + 1 * 32);
- insert_id(0x116C4057, 1 + 2 * 32);
- insert_id(0x216C5057, 1 + 3 * 32);
- insert_id(0x116C6057, 1 + 4 * 32 + 1);
- insert_id(0x116C6057, 1 + 5 * 32 + 1);
- }
- else if (m_m3_step == 0x15)
- {
- insert_id(0x316C7057, 1 + 0 * 32);
- insert_id(0x316C3057, 1 + 1 * 32);
- insert_id(0x216C4057, 1 + 2 * 32); // Lost World may to use 0x016C4057
- insert_id(0x316C5057, 1 + 3 * 32);
- insert_id(0x216C6057, 1 + 4 * 32 + 1);
- insert_id(0x216C6057, 1 + 5 * 32 + 1);
+ for (int i=0; i < 32; i++)
+ {
+ m_id_data[i] = 0;
+ }
+
+ m_id_size = 41;
+
+ UINT64 res = 0x0040000000;
+
+ int start_bit = 0;
+ for (int i = 41; i >= 0; i--)
+ insert_bit(m_id_data, start_bit++, ((UINT64)(1 << i) & res) ? 1 : 0);
}
- else if (m_m3_step >= 0x20)
+ else if (m_ir == U64(0x00000c631f8c7ffe))
{
- insert_id(0x416C7057, 1 + 0 * 32);
- insert_id(0x416C3057, 1 + 1 * 32);
- insert_id(0x316C4057, 1 + 2 * 32);
- insert_id(0x416C5057, 1 + 3 * 32);
- insert_id(0x316C6057, 1 + 4 * 32 + 1);
- insert_id(0x316C6057, 1 + 5 * 32 + 1);
+ tap_set_asic_ids();
}
-
break;
case 4: // Shift-DR
@@ -241,6 +211,66 @@ void model3_state::tap_write(int tck, int tms, int tdi, int trst)
}
}
+void model3_state::tap_set_asic_ids()
+{
+ /*
+ * Read ASIC IDs.
+ *
+ * The ID Sequence is:
+ * - Jupiter
+ * - Mercury
+ * - Venus
+ * - Earth
+ * - Mars
+ * - Mars (again)
+ *
+ * Note that different Model 3 steps have different chip
+ * revisions, hence the different IDs returned below.
+ *
+ * On Step 1.5 and 1.0, instruction 0x0C631F8C7FFE is used to retrieve
+ * the ID codes but Step 2.0 is a little weirder. It seems to use this
+ * and either the state of the TAP after reset or other instructions
+ * to read the IDs as well. This can be emulated in one of 2 ways:
+ * Ignore the instruction and always load up the data or load the
+ * data on TAP reset and when the instruction is issued.
+ */
+
+ for (int i=0; i < 32; i++)
+ {
+ m_id_data[i] = 0;
+ }
+
+ if (m_m3_step == 0x10)
+ {
+ insert_id(0x116C7057, 1 + 0 * 32);
+ insert_id(0x216C3057, 1 + 1 * 32);
+ insert_id(0x116C4057, 1 + 2 * 32);
+ insert_id(0x216C5057, 1 + 3 * 32);
+ insert_id(0x116C6057, 1 + 4 * 32 + 1);
+ insert_id(0x116C6057, 1 + 5 * 32 + 1);
+ }
+ else if (m_m3_step == 0x15)
+ {
+ insert_id(0x316C7057, 1 + 0 * 32);
+ insert_id(0x316C3057, 1 + 1 * 32);
+ insert_id(0x216C4057, 1 + 2 * 32); // Lost World may to use 0x016C4057
+ insert_id(0x316C5057, 1 + 3 * 32);
+ insert_id(0x216C6057, 1 + 4 * 32 + 1);
+ insert_id(0x216C6057, 1 + 5 * 32 + 1);
+ }
+ else if (m_m3_step >= 0x20)
+ {
+ insert_id(0x416C7057, 1 + 0 * 32);
+ insert_id(0x416C3057, 1 + 1 * 32);
+ insert_id(0x316C4057, 1 + 2 * 32);
+ insert_id(0x416C5057, 1 + 3 * 32);
+ insert_id(0x316C6057, 1 + 4 * 32 + 1);
+ insert_id(0x316C6057, 1 + 5 * 32 + 1);
+ }
+
+ m_id_size = 197; // 197 bits
+}
+
/*
* void tap_reset(void);
@@ -250,8 +280,9 @@ void model3_state::tap_write(int tck, int tms, int tdi, int trst)
void model3_state::tap_reset()
{
- m_id_size = 197; // 197 bits
m_tap_state = 0; // test-logic/reset
+
+ tap_set_asic_ids();
}
/*****************************************************************************/
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index a36792813bb..6eb7abe5f91 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -2943,7 +2943,6 @@ $(DRIVERS)/model1.o: $(MAMESRC)/includes/model1.h $(MAMESRC)/audio/dsbz80.h
$(VIDEO)/model1.o: $(MAMESRC)/includes/model1.h $(MAMESRC)/audio/dsbz80.h
$(MACHINE)/model1.o: $(MAMESRC)/includes/model1.h $(MAMESRC)/audio/dsbz80.h
$(VIDEO)/model2.o: $(MAMESRC)/video/model2rd.inc
-$(VIDEO)/model3.o: $(MAMESRC)/video/m3raster.inc
$(VIDEO)/n64.o: $(MAMESRC)/video/rdpfiltr.inc
$(DRIVERS)/bfm_sc4.o: $(MAMESRC)/includes/bfm_sc45.h
$(DRIVERS)/bfm_sc5.o: $(MAMESRC)/includes/bfm_sc45.h
diff --git a/src/mame/video/m3raster.inc b/src/mame/video/m3raster.inc
deleted file mode 100644
index 7c5f49612bf..00000000000
--- a/src/mame/video/m3raster.inc
+++ /dev/null
@@ -1,286 +0,0 @@
-static void draw_scanline_normal(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
-{
- const poly_extra_data *extra = (const poly_extra_data *)extradata;
- const cached_texture *texture = extra->texture;
- bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest;
- UINT32 *p = &destmap->pix32(scanline);
- UINT32 *d = &extra->zbuffer->pix32(scanline);
- float ooz = extent->param[0].start;
- float uoz = extent->param[1].start;
- float voz = extent->param[2].start;
- float doozdx = extent->param[0].dpdx;
- float duozdx = extent->param[1].dpdx;
- float dvozdx = extent->param[2].dpdx;
- UINT32 polyi = extra->polygon_intensity;
- UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
- UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
- UINT32 width = 6 + texture->width;
- int x;
-
- for (x = extent->startx; x < extent->stopx; x++)
- {
- UINT32 iz = ooz * 256.0f;
- if (iz > d[x])
- {
- float z = 1.0f / ooz;
- UINT32 u = uoz * z;
- UINT32 v = voz * z;
- UINT32 u1 = (u >> 8) & umask;
- UINT32 v1 = (v >> 8) & vmask;
- UINT32 u2 = (u1 + 1) & umask;
- UINT32 v2 = (v1 + 1) & vmask;
- UINT32 pix00 = texture->data[(v1 << width) + u1];
- UINT32 pix01 = texture->data[(v1 << width) + u2];
- UINT32 pix10 = texture->data[(v2 << width) + u1];
- UINT32 pix11 = texture->data[(v2 << width) + u2];
- UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v);
- UINT32 fr = ((texel & 0x00ff0000) * polyi) >> 8;
- UINT32 fg = ((texel & 0x0000ff00) * polyi) >> 8;
- UINT32 fb = ((texel & 0x000000ff) * polyi) >> 8;
- p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff);
- d[x] = iz;
- }
-
- ooz += doozdx;
- uoz += duozdx;
- voz += dvozdx;
- }
-}
-
-static void draw_scanline_trans(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
-{
- const poly_extra_data *extra = (const poly_extra_data *)extradata;
- const cached_texture *texture = extra->texture;
- bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest;
- UINT32 *p = &destmap->pix32(scanline);
- UINT32 *d = &extra->zbuffer->pix32(scanline);
- float ooz = extent->param[0].start;
- float uoz = extent->param[1].start;
- float voz = extent->param[2].start;
- float doozdx = extent->param[0].dpdx;
- float duozdx = extent->param[1].dpdx;
- float dvozdx = extent->param[2].dpdx;
- UINT32 polyi = (extra->polygon_intensity * extra->polygon_transparency) >> 5;
- int desttrans = 32 - extra->polygon_transparency;
- UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
- UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
- UINT32 width = 6 + texture->width;
- int x;
-
- for (x = extent->startx; x < extent->stopx; x++)
- {
- UINT32 iz = ooz * 256.0f;
- if (iz > d[x])
- {
- float z = 1.0f / ooz;
- UINT32 u = uoz * z;
- UINT32 v = voz * z;
- UINT32 u1 = (u >> 8) & umask;
- UINT32 v1 = (v >> 8) & vmask;
- UINT32 u2 = (u1 + 1) & umask;
- UINT32 v2 = (v1 + 1) & vmask;
- UINT32 pix00 = texture->data[(v1 << width) + u1];
- UINT32 pix01 = texture->data[(v1 << width) + u2];
- UINT32 pix10 = texture->data[(v2 << width) + u1];
- UINT32 pix11 = texture->data[(v2 << width) + u2];
- UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v);
- UINT32 fr = ((texel & 0x00ff0000) * polyi) >> 8;
- UINT32 fg = ((texel & 0x0000ff00) * polyi) >> 8;
- UINT32 fb = ((texel & 0x000000ff) * polyi) >> 8;
- UINT32 orig = p[x];
- fr += ((orig & 0x00ff0000) * desttrans) >> 5;
- fg += ((orig & 0x0000ff00) * desttrans) >> 5;
- fb += ((orig & 0x000000ff) * desttrans) >> 5;
- p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff);
- d[x] = iz;
- }
-
- ooz += doozdx;
- uoz += duozdx;
- voz += dvozdx;
- }
-}
-
-
-static void draw_scanline_alpha(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
-{
- const poly_extra_data *extra = (const poly_extra_data *)extradata;
- const cached_texture *texture = extra->texture;
- bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest;
- UINT32 *p = &destmap->pix32(scanline);
- UINT32 *d = &extra->zbuffer->pix32(scanline);
- float ooz = extent->param[0].start;
- float uoz = extent->param[1].start;
- float voz = extent->param[2].start;
- float doozdx = extent->param[0].dpdx;
- float duozdx = extent->param[1].dpdx;
- float dvozdx = extent->param[2].dpdx;
- UINT32 polyi = (extra->polygon_intensity * extra->polygon_transparency) >> 5;
- int desttrans = 32 - extra->polygon_transparency;
- UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
- UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
- UINT32 width = 6 + texture->width;
- int x;
-
- for (x = extent->startx; x < extent->stopx; x++)
- {
- UINT32 iz = ooz * 256.0f;
- if (iz > d[x])
- {
- float z = 1.0f / ooz;
- UINT32 u = uoz * z;
- UINT32 v = voz * z;
- UINT32 u1 = (u >> 8) & umask;
- UINT32 v1 = (v >> 8) & vmask;
- UINT32 u2 = (u1 + 1) & umask;
- UINT32 v2 = (v1 + 1) & vmask;
- UINT32 pix00 = texture->data[(v1 << width) + u1];
- UINT32 pix01 = texture->data[(v1 << width) + u2];
- UINT32 pix10 = texture->data[(v2 << width) + u1];
- UINT32 pix11 = texture->data[(v2 << width) + u2];
- UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v);
- UINT32 fa = texel >> 24;
- if (fa != 0)
- {
- UINT32 combined = ((fa + 1) * polyi) >> 8;
- UINT32 fr = ((texel & 0x00ff0000) * combined) >> (8+9);
- UINT32 fg = ((texel & 0x0000ff00) * combined) >> (8+6);
- UINT32 fb = ((texel & 0x000000ff) * combined) >> (8+3);
- UINT32 orig = p[x];
- combined = ((255 - fa) * desttrans) >> 5;
- fr += ((orig & 0x00ff0000) * combined) >> 8;
- fg += ((orig & 0x0000ff00) * combined) >> 8;
- fb += ((orig & 0x000000ff) * combined) >> 8;
- p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff);
- d[x] = iz;
- }
- }
-
- ooz += doozdx;
- uoz += duozdx;
- voz += dvozdx;
- }
-}
-
-
-static void draw_scanline_alpha_test(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
-{
- const poly_extra_data *extra = (const poly_extra_data *)extradata;
- const cached_texture *texture = extra->texture;
- bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest;
- UINT32 *p = &destmap->pix32(scanline);
- UINT32 *d = &extra->zbuffer->pix32(scanline);
- float ooz = extent->param[0].start;
- float uoz = extent->param[1].start;
- float voz = extent->param[2].start;
- float doozdx = extent->param[0].dpdx;
- float duozdx = extent->param[1].dpdx;
- float dvozdx = extent->param[2].dpdx;
- UINT32 polyi = (extra->polygon_intensity * extra->polygon_transparency) >> 5;
- int desttrans = 32 - extra->polygon_transparency;
- UINT32 umask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
- UINT32 vmask = (((extra->texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
- UINT32 width = 6 + texture->width;
- int x;
-
- for (x = extent->startx; x < extent->stopx; x++)
- {
- UINT32 iz = ooz * 256.0f;
- if (iz > d[x])
- {
- float z = 1.0f / ooz;
- UINT32 u = uoz * z;
- UINT32 v = voz * z;
- UINT32 u1 = (u >> 8) & umask;
- UINT32 v1 = (v >> 8) & vmask;
- UINT32 u2 = (u1 + 1) & umask;
- UINT32 v2 = (v1 + 1) & vmask;
- UINT32 pix00 = texture->data[(v1 << width) + u1];
- UINT32 pix01 = texture->data[(v1 << width) + u2];
- UINT32 pix10 = texture->data[(v2 << width) + u1];
- UINT32 pix11 = texture->data[(v2 << width) + u2];
- UINT32 texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v);
- UINT32 fa = texel >> 24;
- if (fa >= 0xf8)
- {
- UINT32 combined = ((fa + 1) * polyi) >> 8;
- UINT32 fr = ((texel & 0x00ff0000) * combined) >> (8+9);
- UINT32 fg = ((texel & 0x0000ff00) * combined) >> (8+6);
- UINT32 fb = ((texel & 0x000000ff) * combined) >> (8+3);
- UINT32 orig = p[x];
- combined = ((255 - fa) * desttrans) >> 8;
- fr += ((orig & 0x00ff0000) * combined) >> 5;
- fg += ((orig & 0x0000ff00) * combined) >> 5;
- fb += ((orig & 0x000000ff) * combined) >> 5;
- p[x] = 0xff000000 | (fr & 0xff0000) | (fg & 0xff00) | (fb & 0xff);
- d[x] = iz;
- }
- }
-
- ooz += doozdx;
- uoz += duozdx;
- voz += dvozdx;
- }
-}
-
-static void draw_scanline_color(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
-{
- const poly_extra_data *extra = (const poly_extra_data *)extradata;
- bitmap_rgb32 *destmap = (bitmap_rgb32 *)dest;
- UINT32 *p = &destmap->pix32(scanline);
- UINT32 *d = &extra->zbuffer->pix32(scanline);
- float ooz = extent->param[0].start;
- float doozdx = extent->param[0].dpdx;
- int fr = (extra->color & 0x7c00) << 9;
- int fg = (extra->color & 0x03e0) << 6;
- int fb = (extra->color & 0x001f) << 3;
- int x;
-
- // apply intensity
- fr = (fr * extra->polygon_intensity) >> 8;
- fg = (fg * extra->polygon_intensity) >> 8;
- fb = (fb * extra->polygon_intensity) >> 8;
-
- /* simple case: no transluceny */
- if (extra->polygon_transparency >= 32)
- {
- UINT32 color = (fr & 0x7c00) | (fg & 0x03e0) | (fb & 0x1f);
- for (x = extent->startx; x < extent->stopx; x++)
- {
- UINT32 iz = ooz * 256.0f;
- if (iz > d[x])
- {
- p[x] = color;
- d[x] = iz;
- }
- ooz += doozdx;
- }
- }
-
- /* translucency */
- else
- {
- int polytrans = extra->polygon_transparency;
-
- fr = (fr * polytrans) >> 5;
- fg = (fg * polytrans) >> 5;
- fb = (fb * polytrans) >> 5;
- polytrans = 32 - polytrans;
-
- for (x = extent->startx; x < extent->stopx; x++)
- {
- UINT32 iz = ooz * 256.0f;
- if (iz > d[x])
- {
- UINT32 orig = p[x];
- int r = fr + (((orig & 0x00ff0000) * polytrans) >> 5);
- int g = fg + (((orig & 0x0000ff00) * polytrans) >> 5);
- int b = fb + (((orig & 0x000000ff) * polytrans) >> 5);
-
- p[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff);
- d[x] = iz;
- }
- ooz += doozdx;
- }
- }
-}
diff --git a/src/mame/video/model3.c b/src/mame/video/model3.c
index 3161a12cf82..df96dcebfcc 100644
--- a/src/mame/video/model3.c
+++ b/src/mame/video/model3.c
@@ -1,41 +1,50 @@
#include "emu.h"
-#include "video/polylgcy.h"
+#include "video/poly.h"
#include "video/rgbutil.h"
#include "includes/model3.h"
+#define ENABLE_BILINEAR 1
-#define pz p[0]
-#define pu p[1]
-#define pv p[2]
-
-
-struct cached_texture
-{
- cached_texture *next;
- UINT8 width;
- UINT8 height;
- UINT8 format;
- UINT8 alpha;
- rgb_t data[1];
-};
+#define TRI_PARAM_TEXTURE_PAGE 0x1
+#define TRI_PARAM_TEXTURE_MIRROR_U 0x2
+#define TRI_PARAM_TEXTURE_MIRROR_V 0x4
+#define TRI_PARAM_TEXTURE_ENABLE 0x8
+#define TRI_PARAM_ALPHA_TEST 0x10
-struct poly_extra_data
+struct model3_polydata
{
cached_texture *texture;
- bitmap_ind32 *zbuffer;
UINT32 color;
- UINT8 texture_param;
- int polygon_transparency;
- int polygon_intensity;
+ UINT32 texture_param;
+ int transparency;
+ int intensity;
};
-#define TRI_PARAM_TEXTURE_PAGE 0x1
-#define TRI_PARAM_TEXTURE_MIRROR_U 0x2
-#define TRI_PARAM_TEXTURE_MIRROR_V 0x4
-#define TRI_PARAM_TEXTURE_ENABLE 0x8
-#define TRI_PARAM_ALPHA_TEST 0x10
+class model3_renderer : public poly_manager<float, model3_polydata, 6, 50000>
+{
+public:
+ model3_renderer(model3_state &state, int width, int height)
+ : poly_manager<float, model3_polydata, 6, 50000>(state.machine()), m_state(state)
+ {
+ m_fb = auto_bitmap_rgb32_alloc(state.machine(), width, height);
+ m_zb = auto_bitmap_ind32_alloc(state.machine(), width, height);
+ }
+
+ void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void draw_triangle(const m3_triangle* tri);
+ void clear_buffers();
+ void draw_scanline_solid(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_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);
+
+private:
+ model3_state &m_state;
+ bitmap_rgb32 *m_fb;
+ bitmap_ind32 *m_zb;
+};
-#define MAX_TRIANGLES 131072
/*****************************************************************************/
@@ -44,14 +53,6 @@ struct poly_extra_data
#define MATRIX_STACK_SIZE 256
-#ifdef UNUSED_DEFINITION
-static const int num_bits[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
-#endif
-
-
-
-
-
#define BYTE_REVERSE32(x) (((x >> 24) & 0xff) | \
((x >> 8) & 0xff00) | \
((x << 8) & 0xff0000) | \
@@ -119,9 +120,8 @@ void model3_state::model3_exit()
fclose(file);
#endif
- invalidate_texture(0, 0, 0, 6, 5);
- invalidate_texture(1, 0, 0, 6, 5);
- poly_free(m_poly);
+// invalidate_texture(0, 0, 0, 6, 5);
+// invalidate_texture(1, 0, 0, 6, 5);
}
void model3_state::video_start()
@@ -148,11 +148,12 @@ void model3_state::video_start()
8 * 8*8
};
- m_poly = poly_alloc(machine(), 4000, sizeof(poly_extra_data), 0);
- machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(model3_state::model3_exit), this));
+ int width = m_screen->width();
+ int height = m_screen->height();
- m_screen->register_screen_bitmap(m_bitmap3d);
- m_screen->register_screen_bitmap(m_zbuffer);
+ m_renderer = auto_alloc(machine(), model3_renderer(*this, width, height));
+
+ machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(model3_state::model3_exit), this));
m_m3_char_ram = auto_alloc_array_clear(machine(), UINT64, 0x100000/8);
m_m3_tile_ram = auto_alloc_array_clear(machine(), UINT64, 0x8000/8);
@@ -170,8 +171,6 @@ void model3_state::video_start()
/* 4MB Polygon RAM */
m_polygon_ram = auto_alloc_array_clear(machine(), UINT32, 0x400000/4);
- m_tick = 0;
- m_debug_layer_disable = 0;
m_vid_reg0 = 0;
m_viewport_focal_length = 300.;
@@ -251,6 +250,7 @@ void model3_state::draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, i
const pen_t *pens = m_palette->pens();
UINT32* palram = (UINT32*)&m_paletteram64[0];
+ UINT16* rowscroll_ram = (UINT16*)&m_m3_char_ram[0x1ec00];
int x1 = cliprect.min_x;
int y1 = cliprect.min_y;
@@ -273,16 +273,30 @@ void model3_state::draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, i
UINT32* dst = &bitmap.pix32(y);
UINT16* src = &pixmap.pix16(iy & 0x1ff);
- int iix = ix;
+ int rowscroll = BYTE_REVERSE16(rowscroll_ram[((layer * 0x200) + y) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0)]) & 0x7fff;
+ if (rowscroll & 0x100)
+ rowscroll |= ~0x1ff;
- for (int x = x1; x <= x2; x++)
+ int iix = ix & 0x1ff;
+
+ int rx1 = x1 - (rowscroll * 2);
+ int rx2 = x2 - (rowscroll * 2);
+
+ if (rx1 < 0)
+ {
+ iix += (0 - rx1);
+ rx1 = 0;
+ }
+ if (rx2 > cliprect.max_x)
+ rx2 = cliprect.max_x;
+
+ 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)
{
- *dst = pens[p0];
+ dst[x] = pens[p0];
}
- dst++;
iix++;
}
@@ -324,7 +338,7 @@ UINT32 model3_state::screen_update_model3(screen_device &screen, bitmap_rgb32 &b
draw_layer(bitmap, cliprect, 0, m_layer_priority & 0x10, layer_scroll_x[0], layer_scroll_y[0]);
// render 3D
- draw_3d_layer(bitmap, cliprect);
+ m_renderer->draw(bitmap, cliprect);
// render enabled layers with priority 1
if ((layer_data[3] & 0x80000000) && (m_layer_priority & 0x8) != 0)
@@ -336,7 +350,6 @@ UINT32 model3_state::screen_update_model3(screen_device &screen, bitmap_rgb32 &b
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]);
- m_real3d_display_list = 0;
return 0;
}
@@ -620,30 +633,266 @@ cached_texture *model3_state::get_texture(int page, int texx, int texy, int texw
/*****************************************************************************/
/* Real3D Graphics stuff */
+/*
+ Real3D Pro-1000 capabilities:
+
+ Coordinate sets
+ - 4096 matrices (matrix base pointer in viewport node)
+
+ Polygons
+ - 32MB max polygon memory. VROM in Model 3, the low 4MB of VROM is overlaid by Polygon RAM for runtime generated content.
+
+ Texture
+ - 2 texture sheets of 2048x1024
+ - Mipmaps located in the bottom right corner
+ - Texture size 32x32 to 1024x1024
+ - Microtextures (is this featured in Model 3?)
+
+ LODs
+ - 127 blend types per viewport with 4 sets of min/max angle or range (where is this in the viewport node?)
+
+ Lighting
+ - Self-luminous lighting (enable and luminosity parameter in polygon structure)
+ - Fixed polygon shading, fixed shading weight per vertex (not found in Model 3, yet)
+ - Flat sun shading (lighting parameters in viewport node) needs a separate enable?
+ - Smooth polygon shading (lighting parameters in viewport, use vertex normals)
+
+ Gamma table
+ - 256 entry 8-bit table, possibly in Polygon RAM
+*/
+
+/*
+ Real3D Memory Structures:
+
+ Culling Nodes:
+ - Located in Culling RAM (0x8E000000)
+ - Limit of 15 child nodes (nesting), not including polygon nodes
+ - Color table (is this featured in Model 3?)
+
+ 0x00: -------- -------- ------xx -------- Viewport number 0-3
+ -------- -------- -------- ---xx--- Viewport priority
+
+ 0x01: Child node pointer (inherits parameters from this node)
+ 0x02: Sibling node pointer
+ 0x03: Unknown (float)
+ 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
+
+ 0x14: xxxxxxxx xxxxxxxx -------- -------- Viewport height (14.2 fixed-point)
+ -------- -------- xxxxxxxx xxxxxxxx Viewport width (14.2 fixed-point)
+
+ 0x15: ?
+ 0x16: Matrix base pointer
+ 0x17: LOD blend type table pointer? (seems to be 8x float per entry)
+ 0x18: ?
+ 0x19: ?
+
+ 0x1a: xxxxxxxx xxxxxxxx -------- -------- Viewport Y coordinate (12.4 fixed-point)
+ -------- -------- xxxxxxxx xxxxxxxx Viewport X coordinate (12.4 fixed-point)
+
+ 0x1b: Copy of word 0x00
+ 0x1c: ?
+
+ 0x1d: xxxxxxxx xxxxxxxx -------- -------- Spotlight Y size
+ -------- -------- xxxxxxxx xxxxxxxx Spotlight Y position (13.3 fixed-point?)
+
+ 0x1e: xxxxxxxx xxxxxxxx -------- -------- Spotlight X size
+ -------- -------- xxxxxxxx xxxxxxxx Spotlight X position (13.3 fixed-point?)
+
+ 0x1f: Light extent (float)
+
+ 0x20: xxxxxxxx -------- -------- -------- ?
+ -------- xxxxxxxx -------- -------- ?
+ -------- -------- --xxx--- -------- Light RGB (RGB111?)
+ -------- -------- -----xxx -------- Light RGB Fog (RGB111?)
+ -------- -------- -------- xxxxxxxx Scroll Fog (0.8 fixed-point?) What is this???
+
+ 0x21: ?
+ 0x22: Fog Color (RGB888)
+ 0x23: Fog Density (float)
+
+ 0x24: xxxxxxxx xxxxxxxx -------- -------- ?
+ -------- -------- xxxxxxxx -------- Sun light ambient (0.8 fixed-point)
+ -------- -------- -------- xxxxxxxx Scroll attenuation (0.8 fixed-point) What is this???
+
+ 0x25: Fog offset
+ 0x26: ?
+ 0x27: ?
+ 0x28: ?
+ 0x29: ?
+ 0x2a: ?
+ 0x2b: ?
+ 0x2c: ?
+ 0x2d: ?
+ 0x2e: ?
+ 0x2f: ?
+
+
+ Sub types:
+ LOD Culling Node. Up to 4 LODs.
+
+ Articulated Part Culling Node (is this used by Model 3?)
+ - An Articulated Part culling node, or six degree–of–freedom node, is used to define
+ geometry that can move relative to the parent coordinate set to which it is attached.
+ Fifteen levels of coordinate set nesting (levels of articulation) are supported.
+
+ Animation Culling Node
+ - Animation culling nodes are used to build a culling hierarchy for an object with different
+ representations, or animation frames. which can be turned on and off by the
+ application. Each child (culling node or polygon) added to an Animation culling node
+ specifies the frame for which the child is valid.
+
+ Instance Culling Node
+ - Instance culling nodes define the top of a shared display list segment that can be
+ referenced from other parts of the scene display list.
+
+ Instance Reference Culling Node
+ - An Instance Reference node is considered a leaf node; its
+ "child" is the shared geometry segment. An Instance Reference may be attached to
+ a parent node and may not have any other children, but may have siblings.
+
+ Point Light
+ - A Point Light is used to create an instance of a point luminous feature. The size,
+ feature type, and number of sides of the point light model may be customized.
+
+ Instance Set
+ - An Instance Set is a culling node which defines a set of point features. Each feature
+ is positioned individually. This type of culling node can be used to simulate particles.
+
+
+
+ Instance Node?
+
+ 0x00: xxxxxxxx xxxxxxxx xxxxxx-- -------- Node number/ID?, num of bits unknown
+ -------- -------- -------- ---x---- This node applies translation, else matrix
+ -------- -------- -------- ----x--- LOD enable?
+ -------- -------- -------- -----x-- ?
+ -------- -------- -------- ------x- ?
+ -------- -------- -------- -------x ?
+
+
+ 0x01: ? (not present on Step 1.0)
+ 0x02: ? (not present on Step 1.0) Scud Race has 0x00000101
+
+ 0x03: --x----- -------- -------- -------- ?
+ -------- -xxxxxxx xxxx---- -------- LOD?
+ -------- -------- ----xxxx xxxxxxxx Node matrix
+
+ 0x04: Translation X coordinate
+ 0x05: Translation Y coordinate
+ 0x06: Translation Z coordinate
+ 0x07: Child node pointer
+ 0x08: Sibling node pointer
+
+ 0x09: xxxxxxxx xxxxxxxx -------- -------- Culling or sorting related?
+ -------- -------- xxxxxxxx xxxxxxxx Culling or sorting related?
+
+
+ Polygon Data
+
+ 0x00: -------- 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---- ?
+ -------- -------- ------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-- If set, this is the last polygon
+ -------- -------- -------- x-xxx-xx ?
+
+ 0x02: xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Y coordinate (2.22 fixed point)
+ -------- -------- -------- ------x- Texture U mirror enable
+ -------- -------- -------- -------x Texture V mirror enable
+ -------- -------- -------- xxxxxx-- ?
+
+ 0x03: xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Z coordinate (2.22 fixed point)
+ -------- -------- -------- --xxx--- Texture width (in 8-pixel tiles)
+ -------- -------- -------- -----xxx Texture height (in 8-pixel tiles)
+
+ 0x04: xxxxxxxx xxxxxxxx xxxxxxxx -------- Color (RGB888)
+ -------- -------- -------- -x------ Texture page
+ -------- -------- -------- ---xxxxx Upper 5 bits of texture U coordinate
+ -------- -------- -------- x-x----- ?
+
+ 0x05: xxxxxxxx xxxxxxxx xxxxxxxx -------- Specular color?
+ -------- -------- -------- x------- Low bit of texture U coordinate
+ -------- -------- -------- ---xxxxx Low 5 bits of texture V coordinate
+ -------- -------- -------- -xx----- ?
+
+ 0x06: x------- -------- -------- -------- Texture contour enable
+ -----x-- -------- -------- -------- Texture enable
+ -------- x------- -------- -------- 1 = disable transparency?
+ -------- -xxxxx-- -------- -------- Polygon transparency (0 = fully transparent)
+ -------- -------x -------- -------- 1 = disable lighting
+ -------- -------- xxxxx--- -------- Polygon luminosity
+ -------- -------- ------xx x------- Texture format
+ -------- -------- -------- -------x Alpha enable?
+ -xxxx-xx ------x- -----x-- -xxxxxx- ?
+
+
+ Vertex entry
+
+ 0x00: xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex X coordinate (17.7 fixed-point in Step 1.0, 13.11 otherwise)
+ -------- -------- -------- xxxxxxxx Vertex normal X (offset from polygon normal)
+
+ 0x01: xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex Y coordinate
+ -------- -------- -------- xxxxxxxx Vertex normal Y
+
+ 0x02: xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex Z coordinate
+ -------- -------- -------- xxxxxxxx Vertex normal Z
+
+ 0x03: xxxxxxxx xxxxxxxx -------- -------- Vertex U coordinate
+ -------- -------- xxxxxxxx xxxxxxxx Vertex V coordinate
+
+*/
+
+
WRITE64_MEMBER(model3_state::real3d_display_list_w)
{
- if(ACCESSING_BITS_32_63) {
+ if (ACCESSING_BITS_32_63)
+ {
m_display_list_ram[offset*2] = BYTE_REVERSE32((UINT32)(data >> 32));
}
- if(ACCESSING_BITS_0_31) {
+ if (ACCESSING_BITS_0_31)
+ {
m_display_list_ram[(offset*2)+1] = BYTE_REVERSE32((UINT32)(data));
}
}
WRITE64_MEMBER(model3_state::real3d_polygon_ram_w)
{
- if(ACCESSING_BITS_32_63) {
+ if (ACCESSING_BITS_32_63)
+ {
m_polygon_ram[offset*2] = BYTE_REVERSE32((UINT32)(data >> 32));
}
- if(ACCESSING_BITS_0_31) {
+ if (ACCESSING_BITS_0_31)
+ {
m_polygon_ram[(offset*2)+1] = BYTE_REVERSE32((UINT32)(data));
}
}
static const UINT8 texture_decode[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,
@@ -753,8 +1002,7 @@ void model3_state::real3d_display_list_end()
}
m_texture_fifo_pos = 0;
- m_zbuffer.fill(0);
- m_bitmap3d.fill(0);
+ m_renderer->clear_buffers();
real3d_traverse_display_list();
}
@@ -765,12 +1013,11 @@ void model3_state::real3d_display_list1_dma(UINT32 src, UINT32 dst, int length,
int d = (dst & 0xffffff) / 4;
for (int i = 0; i < length; i += 4)
{
- UINT32 w;
- if (byteswap) {
- w = BYTE_REVERSE32(space.read_dword(src));
- } else {
- w = space.read_dword(src);
- }
+ UINT32 w = space.read_dword(src);
+
+ if (byteswap)
+ w = BYTE_REVERSE32(w);
+
m_display_list_ram[d++] = w;
src += 4;
}
@@ -782,12 +1029,11 @@ void model3_state::real3d_display_list2_dma(UINT32 src, UINT32 dst, int length,
int d = (dst & 0xffffff) / 4;
for (int i = 0; i < length; i += 4)
{
- UINT32 w;
- if (byteswap) {
- w = BYTE_REVERSE32(space.read_dword(src));
- } else {
- w = space.read_dword(src);
- }
+ UINT32 w = space.read_dword(src);
+
+ if (byteswap)
+ w = BYTE_REVERSE32(w);
+
m_culling_ram[d++] = w;
src += 4;
}
@@ -800,15 +1046,15 @@ void model3_state::real3d_vrom_texture_dma(UINT32 src, UINT32 dst, int length, i
{
for (int i=0; i < length; i+=12)
{
- UINT32 address, header;
-
- if (byteswap) {
- address = BYTE_REVERSE32(space.read_dword((src+i+0)));
- header = BYTE_REVERSE32(space.read_dword((src+i+4)));
- } else {
- address = space.read_dword((src+i+0));
- header = space.read_dword((src+i+4));
+ UINT32 address = space.read_dword(src+i+0);
+ UINT32 header = space.read_dword(src+i+4);
+
+ if (byteswap)
+ {
+ address = BYTE_REVERSE32(address);
+ header = BYTE_REVERSE32(header);
}
+
real3d_upload_texture(header, (UINT32*)&m_vrom[address]);
}
}
@@ -819,12 +1065,11 @@ void model3_state::real3d_texture_fifo_dma(UINT32 src, int length, int byteswap)
address_space &space = m_maincpu->space(AS_PROGRAM);
for (int i = 0; i < length; i += 4)
{
- UINT32 w;
- if (byteswap) {
- w = BYTE_REVERSE32(space.read_dword(src));
- } else {
- w = space.read_dword(src);
- }
+ UINT32 w = space.read_dword(src);
+
+ if (byteswap)
+ w = BYTE_REVERSE32(w);
+
m_texture_fifo[m_texture_fifo_pos] = w;
m_texture_fifo_pos++;
src += 4;
@@ -837,12 +1082,11 @@ void model3_state::real3d_polygon_ram_dma(UINT32 src, UINT32 dst, int length, in
int d = (dst & 0xffffff) / 4;
for (int i = 0; i < length; i += 4)
{
- UINT32 w;
- if (byteswap) {
- w = BYTE_REVERSE32(space.read_dword(src));
- } else {
- w = space.read_dword(src);
- }
+ UINT32 w = space.read_dword(src);
+
+ if (byteswap)
+ w = BYTE_REVERSE32(w);
+
m_polygon_ram[d++] = w;
src += 4;
}
@@ -857,13 +1101,6 @@ WRITE64_MEMBER(model3_state::real3d_cmd_w)
/*****************************************************************************/
/* matrix and vector operations */
-#ifdef UNUSED_FUNCTION
-INLINE float dot_product(VECTOR a, VECTOR b)
-{
- return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]) + (a[3] * b[3]);
-}
-#endif
-
INLINE float dot_product3(VECTOR3 a, VECTOR3 b)
{
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
@@ -959,29 +1196,27 @@ void model3_state::translate_matrix_stack(float x, float y, float z)
/*****************************************************************************/
/* transformation and rasterizing */
-#include "m3raster.inc"
-
-INLINE int is_point_inside(float x, float y, float z, PLANE cp)
+INLINE bool is_point_inside(float x, float y, float z, m3_plane cp)
{
float s = (x * cp.x) + (y * cp.y) + (z * cp.z) + cp.d;
if (s >= 0.0f)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
-INLINE float line_plane_intersection(const poly_vertex *v1, const poly_vertex *v2, PLANE cp)
+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->pz - v2->pz;
- float t = ((cp.x * v1->x) + (cp.y * v1->y) + (cp.z * v1->pz)) / ((cp.x * x) + (cp.y * y) + (cp.z * z));
+ 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;
}
-static int clip_polygon(const poly_vertex *v, int num_vertices, PLANE cp, poly_vertex *vout)
+static int clip_polygon(const m3_clip_vertex *v, int num_vertices, m3_plane cp, m3_clip_vertex *vout)
{
- poly_vertex clipv[10];
+ m3_clip_vertex clipv[10];
int clip_verts = 0;
float t;
int i;
@@ -990,8 +1225,8 @@ static int clip_polygon(const poly_vertex *v, int num_vertices, PLANE cp, poly_v
for (i=0; i < num_vertices; i++)
{
- int v1_in = is_point_inside(v[i].x, v[i].y, v[i].pz, cp);
- int v2_in = is_point_inside(v[previ].x, v[previ].y, v[previ].pz, cp);
+ 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);
if (v1_in && v2_in) /* edge is completely inside the volume */
{
@@ -1004,9 +1239,10 @@ static int clip_polygon(const poly_vertex *v, int num_vertices, PLANE cp, poly_v
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].pz = v[i].pz + ((v[previ].pz - v[i].pz) * t);
- clipv[clip_verts].pu = v[i].pu + ((v[previ].pu - v[i].pu) * t);
- clipv[clip_verts].pv = v[i].pv + ((v[previ].pv - v[i].pv) * 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 */
@@ -1015,9 +1251,10 @@ static int clip_polygon(const poly_vertex *v, int num_vertices, PLANE cp, poly_v
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].pz = v[i].pz + ((v[previ].pz - v[i].pz) * t);
- clipv[clip_verts].pu = v[i].pu + ((v[previ].pu - v[i].pu) * t);
- clipv[clip_verts].pv = v[i].pv + ((v[previ].pv - v[i].pv) * 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 */
@@ -1031,70 +1268,29 @@ static int clip_polygon(const poly_vertex *v, int num_vertices, PLANE cp, poly_v
return clip_verts;
}
-void model3_state::render_one(TRIANGLE *tri)
-{
- poly_extra_data *extra = (poly_extra_data *)poly_get_extra_data(m_poly);
- poly_draw_scanline_func callback = NULL;
-
- tri->v[0].pz = 1.0f / tri->v[0].pz;
- tri->v[1].pz = 1.0f / tri->v[1].pz;
- tri->v[2].pz = 1.0f / tri->v[2].pz;
-
- extra->zbuffer = &m_zbuffer;
- if (tri->param & TRI_PARAM_TEXTURE_ENABLE)
- {
- tri->v[0].pu = tri->v[0].pu * tri->v[0].pz * 256.0f;
- tri->v[0].pv = tri->v[0].pv * tri->v[0].pz * 256.0f;
- tri->v[1].pu = tri->v[1].pu * tri->v[1].pz * 256.0f;
- tri->v[1].pv = tri->v[1].pv * tri->v[1].pz * 256.0f;
- tri->v[2].pu = tri->v[2].pu * tri->v[2].pz * 256.0f;
- tri->v[2].pv = tri->v[2].pv * tri->v[2].pz * 256.0f;
-
- extra->texture = get_texture((tri->param & TRI_PARAM_TEXTURE_PAGE) ? 1 : 0, tri->texture_x, tri->texture_y, tri->texture_width, tri->texture_height, tri->texture_format);
- extra->texture_param = tri->param;
- extra->polygon_transparency = tri->transparency;
- extra->polygon_intensity = tri->intensity;
-
- if (tri->param & TRI_PARAM_ALPHA_TEST)
- callback = draw_scanline_alpha_test;
- else if (extra->texture->alpha == 0xff)
- callback = (tri->transparency >= 32) ? draw_scanline_normal : draw_scanline_trans;
- else
- callback = draw_scanline_alpha;
- poly_render_triangle(m_poly, &m_bitmap3d, m_clip3d, callback, 3, &tri->v[0], &tri->v[1], &tri->v[2]);
- }
- else
- {
- extra->polygon_transparency = tri->transparency;
- extra->polygon_intensity = tri->intensity;
- extra->color = tri->color;
-
- poly_render_triangle(m_poly, &m_bitmap3d, m_clip3d, draw_scanline_color, 1, &tri->v[0], &tri->v[1], &tri->v[2]);
- }
-}
-
void model3_state::draw_model(UINT32 addr)
{
+ // Polygon RAM is mapped to the low 4MB of VROM
UINT32 *model = (addr >= 0x100000) ? &m_vrom[addr] : &m_polygon_ram[addr];
+
UINT32 header[7];
int index = 0;
int last_polygon = FALSE, first_polygon = TRUE, back_face = FALSE;
int num_vertices;
int i, v, vi;
float fixed_point_fraction;
- poly_vertex vertex[4];
- poly_vertex prev_vertex[4];
- poly_vertex clip_vert[10];
+ m3_vertex vertex[4];
+ m3_vertex prev_vertex[4];
+ m3_clip_vertex clip_vert[10];
MATRIX transform_matrix;
float center_x, center_y;
- if(m_step < 0x15) { /* position coordinates are 17.15 fixed-point in Step 1.0 */
- fixed_point_fraction = 1.0f / 32768.0f;
- } else { /* 13.19 fixed-point in other Steps */
- fixed_point_fraction = 1.0f / 524288.0f;
- }
-
+ if (m_step < 0x15) // position coordinates are 17.7 fixed-point in Step 1.0
+ fixed_point_fraction = 1.0f / 128.0f;
+ else // 13.11 fixed-point in other Steps
+ fixed_point_fraction = 1.0f / 2048.0f;
+
get_top_matrix(&transform_matrix);
/* current viewport center coordinates on screen */
@@ -1110,51 +1306,10 @@ void model3_state::draw_model(UINT32 addr)
VECTOR3 normal;
VECTOR3 sn;
VECTOR p[4];
- TRIANGLE tri;
+ m3_triangle tri;
float dot;
- int intensity;
int polygon_transparency;
- //
- // Header bits:
- //
- // 0:00FFFC00 - polygon ID
- // 0:00000300 - ????
- // 0:00000040 - if set, indicates a quad, else it's a triangle
- // 0:00000008 - inherit vertex 3 from previous polygon
- // 0:00000004 - inherit vertex 2 from previous polygon
- // 0:00000002 - inherit vertex 1 from previous polygon
- // 0:00000001 - inherit vertex 0 from previous polygon
- //
- // 1:FFFFFF00 - polygon normal X coordinate, 2.22
- // 1:00000040 - if set, U/V is as-is, else divide U/V by 8
- // 1:00000004 - if set, indicates last polygon in model
- //
- // 2:FFFFFF00 - polygon normal Y coordinate, 2.22
- // 2:00000002 - if set, mirror texture in U
- // 2:00000001 - if set, mirror texture in V
- //
- // 3:FFFFFF00 - polygon normal Z coordinate, 2.22
- // 3:00000038 - texture width, in tiles
- // 3:00000007 - texture height, in tiles
- //
- // 4:FFFFFF00 - RGB lighting color
- // 4:00000040 - texture page
- // 4:0000001F - upper 5 bits of texture X coordinate
- //
- // 5:00000080 - low bit of texture X coordinate
- // 5:0000001F - low 5 bits of texture Y coordinate
- //
- // 6:80000000 - if set, enable alpha test
- // 6:04000000 - if set, textures enabled
- // 6:00800000 - if set, force transparency off
- // 6:007C0000 - 5-bit transparency value (0 is transparent, 0x1F is nearly opaque)
- // 6:00010000 - if set, disable lighting
- // 6:0000F800 - 5-bit additional color control
- // 6:00000380 - 3-bit texture format
- // 6:00000001 - alpha enable?
- //
-
for (i = 0; i < 7; i++)
header[i] = model[index++];
@@ -1168,6 +1323,9 @@ void model3_state::draw_model(UINT32 addr)
if (header[1] & 0x4)
last_polygon = TRUE;
+ if ((header[0] & 0x300) == 0x300) // TODO: broken polygons in srally2 have these bits set
+ return;
+
num_vertices = (header[0] & 0x40) ? 4 : 3;
/* texture coordinates are 16.0 or 13.3 fixed-point */
@@ -1187,22 +1345,28 @@ void model3_state::draw_model(UINT32 addr)
/* load new vertices */
for ( ; vi < num_vertices; vi++)
{
- if ((model[index+0] & 0xf0000000) == 0x70000000 ||
- (model[index+1] & 0xf0000000) == 0x70000000 ||
- (model[index+2] & 0xf0000000) == 0x70000000)
- return;
-
- vertex[vi].x = (float)((INT32)model[index++]) * fixed_point_fraction;
- vertex[vi].y = (float)((INT32)model[index++]) * fixed_point_fraction;
- vertex[vi].pz = (float)((INT32)model[index++]) * fixed_point_fraction;
- vertex[vi].pu = (UINT16)(model[index] >> 16);
- vertex[vi].pv = (UINT16)(model[index++]);
+ UINT32 xw = model[index++];
+ UINT32 yw = model[index++];
+ UINT32 zw = model[index++];
+
+ vertex[vi].x = (float)((INT32)(xw) >> 8) * fixed_point_fraction;
+ vertex[vi].y = (float)((INT32)(yw) >> 8) * fixed_point_fraction;
+ vertex[vi].z = (float)((INT32)(zw) >> 8) * fixed_point_fraction;
+ vertex[vi].u = (UINT16)(model[index] >> 16);
+ vertex[vi].v = (UINT16)(model[index++]);
+// vertex[vi].nx = normal[0] + ((float)((INT8)(xw)) / 127.0f);
+// vertex[vi].ny = normal[1] + ((float)((INT8)(yw)) / 127.0f);
+// vertex[vi].nz = normal[2] + ((float)((INT8)(zw)) / 127.0f);
+
+ vertex[vi].nx = ((float)((INT8)(xw)) / 127.0f);
+ vertex[vi].ny = ((float)((INT8)(yw)) / 127.0f);
+ vertex[vi].nz = ((float)((INT8)(zw)) / 127.0f);
}
/* Copy current vertices as previous vertices */
- memcpy(prev_vertex, vertex, sizeof(poly_vertex) * 4);
+ memcpy(prev_vertex, vertex, sizeof(m3_vertex) * 4);
- color = (((header[4] >> 27) & 0x1f) << 10) | (((header[4] >> 19) & 0x1f) << 5) | ((header[4] >> 11) & 0x1f);
+ color = (header[4] >> 8) & 0xffffff;
polygon_transparency = (header[6] & 0x800000) ? 32 : ((header[6] >> 18) & 0x1f);
/* transform polygon normal to view-space */
@@ -1220,26 +1384,64 @@ void model3_state::draw_model(UINT32 addr)
sn[1] *= m_coordinate_system[1][2];
sn[2] *= m_coordinate_system[2][0];
- /* TODO: depth bias */
- /* transform vertices */
+ // TODO: depth bias
+ // transform and light vertices
for (i = 0; i < num_vertices; i++)
{
VECTOR vect;
vect[0] = vertex[i].x;
vect[1] = vertex[i].y;
- vect[2] = vertex[i].pz;
+ vect[2] = vertex[i].z;
vect[3] = 1.0f;
- /* transform to world-space */
+ // transform to world-space
matrix_multiply_vector(transform_matrix, vect, &p[i]);
- /* apply coordinate system */
+ // 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].pz = p[i][2] * m_coordinate_system[2][0];
- clip_vert[i].pu = vertex[i].pu * texture_coord_scale;
- clip_vert[i].pv = vertex[i].pv * texture_coord_scale;
+ 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;
+
+ // 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[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[2][2]);
+ n[2] *= m_coordinate_system[2][0];
+
+ // lighting
+ float intensity;
+ if ((header[6] & 0x10000) == 0)
+ {
+ dot = dot_product3(n, m_parallel_light);
+ intensity = ((dot * m_parallel_light_intensity) + m_ambient_light_intensity) * 255.0f;
+ if (intensity > 255.0f)
+ {
+ intensity = 255.0f;
+ }
+ if (intensity < 0.0f)
+ {
+ intensity = 0.0f;
+ }
+ }
+ else
+ {
+ // apply luminosity
+ intensity = ((float)((header[6] >> 11) & 0x1f) / 31.0f) * 255.0f;
+ }
+
+ clip_vert[i].i = intensity;
}
/* clip against view frustum */
@@ -1251,7 +1453,7 @@ void model3_state::draw_model(UINT32 addr)
/* 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].pz >0)
+ 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;
@@ -1259,47 +1461,48 @@ void model3_state::draw_model(UINT32 addr)
else
back_face = 0; //no culling for transparent or two-sided polygons
- if(!back_face) {
+ if (!back_face)
+ {
/* homogeneous Z-divide, screen-space transformation */
- for(i=0; i < num_vertices; i++) {
- float ooz = 1.0f / clip_vert[i].pz;
+ 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;
}
- // lighting
- if ((header[6] & 0x10000) == 0)
+
+ cached_texture* texture;
+
+ if (header[6] & 0x4000000)
{
- dot = dot_product3(sn, m_parallel_light);
- intensity = ((dot * m_parallel_light_intensity) + m_ambient_light_intensity) * 256.0f;
- if (intensity > 256)
- {
- intensity = 256;
- }
- if (intensity < 0)
- {
- intensity = 0;
- }
+ int tex_x = ((header[4] & 0x1f) << 1) | ((header[5] >> 7) & 0x1);
+ int tex_y = (header[5] & 0x1f);
+ int tex_width = ((header[3] >> 3) & 0x7);
+ int tex_height = (header[3] & 0x7);
+ int tex_format = (header[6] >> 7) & 0x7;
+
+ if (tex_width >= 6 || tex_height >= 6) // srally2 poly ram has degenerate polys with 2k tex size (cpu bug or intended?)
+ return;
+
+ texture = get_texture((header[4] & 0x40) ? 1 : 0, tex_x, tex_y, tex_width, tex_height, tex_format);
}
else
{
- // apply luminosity
- intensity = 256;
+ texture = NULL;
}
for (i=2; i < num_vertices; i++)
{
- memcpy(&tri.v[0], &clip_vert[0], sizeof(poly_vertex));
- memcpy(&tri.v[1], &clip_vert[i-1], sizeof(poly_vertex));
- memcpy(&tri.v[2], &clip_vert[i], sizeof(poly_vertex));
- tri.texture_x = ((header[4] & 0x1f) << 1) | ((header[5] >> 7) & 0x1);
- tri.texture_y = (header[5] & 0x1f);
- tri.texture_width = ((header[3] >> 3) & 0x7);
- tri.texture_height = (header[3] & 0x7);
- tri.texture_format = (header[6] >> 7) & 0x7;
- tri.transparency = polygon_transparency;
- tri.intensity = intensity;
- tri.color = color;
+ memcpy(&tri.v[0], &clip_vert[0], sizeof(m3_clip_vertex));
+ memcpy(&tri.v[1], &clip_vert[i-1], sizeof(m3_clip_vertex));
+ memcpy(&tri.v[2], &clip_vert[i], sizeof(m3_clip_vertex));
+
+ tri.texture = texture;
+ tri.transparency = polygon_transparency;
+ tri.color = color >> 8;
tri.param = 0;
tri.param |= (header[4] & 0x40) ? TRI_PARAM_TEXTURE_PAGE : 0;
@@ -1308,7 +1511,7 @@ void model3_state::draw_model(UINT32 addr)
tri.param |= (header[2] & 0x1) ? TRI_PARAM_TEXTURE_MIRROR_V : 0;
tri.param |= (header[6] & 0x80000000) ? TRI_PARAM_ALPHA_TEST : 0;
- render_one(&tri);
+ m_renderer->draw_triangle(&tri);
}
}
}
@@ -1521,20 +1724,20 @@ void model3_state::real3d_traverse_display_list()
{
init_matrix_stack();
+ m_list_depth = 0;
+
for (int pri = 0; pri < 4; pri++)
draw_viewport(pri, 0x800000);
-
- poly_wait(m_poly, "real3d_traverse_display_list");
}
-void model3_state::draw_3d_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect)
+void model3_renderer::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int i, j;
for (j = cliprect.min_y; j <= cliprect.max_y; ++j)
{
UINT32 *dst = &bitmap.pix32(j);
- UINT32 *src = &m_bitmap3d.pix32(j);
+ UINT32 *src = &m_fb->pix32(j);
for (i = cliprect.min_x; i <= cliprect.max_x; ++i)
{
@@ -1544,4 +1747,390 @@ void model3_state::draw_3d_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect
}
}
}
+}
+
+void model3_renderer::clear_buffers()
+{
+ rectangle cliprect;
+ cliprect.min_x = 0;
+ cliprect.min_y = 0;
+ cliprect.max_x = 495;
+ cliprect.max_y = 383;
+
+ m_fb->fill(0x00000000, cliprect);
+
+ float zvalue = 10000000000.0f;
+ m_zb->fill(*(int*)&zvalue, cliprect);
+}
+
+void model3_renderer::draw_triangle(const m3_triangle *tri)
+{
+ rectangle cliprect;
+ cliprect.min_x = 0;
+ cliprect.min_y = 0;
+ cliprect.max_x = 495;
+ cliprect.max_y = 383;
+
+ vertex_t v[3];
+
+ if (tri->param & TRI_PARAM_TEXTURE_ENABLE)
+ {
+ for (int i=0; i < 3; i++)
+ {
+ 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[4] = tri->v[i].i;
+ }
+
+ model3_polydata &extra = object_data_alloc();
+ extra.texture = tri->texture;
+ extra.transparency = tri->transparency;
+ extra.intensity = tri->intensity;
+ extra.texture_param = tri->param;
+
+ render_delegate rd;
+ if (tri->param & TRI_PARAM_ALPHA_TEST)
+ {
+ rd = render_delegate(FUNC(model3_renderer::draw_scanline_contour), this);
+ }
+ else if (extra.texture->alpha == 0xff)
+ {
+ if (tri->transparency >= 32)
+ rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex), this);
+ else
+ rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex_trans), this);
+ }
+ else
+ {
+ rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex_alpha), this);
+ }
+
+ render_triangle(cliprect, rd, 5, v[0], v[1], v[2]);
+ }
+ else
+ {
+ for (int i=0; i < 3; i++)
+ {
+ 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] = tri->v[i].i;
+ }
+
+ model3_polydata &extra = object_data_alloc();
+
+ extra.intensity = tri->intensity;
+ extra.color = tri->color;
+
+ render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_solid), this), 2, v[0], v[1], v[2]);
+ }
+}
+
+void model3_renderer::draw_scanline_solid(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;
+
+ int r = polydata.color & 0xff0000;
+ int g = polydata.color & 0xff00;
+ int b = polydata.color & 0xff;
+
+ int srctrans = polydata.transparency;
+ int desttrans = 32 - polydata.transparency;
+
+ for (int x = extent.startx; x < extent.stopx; x++)
+ {
+ if (z < zb[x])
+ {
+ int ii = (int)(in);
+
+ r = (r * ii) >> 8;
+ g = (g * ii) >> 8;
+ b = (b * ii) >> 8;
+
+ if (srctrans != 0x1f)
+ {
+ 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;
+ }
+
+ fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff);
+ zb[x] = z;
+ }
+
+ in += inz;
+ z += dz;
+ }
+}
+
+#define TEX_FETCH_NOFILTER() \
+do { \
+ float intz = 1.0f / ooz; \
+ UINT32 u = uoz * intz; \
+ UINT32 v = voz * intz; \
+ UINT32 u1 = (u >> 8) & umask; \
+ UINT32 v1 = (v >> 8) & vmask; \
+ texel = texture->data[(v1 << width) + u1]; \
+} while(0);
+
+#define TEX_FETCH_BILINEAR() \
+do { \
+ float intz = 1.0f / ooz; \
+ UINT32 u = uoz * intz; \
+ UINT32 v = voz * intz; \
+ UINT32 u1 = (u >> 8) & umask; \
+ UINT32 v1 = (v >> 8) & vmask; \
+ UINT32 u2 = (u1 + 1) & umask; \
+ UINT32 v2 = (v1 + 1) & vmask; \
+ UINT32 pix00 = texture->data[(v1 << width) + u1]; \
+ UINT32 pix01 = texture->data[(v1 << width) + u2]; \
+ UINT32 pix10 = texture->data[(v2 << width) + u1]; \
+ UINT32 pix11 = texture->data[(v2 << width) + u2]; \
+ texel = rgba_bilinear_filter(pix00, pix01, pix10, pix11, u, v); \
+} while(0);
+
+#if ENABLE_BILINEAR
+#define TEX_FETCH() TEX_FETCH_BILINEAR()
+#else
+#define TEX_FETCH() TEX_FETCH_NOFILTER()
+#endif
+
+void model3_renderer::draw_scanline_tex(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;
+
+ for (int x = extent.startx; x < extent.stopx; x++)
+ {
+ if (z < zb[x])
+ {
+ UINT32 texel;
+ TEX_FETCH();
+
+ int ii = in;
+
+ UINT32 r = ((texel & 0xff0000) * ii) >> 8;
+ UINT32 g = ((texel & 0xff00) * ii) >> 8;
+ UINT32 b = ((texel & 0xff) * ii) >> 8;
+
+ fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff);
+ zb[x] = z;
+ }
+
+ ooz += dooz;
+ uoz += duoz;
+ voz += dvoz;
+ in += inz;
+ z += dz;
+ }
+}
+
+void model3_renderer::draw_scanline_contour(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;
+
+ for (int x = extent.startx; x < extent.stopx; x++)
+ {
+ if (z < zb[x])
+ {
+ UINT32 texel;
+ TEX_FETCH();
+
+ 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;
+
+ UINT32 orig = fb[x];
+
+ 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);
+ zb[x] = z;
+ }
+ }
+
+ ooz += dooz;
+ uoz += duoz;
+ voz += dvoz;
+ in += inz;
+ z += dz;
+ }
+}
+
+void model3_renderer::draw_scanline_tex_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);
+ 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;
+
+ int srctrans = polydata.transparency;
+ int desttrans = 32 - polydata.transparency;
+
+ 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;
+
+ for (int x = extent.startx; x < extent.stopx; x++)
+ {
+ if (z < zb[x])
+ {
+ UINT32 texel;
+ TEX_FETCH();
+
+ 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;
+
+ UINT32 orig = fb[x];
+
+ r += ((orig & 0x00ff0000) * desttrans) >> 5;
+ g += ((orig & 0x0000ff00) * desttrans) >> 5;
+ b += ((orig & 0x000000ff) * desttrans) >> 5;
+
+ fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff);
+ zb[x] = z;
+ }
+
+ ooz += dooz;
+ uoz += duoz;
+ voz += dvoz;
+ in += inz;
+ z += dz;
+ }
+}
+
+void model3_renderer::draw_scanline_tex_alpha(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;
+
+// int srctrans = polydata.transparency;
+// int desttrans = 32 - polydata.transparency;
+
+ 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;
+
+ for (int x = extent.startx; x < extent.stopx; x++)
+ {
+ if (z < zb[x])
+ {
+ UINT32 texel;
+ TEX_FETCH();
+
+ UINT32 fa = texel >> 24;
+ if (fa != 0)
+ {
+ 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;
+
+ UINT32 orig = fb[x];
+
+ 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);
+ zb[x] = z;
+ }
+ }
+
+ ooz += dooz;
+ uoz += duoz;
+ voz += dvoz;
+ in += inz;
+ z += dz;
+ }
} \ No newline at end of file