Merge pull request #1477 from mamehaze/021016_2

make model 1 render list scanning code safer by masking accesses to t…
This commit is contained in:
Olivier Galibert 2016-10-02 20:05:47 +02:00 committed by GitHub
commit cfed90ea81
2 changed files with 228 additions and 207 deletions

View File

@ -405,9 +405,9 @@ private:
std::unique_ptr<UINT32[]> m_poly_ram;
// Rendering helper functions
UINT32 readi(const UINT16 *adr) const;
INT16 readi16(const UINT16 *adr) const;
float readf(const UINT16 *adr) const;
UINT32 readi(int adr) const;
INT16 readi16(int adr) const;
float readf(int adr) const;
void cross_product(point_t* o, const point_t* p, const point_t* q) const;
float view_determinant(const point_t *p1, const point_t *p2, const point_t *p3) const;
@ -441,18 +441,21 @@ private:
static float max4f(float a, float b, float c, float d);
static float compute_specular(glm::vec3& normal, glm::vec3& light, float diffuse,int lmode);
int push_direct(int list_offset);
int draw_direct(bitmap_rgb32 &bitmap, const rectangle &cliprect, int list_offset);
int skip_direct(int list_offset) const;
void push_object(UINT32 tex_adr, UINT32 poly_adr, UINT32 size);
UINT16* push_direct(UINT16 *list);
UINT16* skip_direct(UINT16 *list) const;
void draw_objects(bitmap_rgb32 &bitmap, const rectangle &cliprect);
UINT16* draw_direct(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 *list);
UINT16* get_list();
void set_current_render_list();
int get_list_number();
void end_frame();
clipper_t m_clipfn[4];
// run-time rendering
UINT16* m_display_list_current;
optional_shared_ptr<UINT16> m_paletteram16;
required_device<palette_device> m_palette;
required_device<segas24_tile> m_tiles;
@ -461,6 +464,7 @@ private:
UINT16 m_lamp_state;
optional_ioport_array<8> m_analog_ports;
required_ioport_array<3> m_digital_ports;
};

View File

