summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2021-01-12 21:34:19 +0100
committer hap <happppp@users.noreply.github.com>2021-01-12 21:34:35 +0100
commit198696996f7325173f7f82f868499d3554d203c9 (patch)
tree5b2e792f4d92acc04602127a545283562970b43f
parent521a8bf964c990fcd291c4011130e6681c9e5288 (diff)
i8244: changed character layer priorities
-rw-r--r--hash/videopac.xml2
-rw-r--r--src/devices/video/i8244.cpp162
-rw-r--r--src/devices/video/i8244.h4
-rw-r--r--src/mame/drivers/odyssey2.cpp15
4 files changed, 91 insertions, 92 deletions
diff --git a/hash/videopac.xml b/hash/videopac.xml
index 9dc4bb2f0b9..c27fc747a5d 100644
--- a/hash/videopac.xml
+++ b/hash/videopac.xml
@@ -1801,6 +1801,7 @@ Newer releases don't follow this numbering scheme anymore.
<description>Spider-Man (Europe, prototype, set 1)</description>
<year>198?</year>
<publisher>Parker Brothers</publisher>
+ <info name="programmer" value="Jan van Nuland" />
<part name="cart" interface="odyssey_cart">
<feature name="slot" value="o2_rom" />
<dataarea name="rom" size="0x2000">
@@ -1813,6 +1814,7 @@ Newer releases don't follow this numbering scheme anymore.
<description>Spider-Man (Europe, prototype, set 2)</description>
<year>198?</year>
<publisher>Parker Brothers</publisher>
+ <info name="programmer" value="Jan van Nuland" />
<part name="cart" interface="odyssey_cart">
<feature name="slot" value="o2_rom" />
<dataarea name="rom" size="0x2000">
diff --git a/src/devices/video/i8244.cpp b/src/devices/video/i8244.cpp
index 9b49c633561..fb4f181a998 100644
--- a/src/devices/video/i8244.cpp
+++ b/src/devices/video/i8244.cpp
@@ -136,7 +136,9 @@ void i8244_device::device_start()
save_pointer(NAME(m_vdc.reg), 0x100);
memset(m_collision_map, 0, sizeof(m_collision_map));
+ memset(m_priority_map, 0, sizeof(m_priority_map));
save_item(NAME(m_collision_map));
+ save_item(NAME(m_priority_map));
save_item(NAME(m_x_beam_pos));
save_item(NAME(m_y_beam_pos));
@@ -448,7 +450,7 @@ void i8244_device::write_cx(int x, bool cx)
{
u8 colx = m_collision_map[x] & 0x3f;
- // Check if we collide with an already drawn source object
+ // check if we collide with an already drawn source object
if (colx)
{
// external overlap interrupt
@@ -461,7 +463,7 @@ void i8244_device::write_cx(int x, bool cx)
if (colx & m_vdc.s.collision)
m_collision_status |= 0x40;
}
- // Check if an already drawn object would collide with us
+ // check if an already drawn object would collide with us
if (m_vdc.s.collision & 0x40)
{
m_collision_status |= colx;
@@ -470,17 +472,56 @@ void i8244_device::write_cx(int x, bool cx)
}
+void i8244_device::draw_char(u8 index, int x, int y, u8 pixel, u16 color, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ for (int px = x; px < x + 2; px++)
+ {
+ if (cliprect.contains(px, y))
+ {
+ u8 colx = m_collision_map[px];
+
+ // check collision with self
+ if (index < m_priority_map[px])
+ {
+ m_control_status |= 0x80;
+
+ // TODO: much more complex on actual console (weird glitches happen)
+ if (colx & 0x80)
+ continue;
+ }
+ else
+ m_priority_map[px] = index;
+
+ if (pixel)
+ {
+ // check if we collide with an already drawn source object
+ if (m_vdc.s.collision & colx)
+ m_collision_status |= 0x80;
+
+ // check if an already drawn object would collide with us
+ if (m_vdc.s.collision & 0x80)
+ m_collision_status |= colx;
+
+ m_collision_map[px] |= 0x80;
+ bitmap.pix(y, px) = color;
+ }
+ }
+ }
+}
+
+
u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- /* Draw background color */
+ // draw background color
bitmap.fill(bitswap<3>(m_vdc.s.color,3,4,5), cliprect);
for (int scanline = cliprect.min_y; scanline <= cliprect.max_y; scanline++)
{
- /* Clear collision map */
+ // clear collision maps
memset(m_collision_map, 0, sizeof(m_collision_map));
+ memset(m_priority_map, 0, sizeof(m_priority_map));
- /* Display grid if enabled */
+ // display grid if enabled
if (m_vdc.s.control & 0x08)
{
u16 color = bitswap<4>(m_vdc.s.color,6,0,1,2);
@@ -490,7 +531,7 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
int height = 24;
int w = (m_vdc.s.control & 0x80) ? width : 2;
- /* Draw horizontal part of the grid */
+ // draw horizontal part of the grid
for (int y = 0; y < 9; y++)
{
if (y_grid_offset + y * height <= scanline && scanline < y_grid_offset + y * height + 3)
@@ -517,7 +558,7 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
}
}
- /* Draw dots part of the grid */
+ // draw dots part of the grid
if (m_vdc.s.control & 0x40)
{
for (int y = 0; y < 9; y++)
@@ -544,7 +585,7 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
}
}
- /* Draw vertical part of the grid */
+ // draw vertical part of the grid
for (int j = 1, y = 0; y < 8; y++, j <<= 1)
{
if (y_grid_offset + y * height <= scanline && scanline < y_grid_offset + (y + 1) * height)
@@ -572,17 +613,19 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
}
}
- /* Display objects if enabled */
+ // display objects if enabled
if (m_vdc.s.control & 0x20 && scanline <= 242)
{
- /* Quad objects */
+ // quad objects
for (int i = ARRAY_LENGTH(m_vdc.s.quad) - 1; i >= 0; i--)
{
int y = m_vdc.s.quad[i].single[0].y;
+ if (is_ntsc() && y < 0xe)
+ continue;
- // Character height is always determined by the height of the 4th character
- int height = 8 - (((y >> 1) + m_vdc.s.quad[i].single[3].ptr) & 7);
- if (height == 1) height = 8;
+ // character height is always determined by the height of the 4th character
+ int height = 7 - (((y >> 1) + m_vdc.s.quad[i].single[3].ptr) & 7);
+ if (height == 0) height = 8;
if (y <= scanline && scanline < y + height * 2)
{
@@ -590,92 +633,37 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
for (int j = 0; j < ARRAY_LENGTH(m_vdc.s.quad[0].single); j++, x += 16)
{
- u16 color = 8 + ((m_vdc.s.quad[i].single[j].color >> 1) & 0x07);
int offset = (m_vdc.s.quad[i].single[j].ptr | ((m_vdc.s.quad[i].single[j].color & 0x01) << 8)) + (y >> 1) + ((scanline - y) >> 1);
- u8 chr = m_charset[offset & 0x1ff];
- for (u8 m = 0x80; m > 0; m >>= 1, x += 2)
- {
- if (chr & m)
- {
- for (int px = x; px < x + 2; px++)
- {
- if (cliprect.contains(px, scanline))
- {
- // Check collision with self
- u8 colx = m_collision_map[px];
- if (colx & 0x80)
- {
- colx &= ~0x80;
- m_control_status |= 0x80;
- }
-
- // Check if we collide with an already drawn source object
- if (m_vdc.s.collision & colx)
- m_collision_status |= 0x80;
-
- // Check if an already drawn object would collide with us
- if (m_vdc.s.collision & 0x80)
- m_collision_status |= colx;
-
- m_collision_map[px] |= 0x80;
- bitmap.pix(scanline, px) = color;
- }
- }
- }
- }
+ u16 color = 8 + ((m_vdc.s.quad[i].single[j].color >> 1) & 0x07);
+ for (int cx = 0; cx < 8; cx++, x += 2)
+ draw_char(4 * j + 16 * i + 0x40, x, scanline, BIT(m_charset[offset & 0x1ff], cx ^ 7), color, bitmap, cliprect);
}
}
}
- /* Regular foreground objects */
+ // regular foreground objects
for (int i = ARRAY_LENGTH(m_vdc.s.foreground) - 1; i >= 0; i--)
{
int y = m_vdc.s.foreground[i].y;
- int height = 8 - (((y >> 1) + m_vdc.s.foreground[i].ptr) & 7);
- if (height == 1) height = 8;
+ if (is_ntsc() && y < 0xe)
+ continue;
+
+ int height = 7 - (((y >> 1) + m_vdc.s.foreground[i].ptr) & 7);
+ if (height == 0) height = 8;
if (y <= scanline && scanline < y + height * 2)
{
- u16 color = 8 + ((m_vdc.s.foreground[i].color >> 1) & 0x07);
int offset = (m_vdc.s.foreground[i].ptr | ((m_vdc.s.foreground[i].color & 0x01) << 8)) + (y >> 1) + ((scanline - y) >> 1);
- u8 chr = m_charset[offset & 0x1ff];
- int x = (m_vdc.s.foreground[i].x + 5) * 2;
- for (u8 m = 0x80; m > 0; m >>= 1, x += 2)
- {
- if (chr & m)
- {
- for (int px = x; px < x + 2; px++)
- {
- if (cliprect.contains(px, scanline))
- {
- // Check collision with self
- u8 colx = m_collision_map[px];
- if (colx & 0x80)
- {
- colx &= ~0x80;
- m_control_status |= 0x80;
- }
-
- // Check if we collide with an already drawn source object
- if (m_vdc.s.collision & colx)
- m_collision_status |= 0x80;
-
- // Check if an already drawn object would collide with us
- if (m_vdc.s.collision & 0x80)
- m_collision_status |= colx;
-
- m_collision_map[px] |= 0x80;
- bitmap.pix(scanline, px) = color;
- }
- }
- }
- }
+ int x = (m_vdc.s.foreground[i].x + 5) * 2;
+ u16 color = 8 + ((m_vdc.s.foreground[i].color >> 1) & 0x07);
+ for (int cx = 0; cx < 8; cx++, x += 2)
+ draw_char(4 * i + 0x10, x, scanline, BIT(m_charset[offset & 0x1ff], cx ^ 7), color, bitmap, cliprect);
}
}
- /* Sprites */
+ // sprites
for (int i = ARRAY_LENGTH(m_vdc.s.sprites) - 1; i >= 0; i--)
{
int y = m_vdc.s.sprites[i].y;
@@ -692,13 +680,13 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
switch (m_vdc.s.sprites[i].color & 0x03)
{
- case 1: // Xg attribute set
+ case 1: // Xg attribute set
x_shift = 1;
break;
- case 2: // S attribute set
+ case 2: // S attribute set
x_shift = (((scanline - y) / zoom_px) & 0x01) ^ 0x01;
break;
- case 3: // Xg and S attributes set
+ case 3: // Xg and S attributes set
x_shift = ((scanline - y) / zoom_px) & 0x01;
break;
default:
@@ -717,11 +705,11 @@ u32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, con
{
u8 mask = 1 << i;
- // Check if we collide with an already drawn source object
+ // check if we collide with an already drawn source object
if (m_vdc.s.collision & m_collision_map[px])
m_collision_status |= mask;
- // Check if an already drawn object would collide with us
+ // check if an already drawn object would collide with us
if (m_vdc.s.collision & mask)
m_collision_status |= m_collision_map[px];
diff --git a/src/devices/video/i8244.h b/src/devices/video/i8244.h
index d5ad74f832d..5facb28a5a8 100644
--- a/src/devices/video/i8244.h
+++ b/src/devices/video/i8244.h
@@ -117,12 +117,15 @@ protected:
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void set_default_params();
+ inline bool is_ntsc() { return m_vtotal == 263; }
int get_y_beam();
int get_x_beam();
offs_t fix_register_mirrors(offs_t offset);
bool invalid_register(offs_t offset, bool rw);
+ void draw_char(u8 index, int x, int y, u8 pixel, u16 color, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
/* timers */
static constexpr device_timer_id TIMER_VBLANK_START = 0;
static constexpr device_timer_id TIMER_HBLANK_START = 1;
@@ -153,6 +156,7 @@ protected:
vdc_t m_vdc;
u8 m_collision_map[0x200];
+ u8 m_priority_map[0x200];
u8 m_x_beam_pos = 0;
u8 m_y_beam_pos = 0;
diff --git a/src/mame/drivers/odyssey2.cpp b/src/mame/drivers/odyssey2.cpp
index 0410f492b3a..c8b6f8a0576 100644
--- a/src/mame/drivers/odyssey2.cpp
+++ b/src/mame/drivers/odyssey2.cpp
@@ -22,7 +22,7 @@ Videopac consoles:
- Radiola Jet 25 (France)
- Siera Videopac Computer G7000 (France)
- Schneider Videopac 7000 (Germany)
-- Philips Videopac G7200 (Europe, Videopac with built-in screen)
+- Philips Videopac G7200 (Europe, Videopac with built-in B/W screen)
- Philips Videojeu N60 (France)
Videopac+ consoles:
@@ -56,10 +56,13 @@ TODO:
and writes to the ptr/color registers, but does not increment the Y regs
- screen resolution is not strictly defined, height(243) is correct, but
horizontal overscan differs depending on monitor/tv? see syracuse for overscan
-- 824x on the real console, overlapping characters on eachother will cause
- glitches (it is used to an advantage in some as-of-yet undumped homebrews)
-- 8244(NTSC) is not supposed to show characters near the upper border, but
- hiding them will cause bugs in some Euro games
+- 824x on the real console, overlapping major system characters with eachother
+ (including transparent pixels) will cause glitches and instability, it can even
+ overwrite the VDC color and pointer registers
+ * gunfight: accidental usage, sometimes causes 1-frame glitches near bullet
+ * powerlrd: occurs at pink mountain on the right, it's not 1:1 identical on MAME
+ * several homebrews by Rafael: precisely placed overlap to force character
+ color to change to white, see for example Piggyback Planet and Mean Santa
- 8245(PAL) video timing is not 100% accurate, though vtotal and htotal should
be correct. The 8245 is put into slave mode at vblank, timing signals and
vblank IRQ are taken over during it (the Videopac pcb even has extra TTL to
@@ -89,6 +92,8 @@ TODO:
BTANB:
- a lot of PAL games have problems on NTSC (the other way around, not so much)
+ * most-common cause is due to shorter vblank, less time to prepare frame
+ * characters are not rendered near upper border on 8244 (eg. tutank, chezmxme)
- g7400 games don't look correct on odyssey3 and vice versa: ef934x graphics are
placed lower on odyssey3
- Blackjack (Videopac 5) does not work on G7400, caused by a removed BIOS routine