Introduce polynew.h which is a modernized C++ version of the old poly.c.

Cleaned up a lot of stuff and made some changes in preparation for the
future. Converted gaelco3d and midvunit over to the new system.
This commit is contained in:
Aaron Giles 2011-11-21 18:23:01 +00:00
parent d6ce6ab824
commit b4a1e04703
7 changed files with 1402 additions and 288 deletions

1
.gitattributes vendored
View File

@ -1332,6 +1332,7 @@ src/emu/video/pc_vga.c svneol=native#text/plain
src/emu/video/pc_vga.h svneol=native#text/plain
src/emu/video/poly.c svneol=native#text/plain
src/emu/video/poly.h svneol=native#text/plain
src/emu/video/polynew.h svneol=native#text/plain
src/emu/video/psx.c svneol=native#text/plain
src/emu/video/psx.h svneol=native#text/plain
src/emu/video/resnet.c svneol=native#text/plain

1121
src/emu/video/polynew.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1217,34 +1217,6 @@ ROM_END
static DRIVER_INIT( gaelco3d )
{
gaelco3d_state *state = machine.driver_data<gaelco3d_state>();
UINT8 *src, *dst;
int x, y;
/* allocate memory */
state->m_texture_size = machine.region("gfx1")->bytes();
state->m_texmask_size = machine.region("gfx2")->bytes() * 8;
state->m_texture = auto_alloc_array(machine, UINT8, state->m_texture_size);
state->m_texmask = auto_alloc_array(machine, UINT8, state->m_texmask_size);
/* first expand the pixel data */
src = machine.region("gfx1")->base();
dst = state->m_texture;
for (y = 0; y < state->m_texture_size/4096; y += 2)
for (x = 0; x < 4096; x += 2)
{
dst[(y + 0) * 4096 + (x + 1)] = src[0*state->m_texture_size/4 + (y/2) * 2048 + (x/2)];
dst[(y + 1) * 4096 + (x + 1)] = src[1*state->m_texture_size/4 + (y/2) * 2048 + (x/2)];
dst[(y + 0) * 4096 + (x + 0)] = src[2*state->m_texture_size/4 + (y/2) * 2048 + (x/2)];
dst[(y + 1) * 4096 + (x + 0)] = src[3*state->m_texture_size/4 + (y/2) * 2048 + (x/2)];
}
/* then expand the mask data */
src = machine.region("gfx2")->base();
dst = state->m_texmask;
for (y = 0; y < state->m_texmask_size/4096; y++)
for (x = 0; x < 4096; x++)
dst[y * 4096 + x] = (src[(x / 1024) * (state->m_texmask_size/8/4) + (y * 1024 + x % 1024) / 8] >> (x % 8)) & 1;
}

View File

@ -7,10 +7,46 @@
**************************************************************************/
#include "sound/dmadac.h"
#include "video/poly.h"
#include "video/polynew.h"
#define SOUND_CHANNELS 4
struct gaelco3d_object_data
{
UINT32 tex, color;
float ooz_dx, ooz_dy, ooz_base;
float uoz_dx, uoz_dy, uoz_base;
float voz_dx, voz_dy, voz_base;
float z0;
};
class gaelco3d_state;
class gaelco3d_renderer : public poly_manager<float, gaelco3d_object_data, 0, 2000>
{
public:
gaelco3d_renderer(gaelco3d_state &state);
bitmap_t *screenbits() const { return m_screenbits; }
UINT32 polygons() { UINT32 result = m_polygons; m_polygons = 0; return result; }
void render_poly(screen_device &screen, UINT32 *polydata);
private:
gaelco3d_state &m_state;
bitmap_t *m_screenbits;
bitmap_t *m_zbuffer;
UINT32 m_polygons;
offs_t m_texture_size;
offs_t m_texmask_size;
UINT8 *m_texture;
UINT8 *m_texmask;
void render_noz_noperspective(INT32 scanline, const extent_t &extent, const gaelco3d_object_data &extra, int threadid);
void render_normal(INT32 scanline, const extent_t &extent, const gaelco3d_object_data &extra, int threadid);
void render_alphablend(INT32 scanline, const extent_t &extent, const gaelco3d_object_data &extra, int threadid);
};
class gaelco3d_state : public driver_device
{
public:
@ -33,19 +69,12 @@ public:
offs_t m_adsp_incs;
offs_t m_adsp_size;
dmadac_sound_device *m_dmadac[SOUND_CHANNELS];
UINT8 *m_texture;
UINT8 *m_texmask;
offs_t m_texture_size;
offs_t m_texmask_size;
bitmap_t *m_screenbits;
bitmap_t *m_zbuffer;
rgb_t *m_palette;
UINT32 *m_polydata_buffer;
UINT32 m_polydata_count;
int m_polygons;
int m_lastscan;
int m_video_changed;
poly_manager *m_poly;
gaelco3d_renderer *m_poly;
};

View File

@ -4,10 +4,36 @@
**************************************************************************/
#include "video/poly.h"
#include "video/polynew.h"
#define MIDVUNIT_VIDEO_CLOCK 33000000
struct midvunit_object_data
{
UINT16 * destbase;
UINT8 * texbase;
UINT16 pixdata;
UINT8 dither;
};
class midvunit_state;
class midvunit_renderer : public poly_manager<float, midvunit_object_data, 2, 4000>
{
public:
midvunit_renderer(midvunit_state &state);
void process_dma_queue();
void make_vertices_inclusive(vertex_t *vert);
private:
midvunit_state &m_state;
void render_flat(INT32 scanline, const extent_t &extent, const midvunit_object_data &extradata, int threadid);
void render_tex(INT32 scanline, const extent_t &extent, const midvunit_object_data &extradata, int threadid);
void render_textrans(INT32 scanline, const extent_t &extent, const midvunit_object_data &extradata, int threadid);
void render_textransmask(INT32 scanline, const extent_t &extent, const midvunit_object_data &extradata, int threadid);
};
class midvunit_state : public driver_device
{
public:
@ -39,7 +65,7 @@ public:
UINT16 m_page_control;
UINT8 m_video_changed;
emu_timer *m_scanline_timer;
poly_manager *m_poly;
midvunit_renderer *m_poly;
};