@ -17,17 +17,17 @@
enum { FRAC_SHIFT = 16 };
enum { MOIRE = 0x01000000 };
UINT32 model1_state::readi(const UINT16 *adr) const
UINT32 model1_state::readi(int adr) const
{
return adr[0]|(adr[1] << 16);
return m_display_list_current[(adr + 0)&0x7fff] | (m_display_list_current[(adr + 1)&0x7fff] << 16);
}
INT16 model1_state::readi16(const UINT16 *adr) const
INT16 model1_state::readi16(int adr) const
{
return adr[0];
return m_display_list_current[(adr + 0)&0x7fff];
}
float model1_state::readf(const UINT16 *adr) const
float model1_state::readf(int adr) const
{
return u2f(readi(adr));
}
@ -985,20 +985,21 @@ void model1_state::push_object(UINT32 tex_adr, UINT32 poly_adr, UINT32 size) {
}
}
UINT16 *model1_state::push_direct(UINT16 *list) {
UINT32 tex_adr = readi(list);
// v1 = readi(list+2);
// v2 = readi(list+10);
int model1_state::push_direct(int list_offset) {
UINT32 tex_adr = readi(list_offset + 2);
// v1 = readi(list_offset+2+2);
// v2 = readi(list_offset+2+10);
point_t *old_p0 = m_pointpt++;
point_t *old_p1 = m_pointpt++;
old_p0->x = readf(list + 4);
old_p0->y = readf(list + 6);
old_p0->z = readf(list + 8);
old_p1->x = readf(list + 12);
old_p1->y = readf(list + 14);
old_p1->z = readf(list + 16);
old_p0->x = readf(list_offset + 2 + 4);
old_p0->y = readf(list_offset + 2 + 6);
old_p0->z = readf(list_offset + 2 + 8);
old_p1->x = readf(list_offset + 2 + 12);
old_p1->y = readf(list_offset + 2 + 14);
old_p1->z = readf(list_offset + 2 + 16);
LOG_TGP(("VIDEOD start direct\n"));
LOG_TGP(("VIDEOD (%f, %f, %f) (%f, %f, %f)\n",
@ -1025,10 +1026,10 @@ UINT16 *model1_state::push_direct(UINT16 *list) {
old_p1->s.x = old_p1->s.y = 0;
}
list += 18;
list_offset += 18;
for (;;) {
UINT32 flags = readi(list);
UINT32 flags = readi(list_offset + 2);
int type = flags & 3;
if (!type)
@ -1037,43 +1038,43 @@ UINT16 *model1_state::push_direct(UINT16 *list) {
if (flags & 0x00001000)
tex_adr++;
// list+2 is luminosity
// list+4 is 0?
// list+12 is z?
// list+2+2 is luminosity
// list+2+4 is 0?
// list+2+12 is z?
point_t *p0 = m_pointpt++;
point_t *p1 = m_pointpt++;
UINT32 lum = readi(list + 2);
// v1 = readi(list+4);
UINT32 lum = readi(list_offset + 2 + 2);
// v1 = readi(list_offset+2+4);
float z = 0;
if (type == 2)
{
p0->x = readf(list + 6);
p0->y = readf(list + 8);
p0->z = readf(list + 10);
p0->x = readf(list_offset + 2 + 6);
p0->y = readf(list_offset + 2 + 8);
p0->z = readf(list_offset + 2 + 10);
z = p0->z;
LOG_TGP(("VIDEOD %08x %08x (%f, %f, %f)\n",
flags, lum,
p0->x, p0->y, p0->z));
*p1 = *p0;
list += 12;
list_offset += 12;
}
else
{
p0->x = readf(list + 6);
p0->y = readf(list + 8);
p0->z = readf(list + 10);
p1->x = readf(list + 14);
p1->y = readf(list + 16);
p1->z = readf(list + 18);
z = readf(list + 12);
p0->x = readf(list_offset + 2 + 6);
p0->y = readf(list_offset + 2 + 8);
p0->z = readf(list_offset + 2 + 10);
p1->x = readf(list_offset + 2 + 14);
p1->y = readf(list_offset + 2 + 16);
p1->z = readf(list_offset + 2 + 18);
z = readf(list_offset + 2 + 12);
LOG_TGP(("VIDEOD %08x %08x (%f, %f, %f) (%f, %f, %f)\n",
flags, lum,
p0->x, p0->y, p0->z,
p1->x, p1->y, p1->z));
list += 20;
list_offset += 20;
}
int link = (flags >> 8) & 3;
@ -1121,8 +1122,8 @@ UINT16 *model1_state::push_direct(UINT16 *list) {
int g = (color >> 0x5) & 0x1f;
int b = (color >> 0xA) & 0x1f;
lumval >>= 2; //there must be a luma translation table somewhere
if (lumval>0x3f) lumval = 0x3f;
else if (lumval<0) lumval = 0;
if (lumval > 0x3f) lumval = 0x3f;
else if (lumval < 0) lumval = 0;
r = (m_color_xlat[(r << 8) | lumval | 0x0] >> 3) & 0x1f;
g = (m_color_xlat[(g << 8) | lumval | 0x2000] >> 3) & 0x1f;
b = (m_color_xlat[(b << 8) | lumval | 0x4000] >> 3) & 0x1f;
@ -1136,39 +1137,41 @@ UINT16 *model1_state::push_direct(UINT16 *list) {
next:
switch (link) {
case 0:
case 2:
old_p0 = p0;
old_p1 = p1;
break;
case 1:
old_p1 = p0;
break;
case 3:
old_p0 = p1;
break;
case 0:
case 2:
old_p0 = p0;
old_p1 = p1;
break;
case 1:
old_p1 = p0;
break;
case 3:
old_p0 = p1;
break;
}
}
return list + 2;
list_offset += 4;
return list_offset;
}
UINT16* model1_state::skip_direct(UINT16 *list) const
int model1_state::skip_direct(int list_offset) const
{
list += 18;
list_offset += 18;
while (true) {
UINT32 flags = readi(list);
UINT32 flags = readi(list_offset + 2);
int type = flags & 3;
if (!type)
break;
if (type == 2)
list += 12;
list_offset += 12;
else
list += 20;
list_offset += 20;
}
return list + 2;
list_offset += 4;
return list_offset;
}
void model1_state::draw_objects(bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -1184,25 +1187,30 @@ void model1_state::draw_objects(bitmap_rgb32 &bitmap, const rectangle &cliprect)
m_pointpt = m_pointdb;
}
UINT16 *model1_state::draw_direct(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 *list)
int model1_state::draw_direct(bitmap_rgb32 &bitmap, const rectangle &cliprect, int list_offset)
{
LOG_TGP(("VIDEO: draw direct %x\n", readi(list)));
LOG_TGP(("VIDEO: draw direct %x\n", readi(list_offset + 2)));
draw_objects(bitmap, cliprect);
UINT16 *res = push_direct(list);
list_offset = push_direct(list_offset);
unsort_quads();
draw_quads(bitmap, cliprect);
m_quadpt = m_quaddb;
m_pointpt = m_pointdb;
return res;
return list_offset;
}
UINT16 *model1_state::get_list()
void model1_state::set_current_render_list()
{
if(!(m_listctl[0] & 4))
m_listctl[0] = (m_listctl[0] & ~0x40) | (m_listctl[0] & 8 ? 0x40 : 0);
return m_listctl[0] & 0x40 ? m_display_list1 : m_display_list0;
m_display_list_current = m_listctl[0] & 0x40 ? m_display_list1 : m_display_list0;
}
int model1_state::get_list_number()
@ -1289,148 +1297,153 @@ void model1_state::view_t::set_view_translation(float x, float y)
recompute_frustum();
}
void model1_state::tgp_render(bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
m_render_done = 1;
if ((m_listctl[1] & 0x1f) == 0x1f)
{
UINT16 *list = get_list();
set_current_render_list();
int zz = 0;
LOG_TGP(("VIDEO: render list %d\n", get_list_number()));
m_view->init_translation_matrix();
int list_offset = 0;
for (;;) {
int type = (list[1] << 16) | list[0];
m_glist = list;
int type = readi(list_offset + 0);
switch (type)
{
case 0:
list += 2;
break;
case 1:
case 0x41:
// 1 = plane 1
// 2 = ?? draw object (413d3, 17c4c, e)
// 3 = plane 2
// 4 = ?? draw object (408a8, a479, 9)
// 5 = decor
// 6 = ?? draw object (57bd4, 387460, 2ad)
case 0:
list_offset += 2;
break;
case 1:
case 0x41:
// 1 = plane 1
// 2 = ?? draw object (413d3, 17c4c, e)
// 3 = plane 2
// 4 = ?? draw object (408a8, a479, 9)
// 5 = decor
// 6 = ?? draw object (57bd4, 387460, 2ad)
if (true || zz >= 666)
push_object(readi(list + 2), readi(list + 4), readi(list + 6));
list += 8;
break;
case 2:
list = draw_direct(bitmap, cliprect, list + 2);
break;
case 3:
{
LOG_TGP(("VIDEO: viewport (%d, %d, %d, %d, %d, %d, %d)\n",
readi(list + 2),
readi16(list + 4), readi16(list + 6), readi16(list + 8),
readi16(list + 10), readi16(list + 12), readi16(list + 14)));
if (true || zz >= 666)
push_object(readi(list_offset + 2), readi(list_offset + 4), readi(list_offset + 6));
list_offset += 8;
break;
case 2:
{
list_offset = draw_direct(bitmap, cliprect, list_offset);
break;
}
case 3:
{
LOG_TGP(("VIDEO: viewport (%d, %d, %d, %d, %d, %d, %d)\n",
readi(list_offset + 2),
readi16(list_offset + 4), readi16(list_offset + 6), readi16(list_offset + 8),
readi16(list_offset + 10), readi16(list_offset + 12), readi16(list_offset + 14)));
draw_objects(bitmap, cliprect);
draw_objects(bitmap, cliprect);
float xc = readi16(list + 4);
float yc = 383 - (readi16(list + 6) - 39);
float x1 = readi16(list + 8);
float y2 = 383 - (readi16(list + 10) - 39);
float x2 = readi16(list + 12);
float y1 = 383 - (readi16(list + 14) - 39);
float xc = readi16(list_offset + 4);
float yc = 383 - (readi16(list_offset + 6) - 39);
float x1 = readi16(list_offset + 8);
float y2 = 383 - (readi16(list_offset + 10) - 39);
float x2 = readi16(list_offset + 12);
float y1 = 383 - (readi16(list_offset + 14) - 39);
m_view->set_viewport(xc, yc, x1, x2, y1, y2);
m_view->set_viewport(xc, yc, x1, x2, y1, y2);
list += 16;
break;
}
case 4:
list_offset += 16;
break;
}
case 4:
{
int adr = readi(list_offset + 2);
int len = readi(list_offset + 4) + 1;
LOG_TGP(("ZVIDEO: color write, adr=%x, len=%x\n", adr, len));
for (int i = 0; i < len; i++)
{
int adr = readi(list + 2);
int len = readi(list + 4) + 1;
LOG_TGP(("ZVIDEO: color write, adr=%x, len=%x\n", adr, len));
for (int i = 0; i < len; i++)
{
m_tgp_ram[adr - 0x40000 + i] = list[6 + 2 * i];
}
list += 6 + len * 2;
break;
m_tgp_ram[adr - 0x40000 + i] = readi16(list_offset + 6 + 2 * i);
}
case 5:
list_offset += 6 + len * 2;
break;
}
case 5:
{
int adr = readi(list_offset + 2);
int len = readi(list_offset + 4);
for (int i = 0; i < len; i++)
{
int adr = readi(list + 2);
int len = readi(list + 4);
for (int i = 0; i < len; i++)
{
m_poly_ram[adr - 0x800000 + i] = readi(list + 2 * i + 6);
}
list += 6 + len * 2;
break;
m_poly_ram[adr - 0x800000 + i] = readi(list_offset + 2 * i + 6);
}
case 6:
list_offset += 6 + len * 2;
break;
}
case 6:
{
int adr = readi(list_offset + 2);
int len = readi(list_offset + 4);
LOG_TGP(("VIDEO: upload data, adr=%x, len=%x\n", adr, len));
for (int i = 0; i < len; i++)
{
int adr = readi(list + 2);
int len = readi(list + 4);
LOG_TGP(("VIDEO: upload data, adr=%x, len=%x\n", adr, len));
for (int i = 0; i < len; i++)
{
int v = readi(list + 6 + i * 2);
float diffuse = (float(v & 0xff)) / 255.0f;
float ambient = (float((v >> 8) & 0xff)) / 255.0f;
float specular = (float((v >> 16) & 0xff)) / 255.0f;
int power = (v >> 24) & 0xff;
m_view->set_lightparam(i + adr, diffuse, ambient, specular, power);
}
list += 6 + len * 2;
break;
int v = readi(list_offset + 6 + i * 2);
float diffuse = (float(v & 0xff)) / 255.0f;
float ambient = (float((v >> 8) & 0xff)) / 255.0f;
float specular = (float((v >> 16) & 0xff)) / 255.0f;
int power = (v >> 24) & 0xff;
m_view->set_lightparam(i + adr, diffuse, ambient, specular, power);
}
case 7:
LOG_TGP(("VIDEO: code 7 (%d)\n", readi(list + 2)));
zz++;
list += 4;
break;
case 8:
LOG_TGP(("VIDEO: select mode %08x\n", readi(list + 2)));
list += 4;
break;
case 9:
LOG_TGP(("VIDEO: zoom (%f, %f)\n", readf(list + 2), readf(list + 4)));
m_view->set_zoom(readf(list + 2) * 4, readf(list + 4) * 4);
list += 6;
break;
case 0xa:
LOG_TGP(("VIDEO: light vector (%f, %f, %f)\n", readf(list + 2), readf(list + 4), readf(list + 6)));
m_view->set_light_direction(readf(list + 2), readf(list + 4), readf(list + 6));
list += 8;
break;
case 0xb:
list_offset += 6 + len * 2;
break;
}
case 7:
LOG_TGP(("VIDEO: code 7 (%d)\n", readi(list_offset + 2)));
zz++;
list_offset += 4;
break;
case 8:
LOG_TGP(("VIDEO: select mode %08x\n", readi(list_offset + 2)));
list_offset += 4;
break;
case 9:
LOG_TGP(("VIDEO: zoom (%f, %f)\n", readf(list_offset + 2), readf(list_offset + 4)));
m_view->set_zoom(readf(list_offset + 2) * 4, readf(list_offset + 4) * 4);
list_offset += 6;
break;
case 0xa:
LOG_TGP(("VIDEO: light vector (%f, %f, %f)\n", readf(list_offset + 2), readf(list_offset + 4), readf(list_offset + 6)));
m_view->set_light_direction(readf(list_offset + 2), readf(list_offset + 4), readf(list_offset + 6));
list_offset += 8;
break;
case 0xb:
{
LOG_TGP(("VIDEO: matrix (%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f)\n",
readf(list_offset + 2), readf(list_offset + 4), readf(list_offset + 6),
readf(list_offset + 8), readf(list_offset + 10), readf(list_offset + 12),
readf(list_offset + 14), readf(list_offset + 16), readf(list_offset + 18),
readf(list_offset + 20), readf(list_offset + 22), readf(list_offset + 24)));
float mat[12];
for (int i = 0; i < 12; i++)
{
LOG_TGP(("VIDEO: matrix (%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f)\n",
readf(list + 2), readf(list + 4), readf(list + 6),
readf(list + 8), readf(list + 10), readf(list + 12),
readf(list + 14), readf(list + 16), readf(list + 18),
readf(list + 20), readf(list + 22), readf(list + 24)));
float mat[12];
for (int i = 0; i < 12; i++)
{
mat[i] = readf(list + 2 + 2 * i);
}
m_view->set_translation_matrix(mat);
list += 26;
break;
mat[i] = readf(list_offset + 2 + 2 * i);
}
case 0xc:
LOG_TGP(("VIDEO: trans (%f, %f)\n", readf(list + 2), readf(list + 4)));
m_view->set_view_translation(readf(list + 2), readf(list + 4));
list += 6;
break;
case 0xf:
//case -1:
goto end;
default:
LOG_TGP(("VIDEO: unknown type %d\n", type));
goto end;
m_view->set_translation_matrix(mat);
list_offset += 26;
break;
}
case 0xc:
LOG_TGP(("VIDEO: trans (%f, %f)\n", readf(list_offset + 2), readf(list_offset + 4)));
m_view->set_view_translation(readf(list_offset + 2), readf(list_offset + 4));
list_offset += 6;
break;
case 0xf:
//case -1:
goto end;
default:
LOG_TGP(("VIDEO: unknown type %d\n", type));
goto end;
}
}
end:
@ -1438,6 +1451,7 @@ void model1_state::tgp_render(bitmap_rgb32 &bitmap, const rectangle &cliprect)
}
}
void model1_state::tgp_scan()
{
#if 0
@ -1453,83 +1467,86 @@ void model1_state::tgp_scan()
#endif
if (!m_render_done && (m_listctl[1] & 0x1f) == 0x1f)
{
UINT16 *list = get_list();
set_current_render_list();
// Skip everything but the data uploads
LOG_TGP(("VIDEO: scan list %d\n", get_list_number()));
int list_offset = 0;
for (;;)
{
int type = (list[1] << 16) | list[0];
int type = readi(list_offset + 0);
switch (type) {
case 0:
list += 2;
list_offset += 2;
break;
case 1:
case 0x41:
list += 8;
list_offset += 8;
break;
case 2:
list = skip_direct(list + 2);
list_offset = skip_direct(list_offset);
break;
case 3:
list += 16;
list_offset += 16;
break;
case 4:
{
int adr = readi(list + 2);
int len = readi(list + 4) + 1;
int adr = readi(list_offset + 2);
int len = readi(list_offset + 4) + 1;
LOG_TGP(("ZVIDEO: scan color write, adr=%x, len=%x\n", adr, len));
for (int i = 0; i<len; i++)
{
m_tgp_ram[adr - 0x40000 + i] = list[6 + 2 * i];
m_tgp_ram[adr - 0x40000 + i] = readi16(list_offset + 6 + 2 * i);
}
list += 6 + len * 2;
list_offset += 6 + len * 2;
break;
}
case 5:
{
int adr = readi(list + 2);
int len = readi(list + 4);
int adr = readi(list_offset + 2);
int len = readi(list_offset + 4);
for (int i = 0; i < len; i++)
{
m_poly_ram[adr - 0x800000 + i] = readi(list + 2 * i + 6);
m_poly_ram[adr - 0x800000 + i] = readi(list_offset + 2 * i + 6);
}
list += 6 + len * 2;
list_offset += 6 + len * 2;
break;
}
case 6:
{
int adr = readi(list + 2);
int len = readi(list + 4);
int adr = readi(list_offset + 2);
int len = readi(list_offset + 4);
//LOG_TGP(("VIDEO: upload data, adr=%x, len=%x\n", adr, len));
for (int i = 0; i<len; i++)
{
int v = readi(list + 6 + i * 2);
int v = readi(list_offset + 6 + i * 2);
m_view->lightparams[i + adr].d = (float(v & 0xff)) / 255.0f;
m_view->lightparams[i + adr].a = (float((v >> 8) & 0xff)) / 255.0f;
m_view->lightparams[i + adr].s = (float((v >> 16) & 0xff)) / 255.0f;
m_view->lightparams[i + adr].p = (v >> 24) & 0xff;
//LOG_TGP((" %02X\n",v));
}
list += 6 + len * 2;
list_offset += 6 + len * 2;
break;
}
case 7:
list += 4;
list_offset += 4;
break;
case 8:
list += 4;
list_offset += 4;
break;
case 9:
list += 6;
list_offset += 6;
break;
case 0xa:
list += 8;
list_offset += 8;
break;
case 0xb:
list += 26;
list_offset += 26;
break;
case 0xc:
list += 6;
list_offset += 6;
break;
case 0xf:
case -1: