mirror of
https://github.com/holub/mame
synced 2025-06-07 21:33:45 +03:00
S2636 drawing optimisation (nw)
This commit is contained in:
parent
5702bef80d
commit
e883c98c93
@ -6,12 +6,9 @@
|
|||||||
|
|
||||||
This emulation is pretty low-level. For the most part it models
|
This emulation is pretty low-level. For the most part it models
|
||||||
the kinds of counters and flags you'd use if you were actually
|
the kinds of counters and flags you'd use if you were actually
|
||||||
implementing it in programmable logic or on silicon. It even
|
implementing it in programmable logic or on silicon. I'm sure
|
||||||
renders pixels sequentially without multiple passes or needing to
|
there are potential performance improvements in the drawing and
|
||||||
backtrack. This works pretty well, but it probably isn't the most
|
collision detection code.
|
||||||
efficient way to do things. I'm sure there are potential
|
|
||||||
performance improvements in the drawing and collision detection
|
|
||||||
code.
|
|
||||||
|
|
||||||
At present the entire internal space of 256 bytes can be read and
|
At present the entire internal space of 256 bytes can be read and
|
||||||
written. This isn't accurate as some registers are read- or write-
|
written. This isn't accurate as some registers are read- or write-
|
||||||
@ -227,8 +224,10 @@ void s2636_device::render_first_line()
|
|||||||
|
|
||||||
void s2636_device::render_next_line()
|
void s2636_device::render_next_line()
|
||||||
{
|
{
|
||||||
|
// pre-clear the line for convenience
|
||||||
rectangle const &vis_area = m_screen->visible_area();
|
rectangle const &vis_area = m_screen->visible_area();
|
||||||
UINT16 *const row = &m_bitmap.pix16(m_screen_line);
|
UINT16 *const row = &m_bitmap.pix16(m_screen_line);
|
||||||
|
m_bitmap.plot_box(0, m_screen_line, m_bitmap.width(), 1, 0);
|
||||||
|
|
||||||
if ((vis_area.min_y > m_screen_line) || (vis_area.max_y < m_screen_line))
|
if ((vis_area.min_y > m_screen_line) || (vis_area.max_y < m_screen_line))
|
||||||
{
|
{
|
||||||
@ -237,10 +236,6 @@ void s2636_device::render_next_line()
|
|||||||
m_registers[REG_VBL_COL_OBJ] |= 0x40;
|
m_registers[REG_VBL_COL_OBJ] |= 0x40;
|
||||||
m_vrst = true;
|
m_vrst = true;
|
||||||
}
|
}
|
||||||
for (int screen_col = 0; screen_col < m_bitmap.width(); screen_col++)
|
|
||||||
{
|
|
||||||
row[screen_col] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -265,16 +260,8 @@ void s2636_device::render_next_line()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// work out what object pixels belong in this line
|
// work out what object pixels belong in this line
|
||||||
UINT16 obj_clr[OBJ_COUNT];
|
|
||||||
int obj_h_cnt[OBJ_COUNT];
|
|
||||||
int obj_inc[OBJ_COUNT];
|
|
||||||
UINT8 obj_bits[OBJ_COUNT];
|
|
||||||
for (int i = 0; i < OBJ_COUNT; i++)
|
for (int i = 0; i < OBJ_COUNT; i++)
|
||||||
{
|
{
|
||||||
obj_clr[i] = object_color(i) | 0x08;
|
|
||||||
obj_h_cnt[i] = m_registers[OFFS_OBJ[i] + (m_obj_dup[i] ? OFFS_HCB : OFFS_HC)] + m_x_offset;
|
|
||||||
obj_inc[i] = 1 << (3 - object_scale(i));
|
|
||||||
|
|
||||||
// repurpose counter and set flag when we've skipped enough lines
|
// repurpose counter and set flag when we've skipped enough lines
|
||||||
if (!m_obj_cnt[i])
|
if (!m_obj_cnt[i])
|
||||||
{
|
{
|
||||||
@ -284,9 +271,22 @@ void s2636_device::render_next_line()
|
|||||||
|
|
||||||
if (m_obj_disp[i])
|
if (m_obj_disp[i])
|
||||||
{
|
{
|
||||||
|
int const obj_inc = 1 << (3 - object_scale(i));
|
||||||
|
m_obj_cnt[i] -= obj_inc;
|
||||||
|
|
||||||
// fetch appropriate line from object
|
// fetch appropriate line from object
|
||||||
m_obj_cnt[i] -= obj_inc[i];
|
UINT8 const obj_bits = m_registers[OFFS_OBJ[i] + OBJ_HEIGHT - 1 - (m_obj_cnt[i] >> 3)];
|
||||||
obj_bits[i] = m_registers[OFFS_OBJ[i] + OBJ_HEIGHT - 1 - (m_obj_cnt[i] >> 3)];
|
UINT16 const obj_clr = object_color(i) | 0x08 | (0x10 << i);
|
||||||
|
|
||||||
|
// blit it to the line ignoring intermediate pixels
|
||||||
|
int const obj_h_cnt = m_registers[OFFS_OBJ[i] + (m_obj_dup[i] ? OFFS_HCB : OFFS_HC)] + m_x_offset;
|
||||||
|
for (int x = 0, screen_col = vis_area.min_x + (obj_h_cnt * m_divider); (OBJ_WIDTH << 3) > x && (vis_area.max_x >= screen_col); )
|
||||||
|
{
|
||||||
|
bool const bit = bool((obj_bits << (x >> 3)) & 0x80);
|
||||||
|
if (bit && (vis_area.min_x <= screen_col)) row[screen_col] |= obj_clr;
|
||||||
|
x += obj_inc;
|
||||||
|
screen_col += m_divider;
|
||||||
|
}
|
||||||
|
|
||||||
// if that's the last line of the object, flag completion and prepare for duplicates
|
// if that's the last line of the object, flag completion and prepare for duplicates
|
||||||
if (!m_obj_cnt[i])
|
if (!m_obj_cnt[i])
|
||||||
@ -301,7 +301,25 @@ void s2636_device::render_next_line()
|
|||||||
{
|
{
|
||||||
// count down lines to display object
|
// count down lines to display object
|
||||||
m_obj_cnt[i]--;
|
m_obj_cnt[i]--;
|
||||||
obj_bits[i] = 0x00;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's take a look at the score display
|
||||||
|
UINT16 const bg_clr = m_registers[REG_BG_ENB_CLR] & 0x07;
|
||||||
|
int const score_row = m_vis_line - m_y_offset - SCORE_START_Y[m_registers[REG_SCORE_FMT] & 0x01];
|
||||||
|
if ((0 <= score_row) && (SCORE_HEIGHT > score_row))
|
||||||
|
{
|
||||||
|
int const (&score_start_x)[SCORE_DIGITS] = SCORE_START_X[(m_registers[REG_SCORE_FMT] >> 1) & 0x01];
|
||||||
|
for (int i = 0; i < SCORE_DIGITS; i++)
|
||||||
|
{
|
||||||
|
UINT16 score_bits = SCORE_FONT[score_digit(i)][score_row >> 2];
|
||||||
|
int screen_col = vis_area.min_x + ((score_start_x[i] + m_x_offset) * m_divider);
|
||||||
|
while (score_bits && (vis_area.max_x >= screen_col))
|
||||||
|
{
|
||||||
|
if (score_bits & 0x0001) row[screen_col] |= bg_clr | 0x08;
|
||||||
|
score_bits >>= 1;
|
||||||
|
screen_col += m_divider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,69 +333,17 @@ void s2636_device::render_next_line()
|
|||||||
UINT8 const bg_hbar_bits = m_registers[bg_hbar_offs];
|
UINT8 const bg_hbar_bits = m_registers[bg_hbar_offs];
|
||||||
bool const bg_hbar_stretch = bool(bg_hbar_bits & (1 << ((((bg_row % 40) >= 20) ? 3 : 0) + (((bg_row % 20) >= 11) ? 2 : ((bg_row % 20) >= 2) ? 1 : 0))));
|
bool const bg_hbar_stretch = bool(bg_hbar_bits & (1 << ((((bg_row % 40) >= 20) ? 3 : 0) + (((bg_row % 20) >= 11) ? 2 : ((bg_row % 20) >= 2) ? 1 : 0))));
|
||||||
int const bg_hbar_width = bg_hbar_stretch ? 8 : (0xc0 == (bg_hbar_bits & 0xc0)) ? 4 : (0x40 == (bg_hbar_bits & 0xc0)) ? 2 : 1;
|
int const bg_hbar_width = bg_hbar_stretch ? 8 : (0xc0 == (bg_hbar_bits & 0xc0)) ? 4 : (0x40 == (bg_hbar_bits & 0xc0)) ? 2 : 1;
|
||||||
UINT16 const bg_clr = m_registers[REG_BG_ENB_CLR] & 0x07;
|
|
||||||
UINT16 const scrn_clr = bg_enable ? ((m_registers[REG_BG_ENB_CLR] >> 4) & 0x07) : 0x00;
|
UINT16 const scrn_clr = bg_enable ? ((m_registers[REG_BG_ENB_CLR] >> 4) & 0x07) : 0x00;
|
||||||
|
|
||||||
// let's take a look at the score display
|
|
||||||
int const (&score_start_x)[SCORE_DIGITS] = SCORE_START_X[(m_registers[REG_SCORE_FMT] >> 1) & 0x01];
|
|
||||||
int const score_row = m_vis_line - m_y_offset - SCORE_START_Y[m_registers[REG_SCORE_FMT] & 0x01];
|
|
||||||
bool const score_draw = (0 <= score_row) && (SCORE_HEIGHT > score_row);
|
|
||||||
UINT16 score_bits[SCORE_DIGITS];
|
|
||||||
for (int i = 0; i < SCORE_DIGITS; i++)
|
|
||||||
score_bits[i] = score_draw ? SCORE_FONT[score_digit(i)][score_row >> 2] : 0x0000;
|
|
||||||
|
|
||||||
// clear leading horizontal blanking area
|
|
||||||
m_bitmap.plot_box(0, m_screen_line, m_bitmap.width(), 1, 0);
|
|
||||||
|
|
||||||
bool obj_vis[4] = { false, false, false, false };
|
|
||||||
for (int screen_col = vis_area.min_x, x = 0; vis_area.max_x >= screen_col; x++)
|
for (int screen_col = vis_area.min_x, x = 0; vis_area.max_x >= screen_col; x++)
|
||||||
{
|
{
|
||||||
// render objects
|
|
||||||
bool obj[4];
|
|
||||||
for (int i = 0; i < OBJ_COUNT; i++)
|
|
||||||
{
|
|
||||||
if (!obj_h_cnt[i])
|
|
||||||
{
|
|
||||||
obj_h_cnt[i] = OBJ_WIDTH << 3;
|
|
||||||
obj_vis[i] = true;
|
|
||||||
}
|
|
||||||
if (obj_vis[i])
|
|
||||||
{
|
|
||||||
obj_h_cnt[i] -= obj_inc[i];
|
|
||||||
obj[i] = bool(obj_bits[i] & (1U << (obj_h_cnt[i] >> 3)));
|
|
||||||
if (obj[i]) row[screen_col] |= obj_clr[i];
|
|
||||||
if (!obj_h_cnt[i])
|
|
||||||
{
|
|
||||||
obj_h_cnt[i] = -1;
|
|
||||||
obj_vis[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
obj_h_cnt[i]--;
|
|
||||||
obj[i] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check object-object collisions
|
// check object-object collisions
|
||||||
if (obj[0] && obj[1]) m_registers[REG_VBL_COL_OBJ] |= 0x20;
|
if ((row[screen_col] & 0x10) && (row[screen_col] & 0x20)) m_registers[REG_VBL_COL_OBJ] |= 0x20;
|
||||||
if (obj[0] && obj[2]) m_registers[REG_VBL_COL_OBJ] |= 0x10;
|
if ((row[screen_col] & 0x10) && (row[screen_col] & 0x40)) m_registers[REG_VBL_COL_OBJ] |= 0x10;
|
||||||
if (obj[0] && obj[3]) m_registers[REG_VBL_COL_OBJ] |= 0x08;
|
if ((row[screen_col] & 0x10) && (row[screen_col] & 0x80)) m_registers[REG_VBL_COL_OBJ] |= 0x08;
|
||||||
if (obj[1] && obj[2]) m_registers[REG_VBL_COL_OBJ] |= 0x04;
|
if ((row[screen_col] & 0x20) && (row[screen_col] & 0x40)) m_registers[REG_VBL_COL_OBJ] |= 0x04;
|
||||||
if (obj[1] && obj[3]) m_registers[REG_VBL_COL_OBJ] |= 0x02;
|
if ((row[screen_col] & 0x20) && (row[screen_col] & 0x80)) m_registers[REG_VBL_COL_OBJ] |= 0x02;
|
||||||
if (obj[2] && obj[3]) m_registers[REG_VBL_COL_OBJ] |= 0x01;
|
if ((row[screen_col] & 0x40) && (row[screen_col] & 0x80)) m_registers[REG_VBL_COL_OBJ] |= 0x01;
|
||||||
|
|
||||||
// render scores
|
|
||||||
if (score_draw)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < SCORE_DIGITS; i++)
|
|
||||||
{
|
|
||||||
int const score_col = x - m_x_offset - score_start_x[i];
|
|
||||||
bool const score = bool(score_bits[i] & (1U << score_col));
|
|
||||||
if ((0 <= score_col) && (SCORE_WIDTH > score_col) && score)
|
|
||||||
row[screen_col] |= bg_clr | 0x08;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// work out if the background hits this pixel
|
// work out if the background hits this pixel
|
||||||
int const bg_col = x - m_x_offset - BG_START_X;
|
int const bg_col = x - m_x_offset - BG_START_X;
|
||||||
@ -385,10 +351,10 @@ void s2636_device::render_next_line()
|
|||||||
if (bg_draw && (0 <= bg_col) && (BG_WIDTH > bg_col) && bg && (bg_hbar_width > (bg_col & 0x07)))
|
if (bg_draw && (0 <= bg_col) && (BG_WIDTH > bg_col) && bg && (bg_hbar_width > (bg_col & 0x07)))
|
||||||
{
|
{
|
||||||
// do object-background collisions
|
// do object-background collisions
|
||||||
if (obj[0]) m_registers[REG_COL_BG_CMPL] |= 0x80;
|
if (row[screen_col] & 0x10) m_registers[REG_COL_BG_CMPL] |= 0x80;
|
||||||
if (obj[1]) m_registers[REG_COL_BG_CMPL] |= 0x40;
|
if (row[screen_col] & 0x20) m_registers[REG_COL_BG_CMPL] |= 0x40;
|
||||||
if (obj[2]) m_registers[REG_COL_BG_CMPL] |= 0x20;
|
if (row[screen_col] & 0x40) m_registers[REG_COL_BG_CMPL] |= 0x20;
|
||||||
if (obj[3]) m_registers[REG_COL_BG_CMPL] |= 0x10;
|
if (row[screen_col] & 0x80) m_registers[REG_COL_BG_CMPL] |= 0x10;
|
||||||
if (!(row[screen_col] & 0x08)) row[screen_col] = bg_clr;
|
if (!(row[screen_col] & 0x08)) row[screen_col] = bg_clr;
|
||||||
}
|
}
|
||||||
else if (!(row[screen_col] & 0x08))
|
else if (!(row[screen_col] & 0x08))
|
||||||
@ -397,10 +363,8 @@ void s2636_device::render_next_line()
|
|||||||
row[screen_col] = scrn_clr;
|
row[screen_col] = scrn_clr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// advance the screen column
|
// clear collision crud and deal with pixel clock divider ratio
|
||||||
screen_col++;
|
row[screen_col++] &= 0x0f;
|
||||||
|
|
||||||
// deal with pixel clock divider ratio
|
|
||||||
for (int i = 1; (i < m_divider) && (vis_area.max_x >= screen_col); i++, screen_col++)
|
for (int i = 1; (i < m_divider) && (vis_area.max_x >= screen_col); i++, screen_col++)
|
||||||
{
|
{
|
||||||
row[screen_col] = row[screen_col - 1];
|
row[screen_col] = row[screen_col - 1];
|
||||||
|
Loading…
Reference in New Issue
Block a user