View File

@ -24,23 +24,39 @@
#define IS_POLYEND(x) (((x) ^ ((x) >> 1)) & 0x4000)
struct poly_extra_data
gaelco3d_renderer::gaelco3d_renderer(gaelco3d_state &state)
: poly_manager(state.machine()),
m_state(state),
m_screenbits(machine().primary_screen->alloc_compatible_bitmap()),
m_zbuffer(auto_bitmap_alloc(state.machine(), state.machine().primary_screen->width(), state.machine().primary_screen->height(), BITMAP_FORMAT_INDEXED16)),
m_polygons(0),
m_texture_size(state.machine().region("gfx1")->bytes()),
m_texmask_size(state.machine().region("gfx2")->bytes() * 8),
m_texture(auto_alloc_array(state.machine(), UINT8, m_texture_size)),
m_texmask(auto_alloc_array(state.machine(), UINT8, m_texmask_size))
{
running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
state_save_register_global_bitmap(state.machine(), m_screenbits);
state_save_register_global_bitmap(state.machine(), m_zbuffer);
running_machine *m_machine;
UINT32 tex, color;
float ooz_dx, ooz_dy, ooz_base;
float uoz_dx, uoz_dy, uoz_base;
float voz_dx, voz_dy, voz_base;
float z0;
};
static void render_noz_noperspective(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
static void render_normal(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
static void render_alphablend(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
/* first expand the pixel data */
UINT8 *src = state.machine().region("gfx1")->base();
UINT8 *dst = m_texture;
for (int y = 0; y < m_texture_size/4096; y += 2)
for (int x = 0; x < 4096; x += 2)
{
dst[(y + 0) * 4096 + (x + 1)] = src[0*m_texture_size/4 + (y/2) * 2048 + (x/2)];
dst[(y + 1) * 4096 + (x + 1)] = src[1*m_texture_size/4 + (y/2) * 2048 + (x/2)];
dst[(y + 0) * 4096 + (x + 0)] = src[2*m_texture_size/4 + (y/2) * 2048 + (x/2)];
dst[(y + 1) * 4096 + (x + 0)] = src[3*m_texture_size/4 + (y/2) * 2048 + (x/2)];
}
/* then expand the mask data */
src = state.machine().region("gfx2")->base();
dst = m_texmask;
for (int y = 0; y < m_texmask_size/4096; y++)
for (int x = 0; x < 4096; x++)
dst[y * 4096 + x] = (src[(x / 1024) * (m_texmask_size/8/4) + (y * 1024 + x % 1024) / 8] >> (x % 8)) & 1;
}
/*************************************
@ -49,26 +65,11 @@ static void render_alphablend(void *dest, INT32 scanline, const poly_extent *ext
*
*************************************/
static void gaelco3d_exit(running_machine &machine)
{
gaelco3d_state *state = machine.driver_data<gaelco3d_state>();
poly_free(state->m_poly);
}
VIDEO_START( gaelco3d )
{
gaelco3d_state *state = machine.driver_data<gaelco3d_state>();
int width, height;
state->m_poly = poly_alloc(machine, 2000, sizeof(poly_extra_data), 0);
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(gaelco3d_exit), &machine));
state->m_screenbits = machine.primary_screen->alloc_compatible_bitmap();
width = machine.primary_screen->width();
height = machine.primary_screen->height();
state->m_zbuffer = auto_bitmap_alloc(machine, width, height, BITMAP_FORMAT_INDEXED16);
state->m_poly = auto_alloc(machine, gaelco3d_renderer(*state));
state->m_palette = auto_alloc_array(machine, rgb_t, 32768);
state->m_polydata_buffer = auto_alloc_array(machine, UINT32, MAX_POLYDATA);
@ -79,11 +80,7 @@ VIDEO_START( gaelco3d )
state_save_register_global_pointer(machine, state->m_polydata_buffer, MAX_POLYDATA);
state_save_register_global(machine, state->m_polydata_count);
state_save_register_global(machine, state->m_polygons);
state_save_register_global(machine, state->m_lastscan);
state_save_register_global_bitmap(machine, state->m_screenbits);
state_save_register_global_bitmap(machine, state->m_zbuffer);
}
@ -115,9 +112,8 @@ VIDEO_START( gaelco3d )
(repeat these two for each additional point in the fan)
*/
static void render_poly(screen_device &screen, UINT32 *polydata)
void gaelco3d_renderer::render_poly(screen_device &screen, UINT32 *polydata)
{
gaelco3d_state *state = screen.machine().driver_data<gaelco3d_state>();
float midx = screen.width() / 2;
float midy = screen.height() / 2;
float z0 = tms3203x_device::fp_to_float(polydata[0]);
@ -130,9 +126,9 @@ static void render_poly(screen_device &screen, UINT32 *polydata)
float voz_base = tms3203x_device::fp_to_float(polydata[7]) * 256.0f - midx * voz_dx - midy * voz_dy;
float ooz_base = tms3203x_device::fp_to_float(polydata[8]) - midx * ooz_dx - midy * ooz_dy;
float uoz_base = tms3203x_device::fp_to_float(polydata[9]) * 256.0f - midx * uoz_dx - midy * uoz_dy;
poly_extra_data *extra = (poly_extra_data *)poly_get_extra_data(state->m_poly);
gaelco3d_object_data &object = object_data_alloc();
int color = (polydata[10] & 0x7f) << 8;
poly_vertex vert[MAX_VERTICES];
vertex_t vert[MAX_VERTICES];
UINT32 data;
int vertnum;
@ -160,20 +156,19 @@ static void render_poly(screen_device &screen, UINT32 *polydata)
logerror("\n");
}
/* fill in extra data */
extra->m_machine = &screen.machine();
extra->tex = polydata[11];
extra->color = color;
extra->ooz_dx = ooz_dx;
extra->ooz_dy = ooz_dy;
extra->ooz_base = ooz_base;
extra->uoz_dx = uoz_dx;
extra->uoz_dy = uoz_dy;
extra->uoz_base = uoz_base;
extra->voz_dx = voz_dx;
extra->voz_dy = voz_dy;
extra->voz_base = voz_base;
extra->z0 = z0;
/* fill in object data */
object.tex = polydata[11];
object.color = color;
object.ooz_dx = ooz_dx;
object.ooz_dy = ooz_dy;
object.ooz_base = ooz_base;
object.uoz_dx = uoz_dx;
object.uoz_dy = uoz_dy;
object.uoz_base = uoz_base;
object.voz_dx = voz_dx;
object.voz_dy = voz_dy;
object.voz_base = voz_base;
object.z0 = z0;
/* extract vertices */
data = 0;
@ -192,52 +187,49 @@ static void render_poly(screen_device &screen, UINT32 *polydata)
/* special case: no Z buffering and no perspective correction */
if (color != 0x7f00 && z0 < 0 && ooz_dx == 0 && ooz_dy == 0)
poly_render_triangle_fan(state->m_poly, state->m_screenbits, &visarea, render_noz_noperspective, 0, vertnum, &vert[0]);
render_triangle_fan(visarea, render_delegate(FUNC(gaelco3d_renderer::render_noz_noperspective), this), 0, vertnum, &vert[0]);
/* general case: non-alpha blended */
else if (color != 0x7f00)
poly_render_triangle_fan(state->m_poly, state->m_screenbits, &visarea, render_normal, 0, vertnum, &vert[0]);
render_triangle_fan(visarea, render_delegate(FUNC(gaelco3d_renderer::render_normal), this), 0, vertnum, &vert[0]);
/* color 0x7f seems to be hard-coded as a 50% alpha blend */
else
poly_render_triangle_fan(state->m_poly, state->m_screenbits, &visarea, render_alphablend, 0, vertnum, &vert[0]);
render_triangle_fan(visarea, render_delegate(FUNC(gaelco3d_renderer::render_alphablend), this), 0, vertnum, &vert[0]);
state->m_polygons += vertnum - 2;
m_polygons += vertnum - 2;
}
}
static void render_noz_noperspective(void *destbase, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
void gaelco3d_renderer::render_noz_noperspective(INT32 scanline, const extent_t &extent, const gaelco3d_object_data &object, int threadid)
{
const poly_extra_data *extra = (const poly_extra_data *)extradata;
gaelco3d_state *state = extra->machine().driver_data<gaelco3d_state>();
bitmap_t *bitmap = (bitmap_t *)destbase;
float zbase = recip_approx(extra->ooz_base);
float uoz_step = extra->uoz_dx * zbase;
float voz_step = extra->voz_dx * zbase;
int zbufval = (int)(-extra->z0 * zbase);
offs_t endmask = state->m_texture_size - 1;
const rgb_t *palsource = state->m_palette + extra->color;
UINT32 tex = extra->tex;
UINT16 *dest = BITMAP_ADDR16(bitmap, scanline, 0);
UINT16 *zbuf = BITMAP_ADDR16(state->m_zbuffer, scanline, 0);
int startx = extent->startx;
float uoz = (extra->uoz_base + scanline * extra->uoz_dy + startx * extra->uoz_dx) * zbase;
float voz = (extra->voz_base + scanline * extra->voz_dy + startx * extra->voz_dx) * zbase;
float zbase = recip_approx(object.ooz_base);
float uoz_step = object.uoz_dx * zbase;
float voz_step = object.voz_dx * zbase;
int zbufval = (int)(-object.z0 * zbase);
offs_t endmask = m_texture_size - 1;
const rgb_t *palsource = m_state.m_palette + object.color;
UINT32 tex = object.tex;
UINT16 *dest = BITMAP_ADDR16(m_screenbits, scanline, 0);
UINT16 *zbuf = BITMAP_ADDR16(m_zbuffer, scanline, 0);
int startx = extent.startx;
float uoz = (object.uoz_base + scanline * object.uoz_dy + startx * object.uoz_dx) * zbase;
float voz = (object.voz_base + scanline * object.voz_dy + startx * object.voz_dx) * zbase;
int x;
for (x = startx; x < extent->stopx; x++)
for (x = startx; x < extent.stopx; x++)
{
int u = (int)uoz;
int v = (int)voz;
int pixeloffs = (tex + (v >> 8) * 4096 + (u >> 8)) & endmask;
if (pixeloffs >= state->m_texmask_size || !state->m_texmask[pixeloffs])
if (pixeloffs >= m_texmask_size || !m_texmask[pixeloffs])
{
rgb_t rgb00 = palsource[state->m_texture[pixeloffs]];
rgb_t rgb01 = palsource[state->m_texture[(pixeloffs + 1) & endmask]];
rgb_t rgb10 = palsource[state->m_texture[(pixeloffs + 4096) & endmask]];
rgb_t rgb11 = palsource[state->m_texture[(pixeloffs + 4097) & endmask]];
rgb_t rgb00 = palsource[m_texture[pixeloffs]];
rgb_t rgb01 = palsource[m_texture[(pixeloffs + 1) & endmask]];
rgb_t rgb10 = palsource[m_texture[(pixeloffs + 4096) & endmask]];
rgb_t rgb11 = palsource[m_texture[(pixeloffs + 4097) & endmask]];
rgb_t filtered = rgb_bilinear_filter(rgb00, rgb01, rgb10, rgb11, u, v);
dest[x] = (filtered & 0x1f) | ((filtered & 0x1ff800) >> 6);
zbuf[x] = zbufval;
@ -250,27 +242,24 @@ static void render_noz_noperspective(void *destbase, INT32 scanline, const poly_
}
static void render_normal(void *destbase, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
void gaelco3d_renderer::render_normal(INT32 scanline, const extent_t &extent, const gaelco3d_object_data &object, int threadid)
{
const poly_extra_data *extra = (const poly_extra_data *)extradata;
gaelco3d_state *state = extra->machine().driver_data<gaelco3d_state>();
bitmap_t *bitmap = (bitmap_t *)destbase;
float ooz_dx = extra->ooz_dx;
float uoz_dx = extra->uoz_dx;
float voz_dx = extra->voz_dx;
offs_t endmask = state->m_texture_size - 1;
const rgb_t *palsource = state->m_palette + extra->color;
UINT32 tex = extra->tex;
float z0 = extra->z0;
UINT16 *dest = BITMAP_ADDR16(bitmap, scanline, 0);
UINT16 *zbuf = BITMAP_ADDR16(state->m_zbuffer, scanline, 0);
int startx = extent->startx;
float ooz = extra->ooz_base + scanline * extra->ooz_dy + startx * ooz_dx;
float uoz = extra->uoz_base + scanline * extra->uoz_dy + startx * uoz_dx;
float voz = extra->voz_base + scanline * extra->voz_dy + startx * voz_dx;
float ooz_dx = object.ooz_dx;
float uoz_dx = object.uoz_dx;
float voz_dx = object.voz_dx;
offs_t endmask = m_texture_size - 1;
const rgb_t *palsource = m_state.m_palette + object.color;
UINT32 tex = object.tex;
float z0 = object.z0;
UINT16 *dest = BITMAP_ADDR16(m_screenbits, scanline, 0);
UINT16 *zbuf = BITMAP_ADDR16(m_zbuffer, scanline, 0);
int startx = extent.startx;
float ooz = object.ooz_base + scanline * object.ooz_dy + startx * ooz_dx;
float uoz = object.uoz_base + scanline * object.uoz_dy + startx * uoz_dx;
float voz = object.voz_base + scanline * object.voz_dy + startx * voz_dx;
int x;
for (x = startx; x < extent->stopx; x++)
for (x = startx; x < extent.stopx; x++)
{
if (ooz > 0)
{
@ -282,12 +271,12 @@ static void render_normal(void *destbase, INT32 scanline, const poly_extent *ext
int u = (int)(uoz * z);
int v = (int)(voz * z);
int pixeloffs = (tex + (v >> 8) * 4096 + (u >> 8)) & endmask;
if (pixeloffs >= state->m_texmask_size || !state->m_texmask[pixeloffs])
if (pixeloffs >= m_texmask_size || !m_texmask[pixeloffs])
{
rgb_t rgb00 = palsource[state->m_texture[pixeloffs]];
rgb_t rgb01 = palsource[state->m_texture[(pixeloffs + 1) & endmask]];
rgb_t rgb10 = palsource[state->m_texture[(pixeloffs + 4096) & endmask]];
rgb_t rgb11 = palsource[state->m_texture[(pixeloffs + 4097) & endmask]];
rgb_t rgb00 = palsource[m_texture[pixeloffs]];
rgb_t rgb01 = palsource[m_texture[(pixeloffs + 1) & endmask]];
rgb_t rgb10 = palsource[m_texture[(pixeloffs + 4096) & endmask]];
rgb_t rgb11 = palsource[m_texture[(pixeloffs + 4097) & endmask]];
rgb_t filtered = rgb_bilinear_filter(rgb00, rgb01, rgb10, rgb11, u, v);
dest[x] = (filtered & 0x1f) | ((filtered & 0x1ff800) >> 6);
zbuf[x] = (zbufval < 0) ? -zbufval : zbufval;
@ -303,27 +292,24 @@ static void render_normal(void *destbase, INT32 scanline, const poly_extent *ext
}
static void render_alphablend(void *destbase, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
void gaelco3d_renderer::render_alphablend(INT32 scanline, const extent_t &extent, const gaelco3d_object_data &object, int threadid)
{
const poly_extra_data *extra = (const poly_extra_data *)extradata;
gaelco3d_state *state = extra->machine().driver_data<gaelco3d_state>();
bitmap_t *bitmap = (bitmap_t *)destbase;
float ooz_dx = extra->ooz_dx;
float uoz_dx = extra->uoz_dx;
float voz_dx = extra->voz_dx;
offs_t endmask = state->m_texture_size - 1;
const rgb_t *palsource = state->m_palette + extra->color;
UINT32 tex = extra->tex;
float z0 = extra->z0;
UINT16 *dest = BITMAP_ADDR16(bitmap, scanline, 0);
UINT16 *zbuf = BITMAP_ADDR16(state->m_zbuffer, scanline, 0);
int startx = extent->startx;
float ooz = extra->ooz_base + extra->ooz_dy * scanline + startx * ooz_dx;
float uoz = extra->uoz_base + extra->uoz_dy * scanline + startx * uoz_dx;
float voz = extra->voz_base + extra->voz_dy * scanline + startx * voz_dx;
float ooz_dx = object.ooz_dx;
float uoz_dx = object.uoz_dx;
float voz_dx = object.voz_dx;
offs_t endmask = m_texture_size - 1;
const rgb_t *palsource = m_state.m_palette + object.color;
UINT32 tex = object.tex;
float z0 = object.z0;
UINT16 *dest = BITMAP_ADDR16(m_screenbits, scanline, 0);
UINT16 *zbuf = BITMAP_ADDR16(m_zbuffer, scanline, 0);
int startx = extent.startx;
float ooz = object.ooz_base + object.ooz_dy * scanline + startx * ooz_dx;
float uoz = object.uoz_base + object.uoz_dy * scanline + startx * uoz_dx;
float voz = object.voz_base + object.voz_dy * scanline + startx * voz_dx;
int x;
for (x = startx; x < extent->stopx; x++)
for (x = startx; x < extent.stopx; x++)
{
if (ooz > 0)
{
@ -335,12 +321,12 @@ static void render_alphablend(void *destbase, INT32 scanline, const poly_extent
int u = (int)(uoz * z);
int v = (int)(voz * z);
int pixeloffs = (tex + (v >> 8) * 4096 + (u >> 8)) & endmask;
if (pixeloffs >= state->m_texmask_size || !state->m_texmask[pixeloffs])
if (pixeloffs >= m_texmask_size || !m_texmask[pixeloffs])
{
rgb_t rgb00 = palsource[state->m_texture[pixeloffs]];
rgb_t rgb01 = palsource[state->m_texture[(pixeloffs + 1) & endmask]];
rgb_t rgb10 = palsource[state->m_texture[(pixeloffs + 4096) & endmask]];
rgb_t rgb11 = palsource[state->m_texture[(pixeloffs + 4097) & endmask]];
rgb_t rgb00 = palsource[m_texture[pixeloffs]];
rgb_t rgb01 = palsource[m_texture[(pixeloffs + 1) & endmask]];
rgb_t rgb10 = palsource[m_texture[(pixeloffs + 4096) & endmask]];
rgb_t rgb11 = palsource[m_texture[(pixeloffs + 4097) & endmask]];
rgb_t filtered = rgb_bilinear_filter(rgb00, rgb01, rgb10, rgb11, u, v) >> 1;
dest[x] = ((filtered & 0x0f) | ((filtered & 0x0f7800) >> 6)) + ((dest[x] >> 1) & 0x3def);
zbuf[x] = (zbufval < 0) ? -zbufval : zbufval;
@ -366,17 +352,16 @@ void gaelco3d_render(screen_device &screen)
{
gaelco3d_state *state = screen.machine().driver_data<gaelco3d_state>();
/* wait for any queued stuff to complete */
poly_wait(state->m_poly, "Time to render");
state->m_poly->wait("Time to render");
#if DISPLAY_STATS
{
int scan = screen.vpos();
popmessage("Polys = %4d Timeleft = %3d", state->m_polygons, (state->m_lastscan < scan) ? (scan - state->m_lastscan) : (scan + (state->m_lastscan - screen.visible_area().max_y)));
popmessage("Polys = %4d Timeleft = %3d", state->m_poly->polygons(), (state->m_lastscan < scan) ? (scan - state->m_lastscan) : (scan + (state->m_lastscan - screen.visible_area().max_y)));
}
#endif
state->m_polydata_count = 0;
state->m_polygons = 0;
state->m_lastscan = -1;
}
@ -401,7 +386,7 @@ WRITE32_HANDLER( gaelco3d_render_w )
{
if (state->m_polydata_count >= 18 && (state->m_polydata_count % 2) == 1 && IS_POLYEND(state->m_polydata_buffer[state->m_polydata_count - 2]))
{
render_poly(*space->machine().primary_screen, &state->m_polydata_buffer[0]);
state->m_poly->render_poly(*space->machine().primary_screen, &state->m_polydata_buffer[0]);
state->m_polydata_count = 0;
}
state->m_video_changed = TRUE;
@ -423,7 +408,7 @@ WRITE32_HANDLER( gaelco3d_render_w )
WRITE16_HANDLER( gaelco3d_paletteram_w )
{
gaelco3d_state *state = space->machine().driver_data<gaelco3d_state>();
poly_wait(state->m_poly, "Palette change");
state->m_poly->wait("Palette change");
COMBINE_DATA(&space->machine().generic.paletteram.u16[offset]);
state->m_palette[offset] = ((space->machine().generic.paletteram.u16[offset] & 0x7fe0) << 6) | (space->machine().generic.paletteram.u16[offset] & 0x1f);
}
@ -432,7 +417,7 @@ WRITE16_HANDLER( gaelco3d_paletteram_w )
WRITE32_HANDLER( gaelco3d_paletteram_020_w )
{
gaelco3d_state *state = space->machine().driver_data<gaelco3d_state>();
poly_wait(state->m_poly, "Palette change");
state->m_poly->wait("Palette change");
COMBINE_DATA(&space->machine().generic.paletteram.u32[offset]);
state->m_palette[offset*2+0] = ((space->machine().generic.paletteram.u32[offset] & 0x7fe00000) >> 10) | ((space->machine().generic.paletteram.u32[offset] & 0x1f0000) >> 16);
state->m_palette[offset*2+1] = ((space->machine().generic.paletteram.u32[offset] & 0x7fe0) << 6) | (space->machine().generic.paletteram.u32[offset] & 0x1f);
@ -449,8 +434,9 @@ WRITE32_HANDLER( gaelco3d_paletteram_020_w )
SCREEN_UPDATE( gaelco3d )
{
gaelco3d_state *state = screen->machine().driver_data<gaelco3d_state>();
int x, y, ret;
int ret;
/*
if (DISPLAY_TEXTURE && (screen->machine().input().code_pressed(KEYCODE_Z) || screen->machine().input().code_pressed(KEYCODE_X)))
{
static int xv = 0, yv = 0x1000;
@ -487,10 +473,10 @@ SCREEN_UPDATE( gaelco3d )
}
popmessage("(%04X,%04X)", xv, yv);
}
else
else*/
{
if (state->m_video_changed)
copybitmap(bitmap, state->m_screenbits, 0,1, 0,0, cliprect);
copybitmap(bitmap, state->m_poly->screenbits(), 0,1, 0,0, cliprect);
ret = state->m_video_changed;
state->m_video_changed = FALSE;
}

View File

@ -8,7 +8,6 @@
#include "cpu/tms34010/tms34010.h"
#include "cpu/adsp2100/adsp2100.h"
#include "audio/williams.h"
#include "video/poly.h"
#include "includes/midvunit.h"
@ -24,14 +23,9 @@
#define TIME_PER_PIXEL 41e-9
typedef struct _poly_extra_data poly_extra_data;
struct _poly_extra_data
{
UINT8 * texbase;
UINT16 pixdata;
UINT8 dither;
};
midvunit_renderer::midvunit_renderer(midvunit_state &state)
: poly_manager(state.machine()),
m_state(state) { }
/*************************************
@ -56,19 +50,12 @@ static TIMER_CALLBACK( scanline_timer_cb )
}
static void midvunit_exit(running_machine &machine)
{
midvunit_state *state = machine.driver_data<midvunit_state>();
poly_free(state->m_poly);
}
VIDEO_START( midvunit )
{
midvunit_state *state = machine.driver_data<midvunit_state>();
state->m_scanline_timer = machine.scheduler().timer_alloc(FUNC(scanline_timer_cb));
state->m_poly = poly_alloc(machine, 4000, sizeof(poly_extra_data), POLYFLAG_ALLOW_QUADS);
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(midvunit_exit), &machine));
state->m_poly = auto_alloc(machine, midvunit_renderer(*state));
state_save_register_global_array(machine, state->m_video_regs);
state_save_register_global_array(machine, state->m_dma_data);
@ -85,26 +72,25 @@ VIDEO_START( midvunit )
*
*************************************/
static void render_flat(void *destbase, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
void midvunit_renderer::render_flat(INT32 scanline, const extent_t &extent, const midvunit_object_data &objectdata, int threadid)
{
const poly_extra_data *extra = (const poly_extra_data *)extradata;
UINT16 pixdata = extra->pixdata;
int xstep = extra->dither + 1;
UINT16 *dest = (UINT16 *)destbase + scanline * 512;
int startx = extent->startx;
UINT16 pixdata = objectdata.pixdata;
int xstep = objectdata.dither + 1;
UINT16 *dest = objectdata.destbase + scanline * 512;
int startx = extent.startx;
int x;
/* if dithering, ensure that we start on an appropriate pixel */
startx += (scanline ^ startx) & extra->dither;
startx += (scanline ^ startx) & objectdata.dither;
/* non-dithered 0 pixels can use a memset */
if (pixdata == 0 && xstep == 1)
memset(&dest[startx], 0, 2 * (extent->stopx - startx + 1));
memset(&dest[startx], 0, 2 * (extent.stopx - startx + 1));
/* otherwise, we fill manually */
else
{
for (x = startx; x < extent->stopx; x += xstep)
for (x = startx; x < extent.stopx; x += xstep)
dest[x] = pixdata;
}
}
@ -117,19 +103,18 @@ static void render_flat(void *destbase, INT32 scanline, const poly_extent *exten
*
*************************************/
static void render_tex(void *destbase, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
void midvunit_renderer::render_tex(INT32 scanline, const extent_t &extent, const midvunit_object_data &objectdata, int threadid)
{
const poly_extra_data *extra = (const poly_extra_data *)extradata;
UINT16 pixdata = extra->pixdata & 0xff00;
const UINT8 *texbase = extra->texbase;
int xstep = extra->dither + 1;
UINT16 *dest = (UINT16 *)destbase + scanline * 512;
int startx = extent->startx;
int stopx = extent->stopx;
INT32 u = extent->param[0].start;
INT32 v = extent->param[1].start;
INT32 dudx = extent->param[0].dpdx;
INT32 dvdx = extent->param[1].dpdx;
UINT16 pixdata = objectdata.pixdata & 0xff00;
const UINT8 *texbase = objectdata.texbase;
int xstep = objectdata.dither + 1;
UINT16 *dest = objectdata.destbase + scanline * 512;
int startx = extent.startx;
int stopx = extent.stopx;
INT32 u = extent.param[0].start;
INT32 v = extent.param[1].start;
INT32 dudx = extent.param[0].dpdx;
INT32 dvdx = extent.param[1].dpdx;
int x;
/* if dithering, we advance by 2x; also ensure that we start on an appropriate pixel */
@ -155,19 +140,18 @@ static void render_tex(void *destbase, INT32 scanline, const poly_extent *extent
}
static void render_textrans(void *destbase, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
void midvunit_renderer::render_textrans(INT32 scanline, const extent_t &extent, const midvunit_object_data &objectdata, int threadid)
{
const poly_extra_data *extra = (const poly_extra_data *)extradata;
UINT16 pixdata = extra->pixdata & 0xff00;
const UINT8 *texbase = extra->texbase;
int xstep = extra->dither + 1;
UINT16 *dest = (UINT16 *)destbase + scanline * 512;
int startx = extent->startx;
int stopx = extent->stopx;
INT32 u = extent->param[0].start;
INT32 v = extent->param[1].start;
INT32 dudx = extent->param[0].dpdx;
INT32 dvdx = extent->param[1].dpdx;
UINT16 pixdata = objectdata.pixdata & 0xff00;
const UINT8 *texbase = objectdata.texbase;
int xstep = objectdata.dither + 1;
UINT16 *dest = objectdata.destbase + scanline * 512;
int startx = extent.startx;
int stopx = extent.stopx;
INT32 u = extent.param[0].start;
INT32 v = extent.param[1].start;
INT32 dudx = extent.param[0].dpdx;
INT32 dvdx = extent.param[1].dpdx;
int x;
/* if dithering, we advance by 2x; also ensure that we start on an appropriate pixel */
@ -195,19 +179,18 @@ static void render_textrans(void *destbase, INT32 scanline, const poly_extent *e
}
static void render_textransmask(void *destbase, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
void midvunit_renderer::render_textransmask(INT32 scanline, const extent_t &extent, const midvunit_object_data &objectdata, int threadid)
{
const poly_extra_data *extra = (const poly_extra_data *)extradata;
UINT16 pixdata = extra->pixdata;
const UINT8 *texbase = extra->texbase;
int xstep = extra->dither + 1;
UINT16 *dest = (UINT16 *)destbase + scanline * 512;
int startx = extent->startx;
int stopx = extent->stopx;
INT32 u = extent->param[0].start;
INT32 v = extent->param[1].start;
INT32 dudx = extent->param[0].dpdx;
INT32 dvdx = extent->param[1].dpdx;
UINT16 pixdata = objectdata.pixdata;
const UINT8 *texbase = objectdata.texbase;
int xstep = objectdata.dither + 1;
UINT16 *dest = objectdata.destbase + scanline * 512;
int startx = extent.startx;
int stopx = extent.stopx;
INT32 u = extent.param[0].start;
INT32 v = extent.param[1].start;
INT32 dudx = extent.param[0].dpdx;
INT32 dvdx = extent.param[1].dpdx;
int x;
/* if dithering, we advance by 2x; also ensure that we start on an appropriate pixel */
@ -242,17 +225,15 @@ static void render_textransmask(void *destbase, INT32 scanline, const poly_exten
*
*************************************/
static void make_vertices_inclusive(poly_vertex *vert)
void midvunit_renderer::make_vertices_inclusive(vertex_t *vert)
{
UINT8 rmask = 0, bmask = 0, eqmask = 0;
int vnum;
/* build up a mask of right and bottom points */
/* note we assume clockwise orientation here */
for (vnum = 0; vnum < 4; vnum++)
UINT8 rmask = 0, bmask = 0, eqmask = 0;
for (int vnum = 0; vnum < 4; vnum++)
{
poly_vertex *currv = &vert[vnum];
poly_vertex *nextv = &vert[(vnum + 1) & 3];
vertex_t *currv = &vert[vnum];
vertex_t *nextv = &vert[(vnum + 1) & 3];
/* if this vertex equals the next one, tag it */
if (nextv->y == currv->y && nextv->x == currv->x)
@ -272,9 +253,9 @@ static void make_vertices_inclusive(poly_vertex *vert)
return;
/* adjust the right/bottom points so that they get included */
for (vnum = 0; vnum < 4; vnum++)
for (int vnum = 0; vnum < 4; vnum++)
{
poly_vertex *currv = &vert[vnum];
vertex_t *currv = &vert[vnum];
int effvnum = vnum;
/* if we're equal to the next vertex, use that instead */
@ -290,73 +271,71 @@ static void make_vertices_inclusive(poly_vertex *vert)
}
static void process_dma_queue(running_machine &machine)
void midvunit_renderer::process_dma_queue()
{
midvunit_state *state = machine.driver_data<midvunit_state>();
poly_extra_data *extra = (poly_extra_data *)poly_get_extra_data(state->m_poly);
UINT16 *dest = &state->m_videoram[(state->m_page_control & 4) ? 0x40000 : 0x00000];
int textured = ((state->m_dma_data[0] & 0x300) == 0x100);
poly_draw_scanline_func callback;
poly_vertex vert[4];
/* if we're rendering to the same page we're viewing, it has changed */
if ((((state->m_page_control >> 2) ^ state->m_page_control) & 1) == 0 || WATCH_RENDER)
state->m_video_changed = TRUE;
if ((((m_state.m_page_control >> 2) ^ m_state.m_page_control) & 1) == 0 || WATCH_RENDER)
m_state.m_video_changed = TRUE;
/* fill in the vertex data */
vert[0].x = (float)(INT16)state->m_dma_data[2] + 0.5f;
vert[0].y = (float)(INT16)state->m_dma_data[3] + 0.5f;
vert[1].x = (float)(INT16)state->m_dma_data[4] + 0.5f;
vert[1].y = (float)(INT16)state->m_dma_data[5] + 0.5f;
vert[2].x = (float)(INT16)state->m_dma_data[6] + 0.5f;
vert[2].y = (float)(INT16)state->m_dma_data[7] + 0.5f;
vert[3].x = (float)(INT16)state->m_dma_data[8] + 0.5f;
vert[3].y = (float)(INT16)state->m_dma_data[9] + 0.5f;
vertex_t vert[4];
vert[0].x = (float)(INT16)m_state.m_dma_data[2] + 0.5f;
vert[0].y = (float)(INT16)m_state.m_dma_data[3] + 0.5f;
vert[1].x = (float)(INT16)m_state.m_dma_data[4] + 0.5f;
vert[1].y = (float)(INT16)m_state.m_dma_data[5] + 0.5f;
vert[2].x = (float)(INT16)m_state.m_dma_data[6] + 0.5f;
vert[2].y = (float)(INT16)m_state.m_dma_data[7] + 0.5f;
vert[3].x = (float)(INT16)m_state.m_dma_data[8] + 0.5f;
vert[3].y = (float)(INT16)m_state.m_dma_data[9] + 0.5f;
/* make the vertices inclusive of right/bottom points */
make_vertices_inclusive(vert);
/* handle flat-shaded quads here */
render_delegate callback;
bool textured = ((m_state.m_dma_data[0] & 0x300) == 0x100);
if (!textured)
callback = render_flat;
callback = render_delegate(FUNC(midvunit_renderer::render_flat), this);
/* handle textured quads here */
else
{
/* if textured, add the texture info */
vert[0].p[0] = (float)(state->m_dma_data[10] & 0xff) * 65536.0f + 32768.0f;
vert[0].p[1] = (float)(state->m_dma_data[10] >> 8) * 65536.0f + 32768.0f;
vert[1].p[0] = (float)(state->m_dma_data[11] & 0xff) * 65536.0f + 32768.0f;
vert[1].p[1] = (float)(state->m_dma_data[11] >> 8) * 65536.0f + 32768.0f;
vert[2].p[0] = (float)(state->m_dma_data[12] & 0xff) * 65536.0f + 32768.0f;
vert[2].p[1] = (float)(state->m_dma_data[12] >> 8) * 65536.0f + 32768.0f;
vert[3].p[0] = (float)(state->m_dma_data[13] & 0xff) * 65536.0f + 32768.0f;
vert[3].p[1] = (float)(state->m_dma_data[13] >> 8) * 65536.0f + 32768.0f;
vert[0].p[0] = (float)(m_state.m_dma_data[10] & 0xff) * 65536.0f + 32768.0f;
vert[0].p[1] = (float)(m_state.m_dma_data[10] >> 8) * 65536.0f + 32768.0f;
vert[1].p[0] = (float)(m_state.m_dma_data[11] & 0xff) * 65536.0f + 32768.0f;
vert[1].p[1] = (float)(m_state.m_dma_data[11] >> 8) * 65536.0f + 32768.0f;
vert[2].p[0] = (float)(m_state.m_dma_data[12] & 0xff) * 65536.0f + 32768.0f;
vert[2].p[1] = (float)(m_state.m_dma_data[12] >> 8) * 65536.0f + 32768.0f;
vert[3].p[0] = (float)(m_state.m_dma_data[13] & 0xff) * 65536.0f + 32768.0f;
vert[3].p[1] = (float)(m_state.m_dma_data[13] >> 8) * 65536.0f + 32768.0f;
/* handle non-masked, non-transparent quads */
if ((state->m_dma_data[0] & 0xc00) == 0x000)
callback = render_tex;
if ((m_state.m_dma_data[0] & 0xc00) == 0x000)
callback = render_delegate(FUNC(midvunit_renderer::render_tex), this);
/* handle non-masked, transparent quads */
else if ((state->m_dma_data[0] & 0xc00) == 0x800)
callback = render_textrans;
else if ((m_state.m_dma_data[0] & 0xc00) == 0x800)
callback = render_delegate(FUNC(midvunit_renderer::render_textrans), this);
/* handle masked, transparent quads */
else if ((state->m_dma_data[0] & 0xc00) == 0xc00)
callback = render_textransmask;
else if ((m_state.m_dma_data[0] & 0xc00) == 0xc00)
callback = render_delegate(FUNC(midvunit_renderer::render_textransmask), this);
/* handle masked, non-transparent quads */
else
callback = render_flat;
callback = render_delegate(FUNC(midvunit_renderer::render_flat), this);
}
/* set up the extra data for this triangle */
extra->texbase = (UINT8 *)state->m_textureram + (state->m_dma_data[14] * 256);
extra->pixdata = state->m_dma_data[1] | (state->m_dma_data[0] & 0x00ff);
extra->dither = ((state->m_dma_data[0] & 0x2000) != 0);
/* set up the object data for this triangle */
midvunit_object_data &objectdata = object_data_alloc();
objectdata.destbase = &m_state.m_videoram[(m_state.m_page_control & 4) ? 0x40000 : 0x00000];
objectdata.texbase = (UINT8 *)m_state.m_textureram + (m_state.m_dma_data[14] * 256);
objectdata.pixdata = m_state.m_dma_data[1] | (m_state.m_dma_data[0] & 0x00ff);
objectdata.dither = ((m_state.m_dma_data[0] & 0x2000) != 0);
/* render as a quad */
poly_render_quad(state->m_poly, dest, &machine.primary_screen->visible_area(), callback, textured ? 2 : 0, &vert[0], &vert[1], &vert[2], &vert[3]);
render_polygon<4>(machine().primary_screen->visible_area(), callback, textured ? 2 : 0, vert);
}
@ -391,7 +370,7 @@ READ32_HANDLER( midvunit_dma_trigger_r )
{
if (LOG_DMA && space->machine().input().code_pressed(KEYCODE_L))
logerror("%06X:trigger\n", cpu_get_pc(&space->device()));
process_dma_queue(space->machine());
state->m_poly->process_dma_queue();
state->m_dma_data_index = 0;
}
return 0;
@ -477,7 +456,7 @@ READ32_HANDLER( midvunit_scanline_r )
WRITE32_HANDLER( midvunit_videoram_w )
{
midvunit_state *state = space->machine().driver_data<midvunit_state>();
poly_wait(state->m_poly, "Video RAM write");
state->m_poly->wait("Video RAM write");
if (!state->m_video_changed)
{
int visbase = (state->m_page_control & 1) ? 0x40000 : 0x00000;
@ -491,7 +470,7 @@ WRITE32_HANDLER( midvunit_videoram_w )
READ32_HANDLER( midvunit_videoram_r )
{
midvunit_state *state = space->machine().driver_data<midvunit_state>();
poly_wait(state->m_poly, "Video RAM read");
state->m_poly->wait("Video RAM read");
return state->m_videoram[offset];
}
@ -524,7 +503,7 @@ WRITE32_HANDLER( midvunit_textureram_w )
{
midvunit_state *state = space->machine().driver_data<midvunit_state>();
UINT8 *base = (UINT8 *)state->m_textureram;
poly_wait(state->m_poly, "Texture RAM write");
state->m_poly->wait("Texture RAM write");
base[offset * 2] = data;
base[offset * 2 + 1] = data >> 8;
}
@ -552,7 +531,7 @@ SCREEN_UPDATE( midvunit )
int x, y, width, xoffs;
UINT32 offset;
poly_wait(state->m_poly, "Refresh Time");
state->m_poly->wait("Refresh Time");
/* if the video didn't change, indicate as much */
if (!state->m_video_changed)