summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/315_5124.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/315_5124.cpp')
-rw-r--r--src/devices/video/315_5124.cpp191
1 files changed, 135 insertions, 56 deletions
diff --git a/src/devices/video/315_5124.cpp b/src/devices/video/315_5124.cpp
index 9a3a0f8c339..1f4bd1bf484 100644
--- a/src/devices/video/315_5124.cpp
+++ b/src/devices/video/315_5124.cpp
@@ -16,7 +16,7 @@
To do:
- - Register 3 behaviour in mode 4
+ - Mid-scanline changes
- VRAM/CRAM access constraints
@@ -68,6 +68,25 @@ PAL frame timing
#include "video/315_5124.h"
+/****************************************************************************
+ * Configurable logging
+ ****************************************************************************/
+
+#define LOG_GENERAL (1U << 0)
+#define LOG_VIDMODE (1U << 1)
+#define LOG_REGWRITE (1U << 2)
+#define LOG_VCOUNTREAD (1U << 3)
+
+//#define VERBOSE (LOG_GENERAL | LOG_VIDMODE | LOG_REGWRITE | LOG_VCOUNTREAD)
+//#define LOG_OUTPUT_FUNC printf
+#include "logmacro.h"
+
+#define LOGVIDMODE(...) LOGMASKED(LOG_VIDMODE, __VA_ARGS__)
+#define LOGREGWRITE(...) LOGMASKED(LOG_REGWRITE, __VA_ARGS__)
+#define LOGVCOUNTREAD(...) LOGMASKED(LOG_VCOUNTREAD, __VA_ARGS__)
+
+/****************************************************************************/
+
#define SEGA315_5124_PALETTE_SIZE (64 + 16)
#define SEGA315_5377_PALETTE_SIZE 4096
@@ -337,7 +356,7 @@ void sega315_5124_device::select_display_mode()
else if (!M1 && !M2 && M3) // Mode 3 (Multicolor Mode) */
m_vdp_mode = 3;
else
- logerror("Unknown video mode detected (M1 = %c, M2 = %c, M3 = %c, M4 = %c)\n", M1 ? '1' : '0', M2 ? '1' : '0', M3 ? '1' : '0', M4 ? '1' : '0');
+ LOGVIDMODE("Unknown video mode detected (M1 = %c, M2 = %c, M3 = %c, M4 = %c)\n", M1 ? '1' : '0', M2 ? '1' : '0', M3 ? '1' : '0', M4 ? '1' : '0');
}
}
@@ -351,7 +370,7 @@ void sega315_5313_mode4_device::select_display_mode()
{
/* mode 5, not implemented */
m_vdp_mode = 5;
- logerror("Switched to unimplemented video mode 5 !\n");
+ LOGVIDMODE("Switched to unimplemented video mode 5 !\n");
}
else
{
@@ -392,6 +411,24 @@ void sega315_5124_device::set_frame_timing()
u8 sega315_5124_device::vcount_read()
{
+ u8 vc = vcount();
+
+ LOGVCOUNTREAD(
+ "fr %d vpos %3d hpos %3d hc 0x%02X %s: vcount read value 0x%02X\n",
+ screen().frame_number(),
+ screen().vpos(),
+ screen_hpos(),
+ hcount(),
+ machine().describe_context(),
+ vc
+ );
+
+ return vc;
+}
+
+
+u8 sega315_5124_device::vcount()
+{
const int active_scr_start = m_frame_timing[VERTICAL_SYNC] + m_frame_timing[TOP_BLANKING] + m_frame_timing[TOP_BORDER];
int vpos = screen().vpos();
@@ -415,13 +452,19 @@ u8 sega315_5124_device::hcount_read()
void sega315_5124_device::hcount_latch()
{
+ m_hcounter = hcount();
+ m_hcounter_latched = true;
+}
+
+
+u8 sega315_5124_device::hcount()
+{
/* The hcount value returned by the VDP seems to be based on the previous hpos */
int hclock = screen_hpos() - 1;
if (hclock < 0)
hclock += WIDTH;
- m_hcounter = ((hclock - 46) >> 1) & 0xff;
- m_hcounter_latched = true;
+ return ((hclock - 46) >> 1) & 0xff;
}
@@ -876,14 +919,14 @@ void sega315_5124_device::control_write(u8 data)
break;
}
m_reg[reg_num] = m_addr & 0xff;
- //logerror("%s: %s: setting register %x to %02x\n", machine().describe_context(), tag(), reg_num, m_addr & 0xff);
+ LOGREGWRITE("%s: %s: setting register %x to %02x\n", machine().describe_context(), tag(), reg_num, m_addr & 0xff);
switch (reg_num)
{
case 0:
set_display_settings();
if (BIT(m_addr, 1))
- logerror("overscan enabled.\n");
+ LOGVIDMODE("overscan enabled.\n");
break;
case 1:
set_display_settings();
@@ -947,18 +990,6 @@ void sega315_5124_device::control_write(u8 data)
}
-u16 sega315_5124_device::name_table_row_mode4(int row)
-{
- return ((row >> 3) << 6) & (((m_reg[0x02] & 0x01) << 10) | ((m_reg[0x04] & 0x03) << 11) | 0x23ff);
-}
-
-
-u16 sega315_5246_device::name_table_row_mode4(int row)
-{
- return (row >> 3) << 6;
-}
-
-
void sega315_5124_device::draw_leftmost_pixels_mode4(int *line_buffer, int *priority_selected, int fine_x_scroll, int palette_selected, int tile_line)
{
// To draw the leftmost pixels when they aren't part of a tile column
@@ -1009,6 +1040,42 @@ void sega315_5313_mode4_device::draw_leftmost_pixels_mode4(int *line_buffer, int
}
+u16 sega315_5124_device::name_row_mode4(u16 row)
+{
+ return row & (((m_reg[0x02] & 0x01) << 10) | 0x3bff);
+}
+
+
+u16 sega315_5246_device::name_row_mode4(u16 row)
+{
+ return row;
+}
+
+
+u16 sega315_5124_device::tile1_select_mode4(u16 tile_number)
+{
+ return tile_number & ((m_reg[0x03] << 1) | 1);
+}
+
+
+u16 sega315_5246_device::tile1_select_mode4(u16 tile_number)
+{
+ return tile_number;
+}
+
+
+u16 sega315_5124_device::tile2_select_mode4(u16 tile_number)
+{
+ return tile_number & (((m_reg[0x04] & 0x07) << 6) | 0x03f);
+}
+
+
+u16 sega315_5246_device::tile2_select_mode4(u16 tile_number)
+{
+ return tile_number;
+}
+
+
void sega315_5124_device::draw_scanline_mode4(int *line_buffer, int *priority_selected, int line)
{
/* if top 2 rows of screen not affected by horizontal scrolling, then x_scroll = 0 */
@@ -1019,15 +1086,15 @@ void sega315_5124_device::draw_scanline_mode4(int *line_buffer, int *priority_se
const int fine_x_scroll = (x_scroll & 0x07);
int scroll_mod;
- u16 name_table_address;
+ u16 name_base;
if (m_y_pixels != 192)
{
- name_table_address = ((m_reg[0x02] & 0x0c) << 10) | 0x0700;
+ name_base = ((m_reg[0x02] & 0x0c) << 10) | 0x0700;
scroll_mod = 256;
}
else
{
- name_table_address = (m_reg[0x02] << 10) & 0x3800;
+ name_base = (m_reg[0x02] << 10) & 0x3800;
scroll_mod = 224;
}
@@ -1041,9 +1108,11 @@ void sega315_5124_device::draw_scanline_mode4(int *line_buffer, int *priority_se
/* vertical scrolling when bit 7 of reg[0x00] is set */
const int y_scroll = (BIT(m_reg[0x00], 7) && (tile_column > 23)) ? 0 : m_reg9copy;
- const u16 tile_data = space().read_word(name_table_address + name_table_row_mode4((line + y_scroll) % scroll_mod) + table_column);
+ const u16 name_row = name_row_mode4((((line + y_scroll) % scroll_mod) >> 3) << 6);
+ const u16 tile_data = space().read_word(name_base + name_row + table_column);
- const int tile_selected = (tile_data & 0x01ff);
+ const int tile1_selected = tile1_select_mode4(tile_data & 0x01ff);
+ const int tile2_selected = tile2_select_mode4(tile_data & 0x01ff);
const int priority_select = tile_data & PRIORITY_BIT;
const int palette_selected = BIT(tile_data, 11);
const int vert_selected = BIT(tile_data, 10);
@@ -1053,10 +1122,10 @@ void sega315_5124_device::draw_scanline_mode4(int *line_buffer, int *priority_se
if (vert_selected)
tile_line = 0x07 - tile_line;
- const int bit_plane_0 = space().read_byte(((tile_selected << 5) + ((tile_line & 0x07) << 2)) + 0x00);
- const int bit_plane_1 = space().read_byte(((tile_selected << 5) + ((tile_line & 0x07) << 2)) + 0x01);
- const int bit_plane_2 = space().read_byte(((tile_selected << 5) + ((tile_line & 0x07) << 2)) + 0x02);
- const int bit_plane_3 = space().read_byte(((tile_selected << 5) + ((tile_line & 0x07) << 2)) + 0x03);
+ const u8 bit_plane_0 = space().read_byte(((tile1_selected << 5) + ((tile_line & 0x07) << 2)) + 0x00);
+ const u8 bit_plane_1 = space().read_byte(((tile1_selected << 5) + ((tile_line & 0x07) << 2)) + 0x01);
+ const u8 bit_plane_2 = space().read_byte(((tile2_selected << 5) + ((tile_line & 0x07) << 2)) + 0x02);
+ const u8 bit_plane_3 = space().read_byte(((tile2_selected << 5) + ((tile_line & 0x07) << 2)) + 0x03);
/* Column 0 is the leftmost tile column that completely entered in the screen.
If the leftmost pixels aren't part of a complete tile, due to horizontal
@@ -1088,25 +1157,25 @@ void sega315_5124_device::draw_scanline_mode4(int *line_buffer, int *priority_se
}
-u16 sega315_5124_device::sprite_attributes_addr_mode4(u16 base)
+u8 sega315_5124_device::sprite_attribute_extra_offset_mode4(u8 offset)
{
- return base & ((BIT(m_reg[0x05], 0) << 7) | 0x3f7f);
+ return offset & ((BIT(m_reg[0x05], 0) << 7) | 0x7f);
}
-u16 sega315_5246_device::sprite_attributes_addr_mode4(u16 base)
+u8 sega315_5246_device::sprite_attribute_extra_offset_mode4(u8 offset)
{
- return base;
+ return offset;
}
-u8 sega315_5124_device::sprite_tile_mask_mode4(u8 tile_number)
+u8 sega315_5124_device::sprite_tile_select_mode4(u8 tile_number)
{
return tile_number & (((m_reg[0x06] & 0x03) << 6) | 0x3f);
}
-u8 sega315_5246_device::sprite_tile_mask_mode4(u8 tile_number)
+u8 sega315_5246_device::sprite_tile_select_mode4(u8 tile_number)
{
return tile_number;
}
@@ -1140,20 +1209,25 @@ void sega315_5313_mode4_device::sprite_count_overflow(int line, int sprite_index
void sega315_5124_device::select_sprites(int line)
{
+ m_sprite_count = 0;
+ if (m_vdp_mode == 1)
+ {
+ /* Text mode, no sprite processing */
+ return;
+ }
+
/* Check if SI is set */
m_sprite_height = BIT(m_reg[0x01], 1) ? 16 : 8;
/* Check if MAG is set */
m_sprite_zoom_scale = BIT(m_reg[0x01], 0) ? 2 : 1;
- m_sprite_count = 0;
-
- if (m_vdp_mode == 0 || m_vdp_mode == 2)
+ if (m_vdp_mode < 4)
{
/* TMS9918 compatibility sprites */
const int max_sprites = 4;
- m_sprite_base = ((m_reg[0x05] & 0x7f) << 7);
+ m_sprite_attribute_base = ((m_reg[0x05] & 0x7f) << 7);
for (int sprite_index = 0; (sprite_index < 32 * 4); sprite_index += 4)
{
@@ -1161,7 +1235,7 @@ void sega315_5124_device::select_sprites(int line)
because the logical start point is slightly shifted on the scanline */
int parse_line = line - 1;
- int sprite_y = space().read_byte(m_sprite_base + sprite_index);
+ int sprite_y = space().read_byte(m_sprite_attribute_base + sprite_index);
if (sprite_y == 0xd0)
break;
@@ -1182,9 +1256,9 @@ void sega315_5124_device::select_sprites(int line)
{
if (m_sprite_count < max_sprites)
{
- const int sprite_x = space().read_byte(m_sprite_base + sprite_index + 1);
- int sprite_tile_selected = space().read_byte(m_sprite_base + sprite_index + 2);
- const u8 flags = space().read_byte(m_sprite_base + sprite_index + 3);
+ const int sprite_x = space().read_byte(m_sprite_attribute_base + sprite_index + 1);
+ int sprite_tile_selected = space().read_byte(m_sprite_attribute_base + sprite_index + 2);
+ const u8 flags = space().read_byte(m_sprite_attribute_base + sprite_index + 3);
int sprite_line = parse_line - sprite_y;
@@ -1219,7 +1293,8 @@ void sega315_5124_device::select_sprites(int line)
const int max_sprites = 8;
- m_sprite_base = (m_reg[0x05] << 7) & 0x3f00;
+ m_sprite_attribute_base = (m_reg[0x05] << 7) & 0x3f00;
+ const u16 sprite_attribute_extra_base = m_sprite_attribute_base + sprite_attribute_extra_offset_mode4(0x80);
for (int sprite_index = 0; (sprite_index < 64); sprite_index++)
{
@@ -1227,7 +1302,7 @@ void sega315_5124_device::select_sprites(int line)
because the logical start point is slightly shifted on the scanline */
int parse_line = line - 1;
- int sprite_y = space().read_byte(m_sprite_base + sprite_index);
+ int sprite_y = space().read_byte(m_sprite_attribute_base + sprite_index);
if (m_y_pixels == 192 && sprite_y == 0xd0)
break;
@@ -1249,10 +1324,10 @@ void sega315_5124_device::select_sprites(int line)
if (m_sprite_count < max_sprites)
{
const int sprite_line = parse_line - sprite_y;
- int sprite_x = space().read_byte(sprite_attributes_addr_mode4(m_sprite_base + 0x80) + (sprite_index << 1));
- int sprite_tile_selected = space().read_byte(sprite_attributes_addr_mode4(m_sprite_base + 0x81) + (sprite_index << 1));
+ int sprite_x = space().read_byte(sprite_attribute_extra_base + (sprite_index << 1));
+ int sprite_tile_number = space().read_byte(sprite_attribute_extra_base + (sprite_index << 1) + 1);
- sprite_tile_selected = sprite_tile_mask_mode4(sprite_tile_selected);
+ int sprite_tile_selected = sprite_tile_select_mode4(sprite_tile_number);
if (BIT(m_reg[0x00], 3))
sprite_x -= 0x08; /* sprite shift */
@@ -1509,17 +1584,18 @@ void sega315_5124_device::draw_sprites_tms9918_mode(int *line_buffer, int line)
// Display mode 2 (Graphics II Mode)
void sega315_5124_device::draw_scanline_mode2(int *line_buffer, int line)
{
- const u16 name_table_base = ((m_reg[0x02] & 0x0f) << 10) + ((line >> 3) * 32);
+ const u16 name_base = ((m_reg[0x02] & 0x0f) << 10);
const u16 color_base = ((m_reg[0x03] & 0x80) << 6);
const int color_mask = ((m_reg[0x03] & 0x7f) << 3) | 0x07;
const u16 pattern_base = ((m_reg[0x04] & 0x04) << 11);
const int pattern_mask = ((m_reg[0x04] & 0x03) << 8) | 0xff;
const int pattern_offset = (line & 0xc0) << 2;
+ const u16 name_row_base = name_base + ((line >> 3) * 32);
/* Draw background layer */
for (int tile_column = 0; tile_column < 32; tile_column++)
{
- const u8 name = space().read_byte(name_table_base + tile_column);
+ const u8 name = space().read_byte(name_row_base + tile_column);
const u8 pattern = space().read_byte(pattern_base + (((pattern_offset + name) & pattern_mask) * 8) + (line & 0x07) );
const u8 colors = space().read_byte(color_base + (((pattern_offset + name) & color_mask) * 8) + (line & 0x07) );
@@ -1550,14 +1626,15 @@ void sega315_5124_device::draw_scanline_mode2(int *line_buffer, int line)
// Display mode 0 (Graphics I Mode)
void sega315_5124_device::draw_scanline_mode0(int *line_buffer, int line)
{
- const u16 name_base = ((m_reg[0x02] & 0x0f) << 10) + ((line >> 3) * 32);
+ const u16 name_base = ((m_reg[0x02] & 0x0f) << 10);
const u16 color_base = ((m_reg[0x03] << 6) & (VRAM_SIZE - 1));
const u16 pattern_base = ((m_reg[0x04] << 11) & (VRAM_SIZE - 1));
+ const u16 name_row_base = name_base + ((line >> 3) * 32);
/* Draw background layer */
for (int tile_column = 0; tile_column < 32; tile_column++)
{
- const u8 name = space().read_byte(name_base + tile_column);
+ const u8 name = space().read_byte(name_row_base + tile_column);
const u8 pattern = space().read_byte(pattern_base + (name << 3) + (line & 0x07));
const u8 colors = space().read_byte(color_base + (name >> 3));
@@ -1584,8 +1661,9 @@ void sega315_5124_device::draw_scanline_mode0(int *line_buffer, int line)
// Display mode 1 (Text Mode)
void sega315_5124_device::draw_scanline_mode1(int *line_buffer, int line)
{
- const u16 name_base = ((m_reg[0x02] & 0x0f) << 10) + ((line >> 3) * 32);
+ const u16 name_base = ((m_reg[0x02] & 0x0f) << 10);
const u16 pattern_base = ((m_reg[0x04] << 11) & (VRAM_SIZE - 1));
+ const u16 name_row_base = name_base + ((line >> 3) * 32);
for (int pixel_plot_x = 0; pixel_plot_x < 8; pixel_plot_x++)
{
@@ -1595,7 +1673,7 @@ void sega315_5124_device::draw_scanline_mode1(int *line_buffer, int line)
/* Draw background layer */
for (int tile_column = 0; tile_column < 40; tile_column++)
{
- const u8 name = space().read_byte(name_base + tile_column);
+ const u8 name = space().read_byte(name_row_base + tile_column);
const u8 pattern = space().read_byte(pattern_base + (name << 3) + (line & 0x07));
for (int pixel_x = 0; pixel_x < 6; pixel_x++)
@@ -1624,13 +1702,14 @@ void sega315_5124_device::draw_scanline_mode1(int *line_buffer, int line)
// Display mode 3 (Multicolor Mode)
void sega315_5124_device::draw_scanline_mode3(int *line_buffer, int line)
{
- const u16 name_base = ((m_reg[0x02] & 0x0f) << 10) + ((line >> 3) * 32);
+ const u16 name_base = ((m_reg[0x02] & 0x0f) << 10);
const u16 pattern_base = ((m_reg[0x04] << 11) & (VRAM_SIZE - 1));
+ const u16 name_row_base = name_base + ((line >> 3) * 32);
/* Draw background layer */
for (int tile_column = 0; tile_column < 32; tile_column++)
{
- const u8 name = space().read_byte(name_base + tile_column);
+ const u8 name = space().read_byte(name_row_base + tile_column);
const u8 pattern = space().read_byte(pattern_base + (name << 3) + (((line >> 3) & 3) << 1) + ((line & 4) >> 2));
for (int pixel_x = 0; pixel_x < 8; pixel_x++)
@@ -1988,7 +2067,7 @@ void sega315_5124_device::device_start()
//save_item(NAME(m_tmpbitmap));
//save_item(NAME(m_y1_bitmap));
save_item(NAME(m_draw_time));
- save_item(NAME(m_sprite_base));
+ save_item(NAME(m_sprite_attribute_base));
save_item(NAME(m_sprite_pattern_line));
save_item(NAME(m_sprite_tile_selected));
save_item(NAME(m_sprite_x));