scn2674: reworked for the pcd [Carl]

---
mpu4vid sometimes flickers a bit but otherwise looks the same AFAICT
This commit is contained in:
cracyc 2015-02-15 23:15:53 -06:00
parent 7855b2d6e4
commit aa30911c03
9 changed files with 1037 additions and 1001 deletions

735
src/emu/video/scn2674.c Normal file
View File

@ -0,0 +1,735 @@
/*
SCN2674 - Advanced Video Display Controller (AVDC) (Video Chip)
*/
#include "scn2674.h"
#define S674VERBOSE 0
#define LOG2674(x) do { if (S674VERBOSE) logerror x; } while (0)
const device_type SCN2674_VIDEO = &device_creator<scn2674_device>;
// default address map
static ADDRESS_MAP_START( scn2674_vram, AS_0, 8, scn2674_device )
AM_RANGE(0x0000, 0xffff) AM_NOP
ADDRESS_MAP_END
scn2674_device::scn2674_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SCN2674_VIDEO, "Signetics SCN2674 AVDC", tag, owner, clock, "scn2674_device", __FILE__),
device_video_interface(mconfig, *this),
device_memory_interface(mconfig, *this),
m_irq_cb(*this),
m_space_config("videoram", ENDIANNESS_LITTLE, 8, 16, 0, NULL, *ADDRESS_MAP_NAME(scn2674_vram))
{
}
void scn2674_device::device_start()
{
// resolve callbacks
m_display_cb.bind_relative_to(*owner());
m_irq_cb.resolve_safe();
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
m_screen->register_screen_bitmap(m_bitmap);
save_item(NAME(m_address));
save_item(NAME(m_linecounter));
save_item(NAME(m_screen2_l));
save_item(NAME(m_screen2_h));
}
void scn2674_device::device_reset()
{
m_IR_pointer= 0;
m_screen1_l= 0;
m_screen1_h= 0;
m_cursor_l= 0;
m_cursor_h= 0;
m_screen2_l= 0;
m_screen2_h= 0;
m_irq_register= 0;
m_status_register= 0;
m_irq_mask= 0;
m_gfx_enabled= 0;
m_display_enabled= 0;
m_display_enabled_field= 0;
m_display_enabled_scanline= 0;
m_cursor_enabled= 0;
m_IR0_double_ht_wd= 0;
m_IR0_scanline_per_char_row= 0;
m_IR0_sync_select= 0;
m_IR0_buffer_mode_select= 0;
m_IR1_interlace_enable= 0;
m_IR1_equalizing_constant= 0;
m_IR2_row_table= 0;
m_IR2_horz_sync_width= 0;
m_IR2_horz_back_porch= 0;
m_IR3_vert_front_porch= 0;
m_IR3_vert_back_porch= 0;
m_IR4_rows_per_screen= 0;
m_IR4_character_blink_rate_divisor= 0;
m_IR5_character_per_row= 0;
m_IR6_cursor_first_scanline= 0;
m_IR6_cursor_last_scanline= 0;
m_IR7_cursor_underline_position= 0;
m_IR7_cursor_rate_divisor= 0;
m_IR7_cursor_blink= 0;
m_IR7_vsync_width= 0;
m_IR8_display_buffer_first_address_LSB= 0;
m_IR9_display_buffer_first_address_MSB= 0;
m_IR9_display_buffer_last_address= 0;
m_IR10_display_pointer_address_lower= 0;
m_IR11_display_pointer_address_upper= 0;
m_IR11_reset_scanline_counter_on_scrollup= 0;
m_IR11_reset_scanline_counter_on_scrolldown= 0;
m_IR12_scroll_start= 0;
m_IR12_split_register_1= 0;
m_IR13_scroll_end= 0;
m_IR13_split_register_2= 0;
m_IR14_scroll_lines= 0;
m_IR14_double_1= 0;
m_IR14_double_2= 0;
m_spl1= 0;
m_spl2= 0;
m_dbl1= 0;
m_linecounter= 0;
m_irq_state= 0;
m_IR_pointer = 0;
m_address = 0;
m_hpixels_per_column = m_text_hpixels_per_column;
}
// 15 Initialization Registers (8-bit each)
void scn2674_device::write_init_regs(UINT8 data)
{
LOG2674(("scn2674_write_init_regs %02x %02x\n",m_IR_pointer,data));
switch ( m_IR_pointer) /* display some debug info, set mame specific variables */
{
case 0:
m_IR0_double_ht_wd = (data & 0x80)>>7;
m_IR0_scanline_per_char_row = ((data & 0x78)>>3) + 1;
m_IR0_sync_select = (data&0x04)>>2;
m_IR0_buffer_mode_select = (data&0x03);
LOG2674(("IR0 - Double Ht Wd %02x\n",m_IR0_double_ht_wd));//affects IR14 as well
LOG2674(("IR0 - Scanlines per Character Row %02x\n",m_IR0_scanline_per_char_row));//value+1 = scanlines
LOG2674(("IR0 - Sync Select %02x\n",m_IR0_sync_select));//1 = csync
LOG2674(("IR0 - Buffer Mode Select %02x\n",m_IR0_buffer_mode_select)); //0 independent 1 transparent 2 shared 3 row
break;
case 1:
m_IR1_interlace_enable = (data&0x80)>>7;
m_IR1_equalizing_constant = (data&0x7f)+1;
LOG2674(("IR1 - Interlace Enable %02x\n",m_IR1_interlace_enable));
LOG2674(("IR1 - Equalizing Constant %02i CCLKs\n",m_IR1_equalizing_constant));
break;
case 2:
m_IR2_row_table = (data&0x80)>>7;
m_IR2_horz_sync_width = (((data&0x78)>>3)*2) + 2;
m_IR2_horz_back_porch = ((data&0x07)*4) - 1;
LOG2674(("IR2 - Row Table %02x\n",m_IR2_row_table));
LOG2674(("IR2 - Horizontal Sync Width %02i CCLKs\n",m_IR2_horz_sync_width));
LOG2674(("IR2 - Horizontal Back Porch %02i CCLKs\n",m_IR2_horz_back_porch));
break;
case 3:
m_IR3_vert_front_porch = (((data&0xe0)>>5) * 4)+4 ;
m_IR3_vert_back_porch = ((data&0x1f) * 2) + 4;
LOG2674(("IR3 - Vertical Front Porch %02i Lines\n",m_IR3_vert_front_porch));
LOG2674(("IR3 - Vertical Back Porch %02i Lines\n",m_IR3_vert_back_porch));
break;
case 4:
m_IR4_rows_per_screen = (data&0x7f) + 1;
m_IR4_character_blink_rate_divisor = ((data & 0x80)>>7 ? 128:64);
LOG2674(("IR4 - Rows Per Screen %02i\n",m_IR4_rows_per_screen));
LOG2674(("IR4 - Character Blink Rate = 1/%02i\n",m_IR4_character_blink_rate_divisor));
break;
case 5:
/* IR5 - Active Characters Per Row
cccc cccc
c = Characters Per Row */
m_IR5_character_per_row = data + 1;
LOG2674(("IR5 - Active Characters Per Row %02i\n",m_IR5_character_per_row));
break;
case 6:
m_IR6_cursor_last_scanline = (data & 0x0f);
m_IR6_cursor_first_scanline = (data & 0xf0)>>4;
LOG2674(("IR6 - First Line of Cursor %02x\n",m_IR6_cursor_first_scanline));
LOG2674(("IR6 - Last Line of Cursor %02x\n",m_IR6_cursor_last_scanline));
break;
case 7:
{
const UINT8 vsync_table[4] = {3,1,5,7};
m_IR7_cursor_underline_position = (data & 0x0f);
m_IR7_cursor_rate_divisor = ((data & 0x10)>>4 ? 64:32);
m_IR7_cursor_blink = (data & 0x20)>>5;
m_IR7_vsync_width = vsync_table[(data & 0xC0)>>6];
LOG2674(("IR7 - Underline Position %02x\n",m_IR7_cursor_underline_position));
LOG2674(("IR7 - Cursor rate 1/%02i\n",m_IR7_cursor_rate_divisor));
LOG2674(("IR7 - Cursor blink %02x\n",m_IR7_cursor_blink));
LOG2674(("IR7 - Vsync Width %02i Lines\n",m_IR7_vsync_width));
break;
}
case 8:
m_IR8_display_buffer_first_address_LSB = data;
LOG2674(("IR8 - Display Buffer First Address LSB %02x\n",m_IR8_display_buffer_first_address_LSB));
break;
case 9:
m_IR9_display_buffer_first_address_MSB = data & 0x0f;
m_IR9_display_buffer_last_address = (data & 0xf0)>>4;
LOG2674(("IR9 - Display Buffer First Address MSB %02x\n",m_IR9_display_buffer_first_address_MSB));
LOG2674(("IR9 - Display Buffer Last Address %02x\n",m_IR9_display_buffer_last_address));
break;
case 10:
m_IR10_display_pointer_address_lower = data;
LOG2674(("IR10 - Display Pointer Address Lower %02x\n",m_IR10_display_pointer_address_lower));
break;
case 11:
m_IR11_display_pointer_address_upper= data&0x3f;
m_IR11_reset_scanline_counter_on_scrollup= (data&0x40 >> 6);
m_IR11_reset_scanline_counter_on_scrolldown= (data&0x80 >> 7);
LOG2674(("IR11 - Display Pointer Address Lower %02x\n",m_IR11_display_pointer_address_upper));
LOG2674(("IR11 - Reset Scanline Counter on Scroll Up %02x\n",m_IR11_reset_scanline_counter_on_scrollup));
LOG2674(("IR11 - Reset Scanline Counter on Scroll Down %02x\n",m_IR11_reset_scanline_counter_on_scrolldown));
break;
case 12:
m_IR12_scroll_start = (data & 0x80)>>7;
m_IR12_split_register_1 = (data & 0x7f);
LOG2674(("IR12 - Scroll Start %02x\n",m_IR12_scroll_start));
LOG2674(("IR12 - Split Register 1 %02x\n",m_IR12_split_register_1));
break;
case 13:
m_IR13_scroll_end = (data & 0x80)>>7;
m_IR13_split_register_2 = (data & 0x7f);
LOG2674(("IR13 - Scroll End %02x\n",m_IR13_scroll_end));
LOG2674(("IR13 - Split Register 2 %02x\n",m_IR13_split_register_2));
break;
case 14:
m_IR14_scroll_lines = (data & 0x0f);
if (!m_IR0_double_ht_wd)
{
m_IR14_double_2 = (data & 0x30)>>4;
LOG2674(("IR14 - Double 2 %02x\n",m_IR14_double_2));
}
//0 normal, 1, double width, 2, double width and double tops 3, double width and double bottoms
//1 affects SSR1, 2 affects SSR2
//If Double Height enabled in IR0, Screen start 1 upper (bits 7 and 6)replace Double 1, and Double 2 is unused
m_IR14_double_1 = (data & 0xc0)>>6;
LOG2674(("IR14 - Double 1 %02x\n",m_IR14_double_1));
LOG2674(("IR14 - Scroll Lines %02i\n",m_IR14_scroll_lines));
break;
case 15: /* not valid! */
break;
}
if(m_display_enabled)
recompute_parameters();
m_IR_pointer++;
if (m_IR_pointer>14)m_IR_pointer=14;
}
void scn2674_device::write_command(UINT8 data)
{
UINT8 operand;
int i;
if (data==0x00)
{
/* master reset, configures registers */
LOG2674(("master reset\n"));
m_IR_pointer=0;
m_irq_register = 0x00;
m_status_register = 0x20;//RDFLG activated
m_linecounter =0;
m_irq_mask = 0x00;
m_gfx_enabled = 0;
m_display_enabled = 0;
m_cursor_enabled = 0;
m_IR2_row_table = 0;
}
if ((data&0xf0)==0x10)
{
/* set IR pointer */
operand = data & 0x0f;
LOG2674(("set IR pointer %02x\n",operand));
m_IR_pointer=operand;
}
/* ANY COMBINATION OF THESE ARE POSSIBLE */
if ((data&0xe3)==0x22)
{
/* Disable GFX */
LOG2674(("disable GFX %02x\n",data));
m_gfx_enabled = 0;
if(m_display_enabled)
recompute_parameters();
}
if ((data&0xe3)==0x23)
{
/* Enable GFX */
LOG2674(("enable GFX %02x\n",data));
m_gfx_enabled = 1;
if(m_display_enabled)
recompute_parameters();
}
if ((data&0xe9)==0x28)
{
/* Display off */
operand = data & 0x04;
m_display_enabled = 0;
if (operand)
LOG2674(("display OFF - float DADD bus %02x\n",data));
else
LOG2674(("display OFF - no float DADD bus %02x\n",data));
}
if ((data&0xe9)==0x29)
{
/* Display on */
operand = data & 0x04;
if (operand)
{
m_display_enabled_field = 1;
LOG2674(("display ON - next field %02x\n",data));
}
else
{
m_display_enabled_scanline = 1;
LOG2674(("display ON - next scanline %02x\n",data));
}
recompute_parameters(); // start the scanline timer
}
if ((data&0xf1)==0x30)
{
/* Cursor Off */
LOG2674(("cursor off %02x\n",data));
m_cursor_enabled = 0;
}
if ((data&0xf1)==0x31)
{
/* Cursor On */
LOG2674(("cursor on %02x\n",data));
m_cursor_enabled = 1;
}
/* END */
if ((data&0xe0)==0x40)
{
/* Reset Interrupt / Status bit */
operand = data & 0x1f;
LOG2674(("reset interrupt / status bit %02x\n",operand));
m_irq_register &= ~(data & 0x1f);
m_status_register &= ~(data & 0x1f);
LOG2674(("IRQ Status after reset\n"));
LOG2674(("Split 2 IRQ: %d Active\n",(m_irq_register>>0)&1));
LOG2674(("Ready IRQ: %d Active\n",(m_irq_register>>1)&1));
LOG2674(("Split 1 IRQ: %d Active\n",(m_irq_register>>2)&1));
LOG2674(("Line Zero IRQ: %d Active\n",(m_irq_register>>3)&1));
LOG2674(("V-Blank IRQ: %d Active\n",(m_irq_register>>4)&1));
m_irq_state = 0;
for (i = 0; i < 5; i++)
{
if ((m_irq_register>>i&1)&(m_irq_mask>>i&1))
{
m_irq_state = 1;
}
}
m_irq_cb(m_irq_register ? 1 : 0);
}
if ((data&0xe0)==0x80)
{
/* Disable Interrupt mask*/
operand = data & 0x1f;
m_irq_mask &= ~(operand);
LOG2674(("IRQ Mask after disable %x\n",operand));
LOG2674(("Split 2 IRQ: %d Unmasked\n",(m_irq_mask>>0)&1));
LOG2674(("Ready IRQ: %d Unmasked\n",(m_irq_mask>>1)&1));
LOG2674(("Split 1 IRQ: %d Unmasked\n",(m_irq_mask>>2)&1));
LOG2674(("Line Zero IRQ: %d Unmasked\n",(m_irq_mask>>3)&1));
LOG2674(("V-Blank IRQ: %d Unmasked\n",(m_irq_mask>>4)&1));
}
if ((data&0xe0)==0x60)
{
/* Enable Interrupt mask*/
operand = data & 0x1f;
m_irq_mask |= (data & 0x1f);
LOG2674(("IRQ Mask after enable %x\n",operand));
LOG2674(("Split 2 IRQ: %d Unmasked\n",(m_irq_mask>>0)&1));
LOG2674(("Ready IRQ: %d Unmasked\n",(m_irq_mask>>1)&1));
LOG2674(("Split 1 IRQ: %d Unmasked\n",(m_irq_mask>>2)&1));
LOG2674(("Line Zero IRQ: %d Unmasked\n",(m_irq_mask>>3)&1));
LOG2674(("V-Blank IRQ: %d Unmasked\n",(m_irq_mask>>4)&1));
}
/* Delayed Commands */
/* These set 0x20 in status register when done */
if (data == 0xa4)
{
/* read at pointer address */
LOG2674(("DELAYED read at pointer address %02x\n",data));
}
if (data == 0xa2)
{
/* write at pointer address */
LOG2674(("DELAYED write at pointer address %02x\n",data));
}
if (data == 0xa9)
{
/* increase cursor address */
LOG2674(("DELAYED increase cursor address %02x\n",data));
}
if (data == 0xac)
{
/* read at cursor address */
LOG2674(("DELAYED read at cursor address %02x\n",data));
}
if (data == 0xaa)
{
/* write at cursor address */
LOG2674(("DELAYED write at cursor address %02x\n",data));
}
if (data == 0xad)
{
/* read at cursor address + increment */
LOG2674(("DELAYED read at cursor address+increment %02x\n",data));
}
if (data == 0xab)
{
/* write at cursor address + increment */
LOG2674(("DELAYED write at cursor address+increment %02x\n",data));
}
if (data == 0xbb)
{
/* write from cursor address to pointer address */
LOG2674(("DELAYED write from cursor address to pointer address %02x\n",data));
}
if (data == 0xbd)
{
/* read from cursor address to pointer address */
LOG2674(("DELAYED read from cursor address to pointer address %02x\n",data));
}
}
READ8_MEMBER( scn2674_device::read )
{
/*
Offset: Purpose
0 Interrupt Register
1 Status Register
2 Screen Start 1 Lower Register
3 Screen Start 1 Upper Register
4 Cursor Address Lower Register
5 Cursor Address Upper Register
6 Screen Start 2 Lower Register
7 Screen Start 2 Upper Register
*/
switch (offset)
{
/* Status / Irq Register
--RV ZSRs
6+7 -- = ALWAYS 0
5 R = RDFLG (Status Register Only)
4 V = Vblank
3 Z = Line Zero
2 S = Split 1
1 R = Ready
0 s = Split 2
*/
case 0:
LOG2674(("Read Irq Register %02x %06x\n",m_irq_register,space.device().safe_pc()));
return m_irq_register;
case 1:
LOG2674(("Read Status Register %02X %06x\n",m_status_register,space.device().safe_pc()));
return m_status_register;
case 2: LOG2674(("Read Screen1_l Register %06x\n",space.device().safe_pc()));return m_screen1_l;
case 3: LOG2674(("Read Screen1_h Register %06x\n",space.device().safe_pc()));return m_screen1_h & 0x3f;
case 4: LOG2674(("Read Cursor_l Register %06x\n",space.device().safe_pc()));return m_cursor_l;
case 5: LOG2674(("Read Cursor_h Register %06x\n",space.device().safe_pc()));return m_cursor_h;
case 6: LOG2674(("Read Screen2_l Register %06x\n",space.device().safe_pc()));return m_screen2_l;
case 7: LOG2674(("Read Screen2_h Register %06x\n",space.device().safe_pc()));return m_screen2_h;
}
return 0xff;
}
WRITE8_MEMBER( scn2674_device::write )
{
/*
Offset: Purpose
0 Initialization Registers
1 Command Register
2 Screen Start 1 Lower Register
3 Screen Start 1 Upper Register
4 Cursor Address Lower Register
5 Cursor Address Upper Register
6 Screen Start 2 Lower Register
7 Screen Start 2 Upper Register
*/
switch (offset)
{
case 0:
write_init_regs(data);
break;
case 1:
write_command(data);
break;
case 2: m_screen1_l = data; break;
case 3:
m_screen1_h = data;
m_dbl1=(data & 0xc0)>>6;
if (m_IR0_double_ht_wd)
{
m_IR14_double_1 = m_dbl1;
m_screen1_h &= 0x3f;
LOG2674(("IR14 - Double 1 overridden %02x\n",m_IR14_double_1));
}
break;
case 4: m_cursor_l = data; break;
case 5: m_cursor_h = (data & 0x3f); break;
case 6: m_screen2_l = data; break;
case 7:
m_screen2_h = (data&0x3f);
m_spl1 = (data & 0x40);
m_spl2 = (data & 0x80);
break;
}
}
void scn2674_device::recompute_parameters()
{
m_hpixels_per_column = m_gfx_enabled ? m_gfx_hpixels_per_column : m_text_hpixels_per_column;
int horiz_pix_total = ((m_IR1_equalizing_constant + (m_IR2_horz_sync_width << 1)) << 1) * m_hpixels_per_column;
int vert_pix_total = m_IR4_rows_per_screen * m_IR0_scanline_per_char_row + m_IR3_vert_front_porch + m_IR3_vert_back_porch + m_IR7_vsync_width;
attoseconds_t refresh = m_screen->frame_period().attoseconds;
int max_visible_x = (m_IR5_character_per_row * m_hpixels_per_column) - 1;
int max_visible_y = (m_IR4_rows_per_screen * m_IR0_scanline_per_char_row) - 1;
LOG2674(("width %u height %u max_x %u max_y %u refresh %f\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, 1 / ATTOSECONDS_TO_DOUBLE(refresh)));
rectangle visarea;
visarea.set(0, max_visible_x, 0, max_visible_y);
m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh);
m_scanline_timer->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->scan_period());
}
void scn2674_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch(id)
{
case TIMER_SCANLINE:
{
int dw = m_IR0_double_ht_wd ? m_IR14_double_1 : 0; // double width
if(((m_display_enabled_scanline) || (m_display_enabled_field && !m_IR1_interlace_enable)) && (!m_display_enabled))
{
m_display_enabled = 1;
m_display_enabled_scanline = 0;
m_display_enabled_field = 0;
}
else if(!m_display_enabled)
break;
else
m_linecounter++;
// should be triggered at the start of each ROW (line zero for that row)
if(m_linecounter >= m_screen->height())
{
m_status_register |= 0x08;
if (m_irq_mask & 0x08)
{
LOG2674(("SCN2674 Line Zero\n"));
m_irq_state = 1;
m_irq_register |= 0x08;
m_irq_cb(1);
}
m_linecounter = 0;
m_address = (m_screen1_h << 8) | m_screen1_l;
}
if(m_linecounter == (m_IR4_rows_per_screen * m_IR0_scanline_per_char_row))
{
m_status_register |= 0x10;
if(m_irq_mask & 0x10)
{
LOG2674(("vblank irq\n"));
m_irq_state = 1;
m_irq_register |= 0x10;
m_irq_cb(1);
}
}
if(m_linecounter >= (m_IR4_rows_per_screen * m_IR0_scanline_per_char_row))
break;
if((m_linecounter == (m_IR12_split_register_1 * m_IR0_scanline_per_char_row)) && m_linecounter) /* Split Screen 1 */
{
m_status_register |= 0x04;
if(m_irq_mask & 0x04)
{
LOG2674(("SCN2674 Split Screen 1 irq\n"));
m_irq_state = 1;
m_irq_register |= 0x04;
m_irq_cb(1);
}
if(m_spl1)
m_address = (m_screen2_h << 8) | m_screen2_l;
if(!m_IR0_double_ht_wd)
dw = m_IR14_double_1;
}
if((m_linecounter == (m_IR13_split_register_2 * m_IR0_scanline_per_char_row)) && m_linecounter) /* Split Screen 2 */
{
m_status_register |= 0x01;
if(m_irq_mask & 0x01)
{
LOG2674(("SCN2674 Split Screen 2 irq\n"));
m_irq_state = 1;
m_irq_register |= 0x01;
m_irq_cb(1);
}
if(m_spl2)
m_address = (m_screen2_h << 8) | m_screen2_l;
if(!m_IR0_double_ht_wd)
dw = m_IR14_double_2;
}
int charrow = m_linecounter % m_IR0_scanline_per_char_row;
int tilerow = charrow;
if(m_IR2_row_table)
{
if(m_IR0_double_ht_wd)
dw = m_screen1_h >> 6;
if(!charrow)
{
UINT16 addr = (m_screen2_h << 8) | m_screen2_l;
UINT16 line = space().read_word(addr);
m_screen1_h = (line >> 8);
m_screen1_l = line & 0xff;
if(m_IR0_double_ht_wd)
{
dw = line >> 14;
line &= ~0xc000;
}
m_address = line;
addr += 2;
m_screen2_h = (addr >> 8) & 0x3f;
m_screen2_l = addr & 0xff;
}
}
if(dw == 2)
tilerow >>= 1;
else if(dw == 3)
tilerow = (charrow + m_IR0_scanline_per_char_row) >> 1;
UINT16 address = m_address;
for(int i = 0; i < m_IR5_character_per_row; i++)
{
if((address & 0x3fff) == ((m_cursor_h << 8) | m_cursor_l))
m_cursor_on = true;
if (!m_display_cb.isnull())
m_display_cb(m_bitmap,
i * m_hpixels_per_column,
m_linecounter,
tilerow,
space().read_byte(address),
address,
(charrow >= m_IR6_cursor_first_scanline) && m_cursor_on,
dw != 0,
m_gfx_enabled != 0,
charrow == m_IR7_cursor_underline_position,
m_IR7_cursor_blink && (m_screen->frame_number() & (m_IR7_cursor_rate_divisor ? 0x40 : 0x20)));
address = (address + 1) & 0xffff;
if(address > ((m_IR9_display_buffer_last_address << 10) | 0x3ff))
address = (m_IR9_display_buffer_first_address_MSB << 8) | m_IR8_display_buffer_first_address_LSB;
}
if(charrow == m_IR6_cursor_last_scanline)
m_cursor_on = false;
if(m_gfx_enabled || (charrow == (m_IR0_scanline_per_char_row - 1)))
m_address = address;
}
}
}
UINT32 scn2674_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
if (!m_display_enabled)
m_bitmap.fill(rgb_t::black);
else
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
return 0;
}

128
src/emu/video/scn2674.h Normal file
View File

@ -0,0 +1,128 @@
#ifndef SCN2674_H
#define SCN2674_h
#include "emu.h"
#define MCFG_SCN2674_VIDEO_ADD(_tag, _clock, _irq) \
MCFG_DEVICE_ADD(_tag, SCN2674_VIDEO, _clock) \
devcb = &scn2674_device::set_irq_callback(*device, DEVCB_##_irq);
#define MCFG_SCN2674_TEXT_CHARACTER_WIDTH(_value) \
scn2674_device::static_set_character_width(*device, _value);
#define MCFG_SCN2674_GFX_CHARACTER_WIDTH(_value) \
scn2674_device::static_set_gfx_character_width(*device, _value);
#define MCFG_SCN2674_DRAW_CHARACTER_CALLBACK_OWNER(_class, _method) \
scn2674_device::static_set_display_callback(*device, scn2674_device::draw_character_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner)));
#define SCN2674_DRAW_CHARACTER_MEMBER(_name) void _name(bitmap_rgb32 &bitmap, int x, int y, UINT8 linecount, UINT8 charcode, UINT16 address, UINT8 cursor, UINT8 dw, UINT8 lg, UINT8 ul, UINT8 blink)
class scn2674_device : public device_t,
public device_video_interface,
public device_memory_interface
{
public:
scn2674_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
typedef device_delegate<void (bitmap_rgb32 &bitmap, int x, int y, UINT8 linecount, UINT8 charcode, UINT16 address, UINT8 cursor, UINT8 dw, UINT8 lg, UINT8 ul, UINT8 blink)> draw_character_delegate;
// static configuration
template<class _Object> static devcb_base &set_irq_callback(device_t &device, _Object object) { return downcast<scn2674_device &>(device).m_irq_cb.set_callback(object); }
static void static_set_character_width(device_t &device, int value) { downcast<scn2674_device &>(device).m_text_hpixels_per_column = value; }
static void static_set_gfx_character_width(device_t &device, int value) { downcast<scn2674_device &>(device).m_gfx_hpixels_per_column = value; }
static void static_set_display_callback(device_t &device, draw_character_delegate callback) { downcast<scn2674_device &>(device).m_display_cb = callback; }
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_0) ? &m_space_config : NULL; }
protected:
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
bitmap_rgb32 m_bitmap;
devcb_write_line m_irq_cb;
UINT8 m_IR_pointer;
UINT8 m_screen1_l;
UINT8 m_screen1_h;
UINT8 m_cursor_l;
UINT8 m_cursor_h;
UINT8 m_screen2_l;
UINT8 m_screen2_h;
UINT8 m_irq_register;
UINT8 m_status_register;
UINT8 m_irq_mask;
UINT8 m_gfx_enabled;
UINT8 m_display_enabled;
UINT8 m_display_enabled_field;
UINT8 m_display_enabled_scanline;
UINT8 m_cursor_enabled;
UINT8 m_hpixels_per_column;
UINT8 m_text_hpixels_per_column;
UINT8 m_gfx_hpixels_per_column;
UINT8 m_IR0_double_ht_wd;
UINT8 m_IR0_scanline_per_char_row;
UINT8 m_IR0_sync_select;
UINT8 m_IR0_buffer_mode_select;
UINT8 m_IR1_interlace_enable;
UINT8 m_IR1_equalizing_constant;
UINT8 m_IR2_row_table;
UINT8 m_IR2_horz_sync_width;
UINT8 m_IR2_horz_back_porch;
UINT8 m_IR3_vert_front_porch;
UINT8 m_IR3_vert_back_porch;
UINT8 m_IR4_rows_per_screen;
UINT8 m_IR4_character_blink_rate_divisor;
UINT8 m_IR5_character_per_row;
UINT8 m_IR6_cursor_first_scanline;
UINT8 m_IR6_cursor_last_scanline;
UINT8 m_IR7_cursor_underline_position;
UINT8 m_IR7_cursor_rate_divisor;
UINT8 m_IR7_cursor_blink;
UINT8 m_IR7_vsync_width;
UINT8 m_IR8_display_buffer_first_address_LSB;
UINT8 m_IR9_display_buffer_first_address_MSB;
UINT8 m_IR9_display_buffer_last_address;
UINT8 m_IR10_display_pointer_address_lower;
UINT8 m_IR11_display_pointer_address_upper;
UINT8 m_IR11_reset_scanline_counter_on_scrollup;
UINT8 m_IR11_reset_scanline_counter_on_scrolldown;
UINT8 m_IR12_scroll_start;
UINT8 m_IR12_split_register_1;
UINT8 m_IR13_scroll_end;
UINT8 m_IR13_split_register_2;
UINT8 m_IR14_scroll_lines;
UINT8 m_IR14_double_1;
UINT8 m_IR14_double_2;
UINT8 m_spl1;
UINT8 m_spl2;
UINT8 m_dbl1;
int m_linecounter;
UINT16 m_address;
bool m_cursor_on;
UINT8 m_irq_state;
void write_init_regs(UINT8 data);
void write_command(UINT8 data);
void recompute_parameters();
draw_character_delegate m_display_cb;
emu_timer *m_scanline_timer;
const address_space_config m_space_config;
enum
{
TIMER_SCANLINE
};
};
extern const device_type SCN2674_VIDEO;
#endif

View File

@ -453,6 +453,14 @@ ifneq ($(filter SED1520,$(VIDEOS)),)
VIDEOOBJS+= $(VIDEOOBJ)/sed1520.o
endif
#-------------------------------------------------
#
#@src/emu/video/scn2674.h,VIDEOS += SCN2674
#-------------------------------------------------
ifneq ($(filter SCN2674,$(VIDEOS)),)
VIDEOOBJS+= $(VIDEOOBJ)/scn2674.o
endif
#-------------------------------------------------
#
#@src/emu/video/snes_ppu.h,VIDEOS += SNES_PPU

View File

@ -277,8 +277,7 @@ public:
DECLARE_MACHINE_START(mpu4_vid);
DECLARE_MACHINE_RESET(mpu4_vid);
DECLARE_VIDEO_START(mpu4_vid);
UINT32 screen_update_mpu4_vid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
TIMER_DEVICE_CALLBACK_MEMBER(scanline_timer_callback);
SCN2674_DRAW_CHARACTER_MEMBER(display_pixels);
DECLARE_WRITE_LINE_MEMBER(m6809_acia_irq);
DECLARE_WRITE_LINE_MEMBER(m68k_acia_irq);
DECLARE_WRITE_LINE_MEMBER(cpu1_ptm_irq);
@ -297,6 +296,8 @@ public:
DECLARE_WRITE8_MEMBER( vidcharacteriser_w );
DECLARE_READ8_MEMBER( vidcharacteriser_r );
DECLARE_WRITE_LINE_MEMBER(mpu_video_reset);
DECLARE_WRITE8_MEMBER( vram_w );
DECLARE_READ8_MEMBER( vram_r );
};
/*************************************
@ -324,7 +325,6 @@ WRITE_LINE_MEMBER(mpu4vid_state::update_mpu68_interrupts)
{
m_videocpu->set_input_line(1, m_m6840_irq_state ? ASSERT_LINE : CLEAR_LINE);
m_videocpu->set_input_line(2, m_m6850_irq_state ? ASSERT_LINE : CLEAR_LINE);
m_videocpu->set_input_line(3, m_scn2674->get_irq_state() ? ASSERT_LINE : CLEAR_LINE);
}
/* Communications with 6809 board */
@ -384,55 +384,30 @@ static const gfx_layout mpu4_vid_char_8x8_layout =
8*32
};
/* double height */
static const gfx_layout mpu4_vid_char_8x16_layout =
WRITE8_MEMBER(mpu4vid_state::vram_w)
{
8,16,
0x1000, /* 0x1000 tiles (128k of GFX RAM, 0x20 bytes per tile) */
4,
{ 0,8,16,24 },
{ 0,1,2,3,4,5,6,7 },
{ 0*32, 0*32, 1*32, 1*32, 2*32, 2*32, 3*32, 3*32, 4*32, 4*32, 5*32, 5*32, 6*32, 6*32, 7*32, 7*32},
8*32
};
m_vid_mainram[offset] = data | (m_vid_mainram[offset] & 0xff00);
}
/* double width */
static const gfx_layout mpu4_vid_char_16x8_layout =
READ8_MEMBER(mpu4vid_state::vram_r)
{
16,8,
0x1000, /* 0x1000 tiles (128k of GFX RAM, 0x20 bytes per tile) */
4,
{ 0,8,16,24 },
{ 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7 },
{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32},
8*32
};
return m_vid_mainram[offset];
}
static ADDRESS_MAP_START( mpu4_vram, AS_0, 8, mpu4vid_state )
AM_RANGE(0x0000, 0x7fff) AM_READWRITE(vram_r, vram_w)
ADDRESS_MAP_END
/* double height & width */
static const gfx_layout mpu4_vid_char_16x16_layout =
SCN2674_DRAW_CHARACTER_MEMBER(mpu4vid_state::display_pixels)
{
16,16,
0x1000, /* 0x1000 tiles (128k of GFX RAM, 0x20 bytes per tile) */
4,
{ 0,8,16,24 },
{ 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7 },
{ 0*32, 0*32, 1*32, 1*32, 2*32, 2*32, 3*32, 3*32, 4*32, 4*32, 5*32, 5*32, 6*32, 6*32, 7*32, 7*32},
8*32
};
UINT32 mpu4vid_state::screen_update_mpu4_vid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0, cliprect);
m_scn2674->scn2574_draw(machine(), bitmap, cliprect, m_vid_mainram );
return 0;
if(!lg)
{
UINT16 tile = m_vid_mainram[address & 0x7fff];
const UINT8 *line = m_gfxdecode->gfx(m_gfx_index+0)->get_data(tile & 0xfff);
int offset = m_gfxdecode->gfx(m_gfx_index+0)->rowbytes() * linecount;
for(int i = 0; i < 8; i++)
bitmap.pix32(y, x + i) = (tile >> 12) ? m_palette->pen(line[offset + i]) : m_palette->black_pen();
}
}
@ -447,17 +422,11 @@ WRITE16_MEMBER(mpu4vid_state::mpu4_vid_vidram_w )
COMBINE_DATA(&m_vid_vidram[offset]);
offset <<= 1;
m_gfxdecode->gfx(m_gfx_index+0)->mark_dirty(offset/0x20);
m_gfxdecode->gfx(m_gfx_index+1)->mark_dirty(offset/0x20);
m_gfxdecode->gfx(m_gfx_index+2)->mark_dirty(offset/0x20);
m_gfxdecode->gfx(m_gfx_index+3)->mark_dirty(offset/0x20);
}
VIDEO_START_MEMBER(mpu4vid_state,mpu4_vid)
{
/* if anything uses tile sizes other than 8x8 we can't really do it this way.. we'll have to draw tiles by hand.
All Barcrest stuff uses 8x8, son unless the BwB is different, we don't need to */
m_vid_vidram.allocate(0x20000/2);
memset(m_vid_vidram,0,0x20000);
@ -471,13 +440,6 @@ VIDEO_START_MEMBER(mpu4vid_state,mpu4_vid)
/* create the char set (gfx will then be updated dynamically from RAM) */
m_gfxdecode->set_gfx(m_gfx_index+0, global_alloc(gfx_element(m_palette, mpu4_vid_char_8x8_layout, reinterpret_cast<UINT8 *>(m_vid_vidram.target()), NATIVE_ENDIAN_VALUE_LE_BE(8,0), m_palette->entries() / 16, 0)));
m_gfxdecode->set_gfx(m_gfx_index+1, global_alloc(gfx_element(m_palette, mpu4_vid_char_8x16_layout, reinterpret_cast<UINT8 *>(m_vid_vidram.target()), NATIVE_ENDIAN_VALUE_LE_BE(8,0), m_palette->entries() / 16, 0)));
m_gfxdecode->set_gfx(m_gfx_index+2, global_alloc(gfx_element(m_palette, mpu4_vid_char_16x8_layout, reinterpret_cast<UINT8 *>(m_vid_vidram.target()), NATIVE_ENDIAN_VALUE_LE_BE(8,0), m_palette->entries() / 16, 0)));
m_gfxdecode->set_gfx(m_gfx_index+3, global_alloc(gfx_element(m_palette, mpu4_vid_char_16x16_layout, reinterpret_cast<UINT8 *>(m_vid_vidram.target()), NATIVE_ENDIAN_VALUE_LE_BE(8,0), m_palette->entries() / 16, 0)));
m_scn2674->init_stuff();
}
@ -1289,7 +1251,7 @@ static ADDRESS_MAP_START( mpu4_68k_map, AS_PROGRAM, 16, mpu4vid_state )
/* AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, mpu4_vid_scn2674_r, mpu4_vid_scn2674_w,0x00ff)
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
AM_RANGE(0xff8000, 0xff8001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
@ -1307,7 +1269,7 @@ static ADDRESS_MAP_START( mpu4oki_68k_map, AS_PROGRAM, 16, mpu4vid_state )
AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, control_w, 0x00ff)
AM_RANGE(0xa00000, 0xa00003) AM_READWRITE8(ef9369_r, ef9369_w,0x00ff)
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, mpu4_vid_scn2674_r, mpu4_vid_scn2674_w,0x00ff)
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
AM_RANGE(0xff8000, 0xff8001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
@ -1331,7 +1293,7 @@ static ADDRESS_MAP_START( bwbvid_68k_map, AS_PROGRAM, 16, mpu4vid_state )
// AM_RANGE(0xa00000, 0xa0000f) AM_READWRITE(bt471_r,bt471_w) //Some games use this
/* AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, mpu4_vid_scn2674_r, mpu4_vid_scn2674_w,0x00ff)
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
AM_RANGE(0xe00000, 0xe00001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
AM_RANGE(0xe00002, 0xe00003) AM_DEVREADWRITE8("acia6850_1", acia6850_device, data_r, data_w, 0x00ff)
@ -1349,7 +1311,7 @@ static ADDRESS_MAP_START( bwbvid5_68k_map, AS_PROGRAM, 16, mpu4vid_state )
//AM_RANGE(0xa00000, 0xa00003) AM_READWRITE8(bt471_r,bt471_w,0x00ff) Some games use this
/* AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, mpu4_vid_scn2674_r, mpu4_vid_scn2674_w,0x00ff)
AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
AM_RANGE(0xe00000, 0xe00001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
AM_RANGE(0xe00002, 0xe00003) AM_DEVREADWRITE8("acia6850_1", acia6850_device, data_r, data_w, 0x00ff)
@ -1383,12 +1345,6 @@ ADDRESS_MAP_END
TIMER_DEVICE_CALLBACK_MEMBER(mpu4vid_state::scanline_timer_callback)
{
m_scn2674->scn2674_do_scanline(machine(), param);
}
static MACHINE_CONFIG_START( mpu4_vid, mpu4vid_state )
MCFG_CPU_ADD("maincpu", M6809, MPU4_MASTER_CLOCK/4 )
MCFG_CPU_PROGRAM_MAP(mpu4_6809_map)
@ -1403,13 +1359,16 @@ static MACHINE_CONFIG_START( mpu4_vid, mpu4vid_state )
MCFG_SCREEN_VISIBLE_AREA(0, (63*8)+(0)-1, 0, (37*8)+0-1)
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_UPDATE_DRIVER(mpu4vid_state, screen_update_mpu4_vid)
MCFG_SCREEN_UPDATE_DEVICE("scn2674_vid", scn2674_device, screen_update)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", empty)
MCFG_SCN2674_VIDEO_ADD("scn2674_vid", 0, WRITELINE(mpu4vid_state, update_mpu68_interrupts));
MCFG_SCN2674_GFXDECODE("gfxdecode")
MCFG_SCN2674_PALETTE("palette")
MCFG_SCN2674_VIDEO_ADD("scn2674_vid", 0, INPUTLINE("video", 3))
MCFG_SCN2674_TEXT_CHARACTER_WIDTH(8)
MCFG_SCN2674_GFX_CHARACTER_WIDTH(8)
MCFG_SCN2674_DRAW_CHARACTER_CALLBACK_OWNER(mpu4vid_state, display_pixels)
MCFG_DEVICE_ADDRESS_MAP(AS_0, mpu4_vram)
MCFG_CPU_ADD("video", M68000, VIDEO_MASTER_CLOCK )
MCFG_CPU_PROGRAM_MAP(mpu4_68k_map)
@ -1444,9 +1403,6 @@ static MACHINE_CONFIG_START( mpu4_vid, mpu4vid_state )
MCFG_ACIA6850_TXD_HANDLER(DEVWRITELINE("acia6850_0", acia6850_device, write_rxd))
MCFG_ACIA6850_RTS_HANDLER(DEVWRITELINE("acia6850_0", acia6850_device, write_dcd))
MCFG_ACIA6850_IRQ_HANDLER(WRITELINE(mpu4vid_state, m68k_acia_irq))
// for the video timing
MCFG_TIMER_DRIVER_ADD_SCANLINE("scan_timer", mpu4vid_state, scanline_timer_callback, "screen", 0, 1)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( crmaze, mpu4_vid )

View File

@ -327,6 +327,7 @@ VIDEOS += PSX
VIDEOS += RAMDAC
#VIDEOS += S2636
VIDEOS += SAA5050
VIDEOS += SCN2674
#VIDEOS += SED1200
#VIDEOS += SED1330
#VIDEOS += SED1520
@ -960,7 +961,6 @@ $(MAMEOBJ)/barcrest.a: \
$(DRIVERS)/mpu4crystal.o \
$(DRIVERS)/mpu4bwb.o \
$(DRIVERS)/mpu4misc.o \
$(VIDEO)/scn2674.o \
$(DRIVERS)/mpu5hw.o $(DRIVERS)/mpu5.o \
$(VIDEO)/awpvid.o \
$(MACHINE)/meters.o \

View File

@ -1,760 +0,0 @@
/*
SCN2674 - Advanced Video Display Controller (AVDC) (Video Chip)
This is a somewhat terrible implementation and should probably just be rewritten from scratch
it is currently used by mpu4vid.c and still quite heavily tied to the behavior of that.
I don't know if the timing bugs with those games comes from this, or emulation of the other
MPU4 devices tho because even some of the non-video games seem laggy and prone to failure.
-- currently expects (from the host driver)
decoded gfx in regions 0,1,2,3 in various formats (normal, double height etc.)
eventually the chip should just handle this without the need to decode anything
a callback function for when the irqs are changed / updated
a call from the video start from your video start function
a call to the scanline function each scanline
a call to the video draw (with ram pointer) from a screen update function
video to be on the primary screen
this could all be simplified / changed, the chip can actually be hooked up in various ways
including working on a per scanline basis with almost no ram
*/
#include "emu.h"
#include "scn2674.h"
const device_type SCN2674_VIDEO = &device_creator<scn2674_device>;
scn2674_device::scn2674_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SCN2674_VIDEO, "SCN2674 VDC", tag, owner, clock, "scn2674_device", __FILE__),
m_interrupt_callback(*this),
m_gfxdecode(*this),
m_palette(*this)
{
}
//-------------------------------------------------
// static_set_gfxdecode_tag: Set the tag of the
// gfx decoder
//-------------------------------------------------
void scn2674_device::static_set_gfxdecode_tag(device_t &device, const char *tag)
{
downcast<scn2674_device &>(device).m_gfxdecode.set_tag(tag);
}
//-------------------------------------------------
// static_set_palette_tag: Set the tag of the
// palette device
//-------------------------------------------------
void scn2674_device::static_set_palette_tag(device_t &device, const char *tag)
{
downcast<scn2674_device &>(device).m_palette.set_tag(tag);
}
void scn2674_device::device_start()
{
// resolve callbacks
m_interrupt_callback.resolve_safe();
}
void scn2674_device::device_reset()
{
m_scn2674_IR_pointer= 0;
m_scn2674_screen1_l= 0;
m_scn2674_screen1_h= 0;
m_scn2674_cursor_l= 0;
m_scn2674_cursor_h= 0;
m_scn2674_screen2_l= 0;
m_scn2674_screen2_h= 0;
m_scn2674_irq_register= 0;
m_scn2674_status_register= 0;
m_scn2674_irq_mask= 0;
m_scn2674_gfx_enabled= 0;
m_scn2674_display_enabled= 0;
m_scn2674_display_enabled_field= 0;
m_scn2674_display_enabled_scanline= 0;
m_scn2674_cursor_enabled= 0;
m_IR0_scn2674_double_ht_wd= 0;
m_IR0_scn2674_scanline_per_char_row= 0;
m_IR0_scn2674_sync_select= 0;
m_IR0_scn2674_buffer_mode_select= 0;
m_IR1_scn2674_interlace_enable= 0;
m_IR1_scn2674_equalizing_constant= 0;
m_IR2_scn2674_row_table= 0;
m_IR2_scn2674_horz_sync_width= 0;
m_IR2_scn2674_horz_back_porch= 0;
m_IR3_scn2674_vert_front_porch= 0;
m_IR3_scn2674_vert_back_porch= 0;
m_IR4_scn2674_rows_per_screen= 0;
m_IR4_scn2674_character_blink_rate_divisor= 0;
m_IR5_scn2674_character_per_row= 0;
m_IR6_scn2674_cursor_first_scanline= 0;
m_IR6_scn2674_cursor_last_scanline= 0;
m_IR7_scn2674_cursor_underline_position= 0;
m_IR7_scn2674_cursor_rate_divisor= 0;
m_IR7_scn2674_cursor_blink= 0;
m_IR7_scn2674_vsync_width= 0;
m_IR8_scn2674_display_buffer_first_address_LSB= 0;
m_IR9_scn2674_display_buffer_first_address_MSB= 0;
m_IR9_scn2674_display_buffer_last_address= 0;
m_IR10_scn2674_display_pointer_address_lower= 0;
m_IR11_scn2674_display_pointer_address_upper= 0;
m_IR11_scn2674_reset_scanline_counter_on_scrollup= 0;
m_IR11_scn2674_reset_scanline_counter_on_scrolldown= 0;
m_IR12_scn2674_scroll_start= 0;
m_IR12_scn2674_split_register_1= 0;
m_IR13_scn2674_scroll_end= 0;
m_IR13_scn2674_split_register_2= 0;
m_IR14_scn2674_scroll_lines= 0;
m_IR14_scn2674_double_1= 0;
m_IR14_scn2674_double_2= 0;
m_scn2674_horz_front_porch= 0;
m_scn2674_spl1= 0;
m_scn2674_spl2= 0;
m_scn2674_dbl1= 0;
m_rowcounter= 0;
m_linecounter= 0;
m_scn2674_irq_state= 0;
}
// 15 Initialization Registers (8-bit each)
void scn2674_device::scn2674_write_init_regs(UINT8 data)
{
LOG2674(("scn2674_write_init_regs %02x %02x\n",m_scn2674_IR_pointer,data));
// m_scn2674_IR[m_scn2674_IR_pointer]=data;
switch ( m_scn2674_IR_pointer) /* display some debug info, set mame specific variables */
{
case 0:
m_IR0_scn2674_double_ht_wd = (data & 0x80)>>7;
m_IR0_scn2674_scanline_per_char_row = ((data & 0x78)>>3) + 1;
m_IR0_scn2674_sync_select = (data&0x04)>>2;
m_IR0_scn2674_buffer_mode_select = (data&0x03);
LOG2674(("IR0 - Double Ht Wd %02x\n",m_IR0_scn2674_double_ht_wd));//affects IR14 as well
LOG2674(("IR0 - Scanlines per Character Row %02x\n",m_IR0_scn2674_scanline_per_char_row));//value+1 = scanlines
if (m_IR0_scn2674_scanline_per_char_row != 8)
{
popmessage("Row size change, contact MAMEDEV");
}
LOG2674(("IR0 - Sync Select %02x\n",m_IR0_scn2674_sync_select));//1 = csync
LOG2674(("IR0 - Buffer Mode Select %02x\n",m_IR0_scn2674_buffer_mode_select)); //0 independent 1 transparent 2 shared 3 row
break;
case 1:
m_IR1_scn2674_interlace_enable = (data&0x80)>>7;
m_IR1_scn2674_equalizing_constant = (data&0x7f)+1;
LOG2674(("IR1 - Interlace Enable %02x\n",m_IR1_scn2674_interlace_enable));
LOG2674(("IR1 - Equalizing Constant %02i CCLKs\n",m_IR1_scn2674_equalizing_constant));
break;
case 2:
m_IR2_scn2674_row_table = (data&0x80)>>7;
m_IR2_scn2674_horz_sync_width = (((data&0x78)>>3)*2) + 2;
m_IR2_scn2674_horz_back_porch = ((data&0x07)*4) - 1;
LOG2674(("IR2 - Row Table %02x\n",m_IR2_scn2674_row_table));
LOG2674(("IR2 - Horizontal Sync Width %02i CCLKs\n",m_IR2_scn2674_horz_sync_width));
LOG2674(("IR2 - Horizontal Back Porch %02i CCLKs\n",m_IR2_scn2674_horz_back_porch));
break;
case 3:
m_IR3_scn2674_vert_front_porch = (((data&0xe0)>>5) * 4)+4 ;
m_IR3_scn2674_vert_back_porch = ((data&0x1f) * 2) + 4;
LOG2674(("IR3 - Vertical Front Porch %02i Lines\n",m_IR3_scn2674_vert_front_porch));
LOG2674(("IR3 - Vertical Back Porch %02i Lines\n",m_IR3_scn2674_vert_back_porch));
break;
case 4:
m_IR4_scn2674_rows_per_screen = (data&0x7f) + 1;
m_IR4_scn2674_character_blink_rate_divisor = ((data & 0x80)>>7 ? 128:64);
LOG2674(("IR4 - Rows Per Screen %02i\n",m_IR4_scn2674_rows_per_screen));
LOG2674(("IR4 - Character Blink Rate = 1/%02i\n",m_IR4_scn2674_character_blink_rate_divisor));
break;
case 5:
/* IR5 - Active Characters Per Row
cccc cccc
c = Characters Per Row */
m_IR5_scn2674_character_per_row = data + 1;
LOG2674(("IR5 - Active Characters Per Row %02i\n",m_IR5_scn2674_character_per_row));
break;
case 6:
m_IR6_scn2674_cursor_last_scanline = (data & 0x0f);
m_IR6_scn2674_cursor_first_scanline = (data & 0xf0)>>4;
LOG2674(("IR6 - First Line of Cursor %02x\n",m_IR6_scn2674_cursor_first_scanline));
LOG2674(("IR6 - Last Line of Cursor %02x\n",m_IR6_scn2674_cursor_last_scanline));
break;
case 7:
m_IR7_scn2674_cursor_underline_position = (data & 0x0f);
m_IR7_scn2674_cursor_rate_divisor = ((data & 0x10)>>4 ? 64:32);
m_IR7_scn2674_cursor_blink = (data & 0x20)>>5;
m_IR7_scn2674_vsync_width = vsync_table[(data & 0xC0)>>6];
LOG2674(("IR7 - Underline Position %02x\n",m_IR7_scn2674_cursor_underline_position));
LOG2674(("IR7 - Cursor rate 1/%02i\n",m_IR7_scn2674_cursor_rate_divisor));
LOG2674(("IR7 - Cursor blink %02x\n",m_IR7_scn2674_cursor_blink));
LOG2674(("IR7 - Vsync Width %02i Lines\n",m_IR7_scn2674_vsync_width));
break;
case 8:
m_IR8_scn2674_display_buffer_first_address_LSB = data;
LOG2674(("IR8 - Display Buffer First Address LSB %02x\n",m_IR8_scn2674_display_buffer_first_address_LSB));
break;
case 9:
m_IR9_scn2674_display_buffer_first_address_MSB = data & 0x0f;
m_IR9_scn2674_display_buffer_last_address = (data & 0xf0)>>4;
LOG2674(("IR9 - Display Buffer First Address MSB %02x\n",m_IR9_scn2674_display_buffer_first_address_MSB));
LOG2674(("IR9 - Display Buffer Last Address %02x\n",m_IR9_scn2674_display_buffer_last_address));
break;
case 10:
m_IR10_scn2674_display_pointer_address_lower = data;
LOG2674(("IR10 - Display Pointer Address Lower %02x\n",m_IR10_scn2674_display_pointer_address_lower));
break;
case 11:
m_IR11_scn2674_display_pointer_address_upper= data&0x3f;
m_IR11_scn2674_reset_scanline_counter_on_scrollup= (data&0x40 >> 6);
m_IR11_scn2674_reset_scanline_counter_on_scrolldown= (data&0x80 >> 7);
LOG2674(("IR11 - Display Pointer Address Lower %02x\n",m_IR11_scn2674_display_pointer_address_upper));
LOG2674(("IR11 - Reset Scanline Counter on Scroll Up %02x\n",m_IR11_scn2674_reset_scanline_counter_on_scrollup));
LOG2674(("IR11 - Reset Scanline Counter on Scroll Down %02x\n",m_IR11_scn2674_reset_scanline_counter_on_scrolldown));
break;
case 12:
m_IR12_scn2674_scroll_start = (data & 0x80)>>7;
m_IR12_scn2674_split_register_1 = (data & 0x7f);
LOG2674(("IR12 - Scroll Start %02x\n",m_IR12_scn2674_scroll_start));
LOG2674(("IR12 - Split Register 1 %02x\n",m_IR12_scn2674_split_register_1));
break;
case 13:
m_IR13_scn2674_scroll_end = (data & 0x80)>>7;
m_IR13_scn2674_split_register_2 = (data & 0x7f);
LOG2674(("IR13 - Scroll End %02x\n",m_IR13_scn2674_scroll_end));
LOG2674(("IR13 - Split Register 2 %02x\n",m_IR13_scn2674_split_register_2));
break;
case 14:
m_IR14_scn2674_scroll_lines = (data & 0x0f);
if (!m_IR0_scn2674_double_ht_wd)
{
m_IR14_scn2674_double_2 = (data & 0x30)>>4;
LOG2674(("IR14 - Double 2 %02x\n",m_IR14_scn2674_double_2));
}
//0 normal, 1, double width, 2, double width and double tops 3, double width and double bottoms
//1 affects SSR1, 2 affects SSR2
//If Double Height enabled in IR0, Screen start 1 upper (bits 7 and 6)replace Double 1, and Double 2 is unused
m_IR14_scn2674_double_1 = (data & 0xc0)>>6;
LOG2674(("IR14 - Double 1 %02x\n",m_IR14_scn2674_double_1));
LOG2674(("IR14 - Scroll Lines %02i\n",m_IR14_scn2674_scroll_lines));
break;
case 15: /* not valid! */
break;
}
m_scn2674_horz_front_porch = 2*(m_IR1_scn2674_equalizing_constant) + 3*(m_IR2_scn2674_horz_sync_width)-(m_IR5_scn2674_character_per_row) - m_IR2_scn2674_horz_back_porch;
LOG2674(("Horizontal Front Porch %02x CCLKs\n",m_scn2674_horz_front_porch));
m_scn2674_IR_pointer++;
if (m_scn2674_IR_pointer>14)m_scn2674_IR_pointer=14;
}
void scn2674_device::scn2674_write_command(running_machine &machine, UINT8 data)
{
UINT8 operand;
int i;
LOG2674(("scn2674_write_command %02x\n",data));
if (data==0x00)
{
/* master reset, configures registers */
LOG2674(("master reset\n"));
m_scn2674_IR_pointer=0;
m_scn2674_irq_register = 0x00;
m_scn2674_status_register = 0x20;//RDFLG activated
m_linecounter =0;
m_rowcounter =0;
m_scn2674_irq_mask = 0x00;
m_scn2674_gfx_enabled = 0;
m_scn2674_display_enabled = 0;
m_scn2674_cursor_enabled = 0;
m_IR2_scn2674_row_table = 0;
}
if ((data&0xf0)==0x10)
{
/* set IR pointer */
operand = data & 0x0f;
LOG2674(("set IR pointer %02x\n",operand));
m_scn2674_IR_pointer=operand;
}
/* ANY COMBINATION OF THESE ARE POSSIBLE */
if ((data&0xe3)==0x22)
{
/* Disable GFX */
LOG2674(("disable GFX %02x\n",data));
m_scn2674_gfx_enabled = 0;
}
if ((data&0xe3)==0x23)
{
/* Enable GFX */
LOG2674(("enable GFX %02x\n",data));
m_scn2674_gfx_enabled = 1;
}
if ((data&0xe9)==0x28)
{
/* Display off */
operand = data & 0x04;
m_scn2674_display_enabled = 0;
if (operand)
LOG2674(("display OFF - float DADD bus %02x\n",data));
else
LOG2674(("display OFF - no float DADD bus %02x\n",data));
}
if ((data&0xe9)==0x29)
{
/* Display on */
operand = data & 0x04;
if (operand)
{
m_scn2674_display_enabled_field = 1;
LOG2674(("display ON - next field %02x\n",data));
}
else
{
m_scn2674_display_enabled_scanline = 1;
LOG2674(("display ON - next scanline %02x\n",data));
}
}
if ((data&0xf1)==0x30)
{
/* Cursor Off */
LOG2674(("cursor off %02x\n",data));
m_scn2674_cursor_enabled = 0;
}
if ((data&0xf1)==0x31)
{
/* Cursor On */
LOG2674(("cursor on %02x\n",data));
m_scn2674_cursor_enabled = 1;
}
/* END */
if ((data&0xe0)==0x40)
{
/* Reset Interrupt / Status bit */
operand = data & 0x1f;
LOG2674(("reset interrupt / status bit %02x\n",operand));
m_scn2674_irq_register &= ~(data & 0x1f);
m_scn2674_status_register &= ~(data & 0x1f);
LOG2674(("IRQ Status after reset\n"));
LOG2674(("Split 2 IRQ: %d Active\n",(m_scn2674_irq_register>>0)&1));
LOG2674(("Ready IRQ: %d Active\n",(m_scn2674_irq_register>>1)&1));
LOG2674(("Split 1 IRQ: %d Active\n",(m_scn2674_irq_register>>2)&1));
LOG2674(("Line Zero IRQ: %d Active\n",(m_scn2674_irq_register>>3)&1));
LOG2674(("V-Blank IRQ: %d Active\n",(m_scn2674_irq_register>>4)&1));
m_scn2674_irq_state = 0;
for (i = 0; i < 5; i++)
{
if ((m_scn2674_irq_register>>i&1)&(m_scn2674_irq_mask>>i&1))
{
m_scn2674_irq_state = 1;
}
}
m_interrupt_callback(1);
}
if ((data&0xe0)==0x80)
{
/* Disable Interrupt mask*/
operand = data & 0x1f;
m_scn2674_irq_mask &= ~(operand);
LOG2674(("IRQ Mask after disable %x\n",operand));
LOG2674(("Split 2 IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>0)&1));
LOG2674(("Ready IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>1)&1));
LOG2674(("Split 1 IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>2)&1));
LOG2674(("Line Zero IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>3)&1));
LOG2674(("V-Blank IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>4)&1));
}
if ((data&0xe0)==0x60)
{
/* Enable Interrupt mask*/
operand = data & 0x1f;
m_scn2674_irq_mask |= (data & 0x1f);
LOG2674(("IRQ Mask after enable %x\n",operand));
LOG2674(("Split 2 IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>0)&1));
LOG2674(("Ready IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>1)&1));
LOG2674(("Split 1 IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>2)&1));
LOG2674(("Line Zero IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>3)&1));
LOG2674(("V-Blank IRQ: %d Unmasked\n",(m_scn2674_irq_mask>>4)&1));
}
/* Delayed Commands */
/* These set 0x20 in status register when done */
if (data == 0xa4)
{
/* read at pointer address */
LOG2674(("DELAYED read at pointer address %02x\n",data));
}
if (data == 0xa2)
{
/* write at pointer address */
LOG2674(("DELAYED write at pointer address %02x\n",data));
}
if (data == 0xa9)
{
/* increase cursor address */
LOG2674(("DELAYED increase cursor address %02x\n",data));
}
if (data == 0xac)
{
/* read at cursor address */
LOG2674(("DELAYED read at cursor address %02x\n",data));
}
if (data == 0xaa)
{
/* write at cursor address */
LOG2674(("DELAYED write at cursor address %02x\n",data));
}
if (data == 0xad)
{
/* read at cursor address + increment */
LOG2674(("DELAYED read at cursor address+increment %02x\n",data));
}
if (data == 0xab)
{
/* write at cursor address + increment */
LOG2674(("DELAYED write at cursor address+increment %02x\n",data));
}
if (data == 0xbb)
{
/* write from cursor address to pointer address */
LOG2674(("DELAYED write from cursor address to pointer address %02x\n",data));
}
if (data == 0xbd)
{
/* read from cursor address to pointer address */
LOG2674(("DELAYED read from cursor address to pointer address %02x\n",data));
}
}
READ8_MEMBER( scn2674_device::mpu4_vid_scn2674_r )
{
/*
Offset: Purpose
0 Interrupt Register
1 Status Register
2 Screen Start 1 Lower Register
3 Screen Start 1 Upper Register
4 Cursor Address Lower Register
5 Cursor Address Upper Register
6 Screen Start 2 Lower Register
7 Screen Start 2 Upper Register
*/
switch (offset)
{
/* Status / Irq Register
--RV ZSRs
6+7 -- = ALWAYS 0
5 R = RDFLG (Status Register Only)
4 V = Vblank
3 Z = Line Zero
2 S = Split 1
1 R = Ready
0 s = Split 2
*/
case 0:
LOG2674(("Read Irq Register %02x %06x\n",m_scn2674_irq_register,space.device().safe_pc()));
return m_scn2674_irq_register;
case 1:
LOG2674(("Read Status Register %02X %06x\n",m_scn2674_status_register,space.device().safe_pc()));
return m_scn2674_status_register;
case 2: LOG2674(("Read Screen1_l Register %06x\n",space.device().safe_pc()));return m_scn2674_screen1_l;
case 3: LOG2674(("Read Screen1_h Register %06x\n",space.device().safe_pc()));return m_scn2674_screen1_h;
case 4: LOG2674(("Read Cursor_l Register %06x\n",space.device().safe_pc()));return m_scn2674_cursor_l;
case 5: LOG2674(("Read Cursor_h Register %06x\n",space.device().safe_pc()));return m_scn2674_cursor_h;
case 6: LOG2674(("Read Screen2_l Register %06x\n",space.device().safe_pc()));return m_scn2674_screen2_l;
case 7: LOG2674(("Read Screen2_h Register %06x\n",space.device().safe_pc()));return m_scn2674_screen2_h;
}
return 0xff;
}
WRITE8_MEMBER( scn2674_device::mpu4_vid_scn2674_w )
{
/*
Offset: Purpose
0 Initialization Registers
1 Command Register
2 Screen Start 1 Lower Register
3 Screen Start 1 Upper Register
4 Cursor Address Lower Register
5 Cursor Address Upper Register
6 Screen Start 2 Lower Register
7 Screen Start 2 Upper Register
*/
switch (offset)
{
case 0:
scn2674_write_init_regs(data);
break;
case 1:
scn2674_write_command(space.machine(), data);
break;
case 2: m_scn2674_screen1_l = data; break;
case 3:
m_scn2674_screen1_h = (data&0x3f);//uppermost two bytes not part of register
m_scn2674_dbl1=(data & 0xc0)>>6;
if (m_IR0_scn2674_double_ht_wd)
{
m_IR14_scn2674_double_1 = m_scn2674_dbl1;
LOG2674(("IR14 - Double 1 overridden %02x\n",m_IR14_scn2674_double_1));
}
break;
case 4: m_scn2674_cursor_l = data; break;
case 5: m_scn2674_cursor_h = data; break;
case 6: m_scn2674_screen2_l = data; break;
case 7:
m_scn2674_screen2_h = (data&0x3f);
m_scn2674_spl1 = (data & 0x40);
m_scn2674_spl2 = (data & 0x80);
break;
}
}
void scn2674_device::scn2674_line(running_machine &machine)
{
if (m_linecounter==0)/* Ready - this triggers for the first scanline of the screen */
{
m_scn2674_status_register |= 0x02;
if (m_scn2674_irq_mask&0x02)
{
LOG2674(("SCN2674 Ready\n"));
m_scn2674_irq_state = 1;
m_scn2674_irq_register |= 0x02;
m_interrupt_callback(1);
}
}
// should be triggered at the start of each ROW (line zero for that row)
if (( m_linecounter%8 == 0)&& (m_linecounter < 297) )
{
m_scn2674_status_register |= 0x08;
if (m_scn2674_irq_mask&0x08)
{
LOG2674(("SCN2674 Line Zero\n"));
m_scn2674_irq_state = 1;
m_scn2674_irq_register |= 0x08;
m_interrupt_callback(1);
}
m_rowcounter = ((m_rowcounter+1)% 37);//Not currently used
}
// this is ROWS not scanlines!!
if ((m_linecounter == m_IR12_scn2674_split_register_1*8)&&(m_linecounter != 0))
/* Split Screen 1 */
{
if (m_scn2674_spl1)
{
popmessage("Split screen 1 address shift required, contact MAMEDEV");
}
m_scn2674_status_register |= 0x04;
if (m_scn2674_irq_mask&0x04)
{
machine.first_screen()->update_partial(m_linecounter);
m_scn2674_irq_register |= 0x04;
LOG2674(("SCN2674 Split Screen 1\n"));
m_scn2674_irq_state = 1;
m_interrupt_callback(1);
// machine.first_screen()->update_partial(m_linecounter);
}
}
// this is in ROWS not scanlines!!!
if ((m_linecounter == m_IR13_scn2674_split_register_2*8)&&(m_linecounter != 0))
/* Split Screen 2 */
{
if (m_scn2674_spl2)
{
popmessage("Split screen 2 address shift required, contact MAMEDEV");
}
m_scn2674_status_register |= 0x01;
if (m_scn2674_irq_mask&0x01)
{
machine.first_screen()->update_partial(m_linecounter);
LOG2674(("SCN2674 Split Screen 2 irq\n"));
m_scn2674_irq_state = 1;
m_scn2674_irq_register |= 0x01;
m_interrupt_callback(1);
//machine.first_screen()->update_partial(m_linecounter);
}
}
if (m_linecounter==296)//front porch
{
m_scn2674_status_register |= 0x10;
if (m_scn2674_irq_mask&0x10)
{
LOG2674(("vblank irq\n"));
m_scn2674_irq_state = 1;
m_scn2674_irq_register |= 0x10;
m_interrupt_callback(1);
}
}
}
// scanline timer
void scn2674_device::scn2674_do_scanline(running_machine &machine, int scanline)
{
//This represents the scanline counter in the SCN2674. Note that we ignore the horizontal blanking
if (((m_scn2674_display_enabled_scanline) || (m_scn2674_display_enabled_field && (m_IR1_scn2674_interlace_enable == 0)))&&(!m_scn2674_display_enabled))
{
m_scn2674_display_enabled = 1;
m_scn2674_display_enabled_scanline = 0;
m_scn2674_display_enabled_field = 0;
}
if (m_scn2674_display_enabled)
{
m_linecounter = scanline;
}
else
{
m_linecounter =297;//hold the counter in the vsync point, it's not clear whether this is done or not
}
scn2674_line(machine);
// timer.machine().scheduler().synchronize();
}
////// screen update
template<class _BitmapClass>
void scn2674_device::scn2574_draw_common( running_machine &machine, _BitmapClass &bitmap, const rectangle &cliprect, UINT16* vid_mainram )
{
int x, y/*, count = 0*/;
/* this is in main ram.. i think it must transfer it out of here??? */
/* count = 0x0018b6/2; - crmaze count = 0x004950/2; - turnover */
/* we're in row table mode...thats why */
for(y = 0; y < m_IR4_scn2674_rows_per_screen; y++)
{
int screen2_base = (m_scn2674_screen2_h << 8) | m_scn2674_screen2_l;
UINT16 rowbase = (vid_mainram[1+screen2_base+(y*2)]<<8)|vid_mainram[screen2_base+(y*2)];
int dbl_size=0;
int gfxregion = 0;
if (m_IR0_scn2674_double_ht_wd)
{
dbl_size = (rowbase & 0xc000)>>14; /* ONLY if double size is enabled.. otherwise it can address more chars given more RAM */
}
if (dbl_size&2)
{
gfxregion = 1;
}
for(x = 0; x < m_IR5_scn2674_character_per_row; x++)
{
UINT16 tiledat;
UINT16 attr;
tiledat = vid_mainram[(rowbase+x)&0x7fff];
attr = tiledat >>12;
if (attr)
m_gfxdecode->gfx(gfxregion)->opaque(bitmap,cliprect,tiledat,0,0,0,(x*8),(y*8));
}
if (dbl_size&2)
{
y++;/* skip a row? */
}
}
}
void scn2674_device::scn2574_draw( running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect, UINT16* vid_mainram )
{ scn2574_draw_common(machine, bitmap, cliprect, vid_mainram); }
void scn2674_device::scn2574_draw( running_machine &machine, bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16* vid_mainram )
{ scn2574_draw_common(machine, bitmap, cliprect, vid_mainram); }
void scn2674_device::init_stuff()
{
// from video start
m_scn2674_IR_pointer = 0;
}

View File

@ -1,127 +0,0 @@
#define S674VERBOSE 0
#define LOG2674(x) do { if (S674VERBOSE) logerror x; } while (0)
#define MCFG_SCN2674_VIDEO_ADD(_tag, _clock, _irq) \
MCFG_DEVICE_ADD(_tag, SCN2674_VIDEO, _clock) \
downcast<scn2674_device *>(device)->set_callbacks(DEVCB_##_irq);
#define MCFG_SCN2674_GFXDECODE(_gfxtag) \
scn2674_device::static_set_gfxdecode_tag(*device, "^" _gfxtag);
#define MCFG_SCN2674_PALETTE(_palette_tag) \
scn2674_device::static_set_palette_tag(*device, "^" _palette_tag);
typedef void (*s2574_interrupt_callback_func)(running_machine &machine);
static const UINT8 vsync_table[4] = {3,1,5,7}; //Video related
class scn2674_device : public device_t
{
public:
scn2674_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration
static void static_set_gfxdecode_tag(device_t &device, const char *tag);
static void static_set_palette_tag(device_t &device, const char *tag);
template<class _irq> void set_callbacks(_irq irq) {
m_interrupt_callback.set_callback(irq);
}
// int m_gfx_index;
DECLARE_READ8_MEMBER( mpu4_vid_scn2674_r );
DECLARE_WRITE8_MEMBER( mpu4_vid_scn2674_w );
UINT8 get_irq_state( void )
{
return m_scn2674_irq_state;
}
void scn2574_draw(running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect, UINT16* vid_mainram);
void scn2574_draw(running_machine &machine, bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16* vid_mainram);
void init_stuff();
void scn2674_do_scanline(running_machine &machine, int scanline);
protected:
virtual void device_start();
virtual void device_reset();
devcb_write_line m_interrupt_callback;
UINT8 m_scn2674_IR_pointer;
UINT8 m_scn2674_screen1_l;
UINT8 m_scn2674_screen1_h;
UINT8 m_scn2674_cursor_l;
UINT8 m_scn2674_cursor_h;
UINT8 m_scn2674_screen2_l;
UINT8 m_scn2674_screen2_h;
UINT8 m_scn2674_irq_register;
UINT8 m_scn2674_status_register;
UINT8 m_scn2674_irq_mask;
UINT8 m_scn2674_gfx_enabled;
UINT8 m_scn2674_display_enabled;
UINT8 m_scn2674_display_enabled_field;
UINT8 m_scn2674_display_enabled_scanline;
UINT8 m_scn2674_cursor_enabled;
UINT8 m_IR0_scn2674_double_ht_wd;
UINT8 m_IR0_scn2674_scanline_per_char_row;
UINT8 m_IR0_scn2674_sync_select;
UINT8 m_IR0_scn2674_buffer_mode_select;
UINT8 m_IR1_scn2674_interlace_enable;
UINT8 m_IR1_scn2674_equalizing_constant;
UINT8 m_IR2_scn2674_row_table;
UINT8 m_IR2_scn2674_horz_sync_width;
UINT8 m_IR2_scn2674_horz_back_porch;
UINT8 m_IR3_scn2674_vert_front_porch;
UINT8 m_IR3_scn2674_vert_back_porch;
UINT8 m_IR4_scn2674_rows_per_screen;
UINT8 m_IR4_scn2674_character_blink_rate_divisor;
UINT8 m_IR5_scn2674_character_per_row;
UINT8 m_IR6_scn2674_cursor_first_scanline;
UINT8 m_IR6_scn2674_cursor_last_scanline;
UINT8 m_IR7_scn2674_cursor_underline_position;
UINT8 m_IR7_scn2674_cursor_rate_divisor;
UINT8 m_IR7_scn2674_cursor_blink;
UINT8 m_IR7_scn2674_vsync_width;
UINT8 m_IR8_scn2674_display_buffer_first_address_LSB;
UINT8 m_IR9_scn2674_display_buffer_first_address_MSB;
UINT8 m_IR9_scn2674_display_buffer_last_address;
UINT8 m_IR10_scn2674_display_pointer_address_lower;
UINT8 m_IR11_scn2674_display_pointer_address_upper;
UINT8 m_IR11_scn2674_reset_scanline_counter_on_scrollup;
UINT8 m_IR11_scn2674_reset_scanline_counter_on_scrolldown;
UINT8 m_IR12_scn2674_scroll_start;
UINT8 m_IR12_scn2674_split_register_1;
UINT8 m_IR13_scn2674_scroll_end;
UINT8 m_IR13_scn2674_split_register_2;
UINT8 m_IR14_scn2674_scroll_lines;
UINT8 m_IR14_scn2674_double_1;
UINT8 m_IR14_scn2674_double_2;
UINT8 m_scn2674_horz_front_porch;
UINT8 m_scn2674_spl1;
UINT8 m_scn2674_spl2;
UINT8 m_scn2674_dbl1;
int m_rowcounter;
int m_linecounter;
UINT8 m_scn2674_irq_state;
void scn2674_write_init_regs(UINT8 data);
void scn2674_write_command(running_machine &machine, UINT8 data);
void scn2674_line(running_machine &machine);
template<class _BitmapClass>
void scn2574_draw_common( running_machine &machine, _BitmapClass &bitmap, const rectangle &cliprect, UINT16* vid_mainram );
private:
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
};
extern const device_type SCN2674_VIDEO;

View File

@ -20,6 +20,7 @@
#include "machine/mc146818.h"
#include "sound/speaker.h"
#include "video/scn2674.h"
#include "formats/pc_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@ -38,6 +39,8 @@ public:
m_fdc(*this, "fdc"),
m_rtc(*this, "rtc"),
m_crtc(*this, "crtc"),
m_palette(*this, "palette"),
m_gfxdecode(*this, "gfxdecode"),
m_vram(*this, "vram"),
m_charram(8*1024)
{ }
@ -46,17 +49,25 @@ public:
TIMER_DEVICE_CALLBACK_MEMBER( timer0_tick );
DECLARE_WRITE_LINE_MEMBER( i186_timer1_w );
DECLARE_READ8_MEMBER( charram_r );
DECLARE_WRITE8_MEMBER( charram_w );
DECLARE_READ16_MEMBER( nmi_io_r );
DECLARE_WRITE16_MEMBER( nmi_io_w );
DECLARE_READ8_MEMBER( nmi_io_r );
DECLARE_WRITE8_MEMBER( nmi_io_w );
DECLARE_READ8_MEMBER( rtc_r );
DECLARE_WRITE8_MEMBER( rtc_w );
DECLARE_READ8_MEMBER( stat_r );
DECLARE_WRITE8_MEMBER( stat_w );
DECLARE_READ8_MEMBER( led_r );
DECLARE_WRITE8_MEMBER( led_w );
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
DECLARE_READ8_MEMBER( detect_r );
DECLARE_WRITE8_MEMBER( detect_w );
DECLARE_READ8_MEMBER( dskctl_r );
DECLARE_WRITE8_MEMBER( dskctl_w );
DECLARE_READ8_MEMBER( mcu_r );
DECLARE_WRITE8_MEMBER( mcu_w );
DECLARE_WRITE8_MEMBER( vram_sw_w );
DECLARE_READ16_MEMBER( vram_r );
DECLARE_WRITE16_MEMBER( vram_w );
SCN2674_DRAW_CHARACTER_MEMBER(display_pixels);
DECLARE_FLOPPY_FORMATS( floppy_formats );
protected:
// driver_device overrides
@ -72,9 +83,11 @@ private:
required_device<wd2793_t> m_fdc;
required_device<mc146818_device> m_rtc;
required_device<scn2674_device> m_crtc;
required_device<palette_device> m_palette;
required_device<gfxdecode_device> m_gfxdecode;
required_shared_ptr<UINT16> m_vram;
dynamic_buffer m_charram;
UINT8 m_stat, m_led;
UINT8 m_stat, m_led, m_dskctl, m_vram_sw;
};
@ -96,13 +109,15 @@ static const gfx_layout pcd_charlayout =
};
void pcd_state::machine_start()
{
machine().device<gfxdecode_device>("gfxdecode")->set_gfx(0, global_alloc(gfx_element(machine().device<palette_device>("palette"), pcd_charlayout, m_charram, 0, 2, 0)));
m_gfxdecode->set_gfx(0, global_alloc(gfx_element(machine().device<palette_device>("palette"), pcd_charlayout, m_charram, 0, 1, 0)));
}
void pcd_state::machine_reset()
{
m_stat = 0;
m_led = 0;
m_dskctl = 0;
m_vram_sw = 1;
}
READ8_MEMBER( pcd_state::irq_callback )
@ -121,31 +136,42 @@ WRITE_LINE_MEMBER( pcd_state::i186_timer1_w )
m_speaker->level_w(state);
}
READ8_MEMBER( pcd_state::charram_r )
READ16_MEMBER( pcd_state::vram_r )
{
return m_charram[offset >> 1];
return m_vram[offset];
}
WRITE8_MEMBER( pcd_state::charram_w )
WRITE16_MEMBER( pcd_state::vram_w )
{
m_charram[offset >> 1] = data;
if(m_vram_sw)
COMBINE_DATA(&m_vram[offset]);
else if(mem_mask & 0xff)
{
m_charram[offset & 0x1fff] = data;
m_gfxdecode->gfx(0)->mark_dirty(offset/16);
}
}
READ16_MEMBER( pcd_state::nmi_io_r )
WRITE8_MEMBER( pcd_state::vram_sw_w )
{
m_vram_sw = data & 1;
}
READ8_MEMBER( pcd_state::nmi_io_r )
{
if(space.debugger_access())
return 0;
logerror("%s: unmapped %s %04x\n", machine().describe_context(), space.name(), offset << 1);
logerror("%s: unmapped %s %04x\n", machine().describe_context(), space.name(), offset);
m_stat |= 8;
m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
return 0;
}
WRITE16_MEMBER( pcd_state::nmi_io_w )
WRITE8_MEMBER( pcd_state::nmi_io_w )
{
if(space.debugger_access())
return;
logerror("%s: unmapped %s %04x\n", machine().describe_context(), space.name(), offset << 1);
logerror("%s: unmapped %s %04x\n", machine().describe_context(), space.name(), offset);
m_stat |= 8;
m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
}
@ -169,12 +195,60 @@ READ8_MEMBER( pcd_state::stat_r )
WRITE8_MEMBER( pcd_state::stat_w )
{
m_stat = data;
m_stat &= ~data;
}
READ8_MEMBER( pcd_state::detect_r )
{
return 0;
}
WRITE8_MEMBER( pcd_state::detect_w )
{
}
READ8_MEMBER( pcd_state::mcu_r )
{
return 0x20;
}
WRITE8_MEMBER( pcd_state::mcu_w )
{
}
READ8_MEMBER( pcd_state::dskctl_r )
{
return m_dskctl;
}
WRITE8_MEMBER( pcd_state::dskctl_w )
{
floppy_image_device *floppy0 = m_fdc->subdevice<floppy_connector>("0")->get_device();
floppy_image_device *floppy1 = m_fdc->subdevice<floppy_connector>("1")->get_device();
if((data & 1) && floppy0)
m_fdc->set_floppy(floppy0);
if(floppy0)
{
floppy0->mon_w(!(data & 4));
floppy0->ss_w((data & 8) != 0);
}
if(floppy1)
{
floppy1->mon_w(!(data & 4));
floppy1->ss_w((data & 8) != 0);
}
m_dskctl = data;
}
READ8_MEMBER( pcd_state::led_r )
{
return m_led;
// DIPs?
// 0x01 no mmu
// 0x10 enter monitor after post
// 0x20 enter monitor before post
return 0x01;
}
WRITE8_MEMBER( pcd_state::led_w )
@ -185,11 +259,21 @@ WRITE8_MEMBER( pcd_state::led_w )
m_led = data;
}
UINT32 pcd_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
SCN2674_DRAW_CHARACTER_MEMBER(pcd_state::display_pixels)
{
//bitmap.fill(0, cliprect);
m_crtc->scn2574_draw(machine(), bitmap, cliprect, m_vram);
return 0;
if(lg)
{
UINT16 data = m_vram[address];
data = (data >> 8) | (data << 8);
for(int i = 0; i < 16; i++)
bitmap.pix32(y, x + i) = m_palette->pen((data & (1 << (16 - i))) ? 1 : 0);
}
else
{
UINT8 data = m_charram[(m_vram[address] & 0xff) * 16 + linecount];
for(int i = 0; i < 8; i++)
bitmap.pix32(y, x + i) = m_palette->pen((data & (1 << (8 - i))) ? 1 : 0);
}
}
//**************************************************************************
@ -198,29 +282,33 @@ UINT32 pcd_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, con
static ADDRESS_MAP_START( pcd_map, AS_PROGRAM, 16, pcd_state )
AM_RANGE(0x00000, 0x3ffff) AM_RAM // fixed 256k for now
AM_RANGE(0xf0000, 0xf7fff) AM_RAM AM_SHARE("vram")
//AM_RANGE(0xf7000, 0xfbfff) AM_READWRITE8(charram_r, charram_w, 0xffff)
AM_RANGE(0xf0000, 0xf7fff) AM_READWRITE(vram_r, vram_w) AM_SHARE("vram")
AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION("bios", 0)
AM_RANGE(0x00000, 0xfffff) AM_READWRITE(nmi_io_r, nmi_io_w)
AM_RANGE(0x00000, 0xfffff) AM_READWRITE8(nmi_io_r, nmi_io_w, 0xffff)
ADDRESS_MAP_END
static ADDRESS_MAP_START( pcd_io, AS_IO, 16, pcd_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0xefff) AM_READWRITE8(nmi_io_r, nmi_io_w, 0xffff)
AM_RANGE(0xf000, 0xf7ff) AM_RAM AM_SHARE("nvram")
AM_RANGE(0xf800, 0xf801) AM_DEVREADWRITE8("pic1", pic8259_device, read, write, 0xffff)
AM_RANGE(0xf820, 0xf821) AM_DEVREADWRITE8("pic2", pic8259_device, read, write, 0xffff)
AM_RANGE(0xf840, 0xf841) AM_READWRITE8(stat_r, stat_w, 0x00ff)
AM_RANGE(0xf840, 0xf841) AM_READWRITE8(led_r, led_w, 0xff00)
AM_RANGE(0xf880, 0xf8bf) AM_READWRITE8(rtc_r, rtc_w, 0xffff)
AM_RANGE(0xf900, 0xf907) AM_DEVREADWRITE8("fdc", wd2793_t, read, write, 0xffff)
AM_RANGE(0xf900, 0xf903) AM_DEVREADWRITE8("fdc", wd2793_t, read, write, 0xffff)
AM_RANGE(0xf904, 0xf905) AM_READWRITE8(dskctl_r, dskctl_w, 0x00ff)
//AM_RANGE(0xf940, 0xf943) scsi
AM_RANGE(0xf980, 0xf98f) AM_DEVWRITE8("crtc", scn2674_device, write, 0x00ff)
AM_RANGE(0xf980, 0xf98f) AM_DEVREAD8("crtc", scn2674_device, read, 0xff00)
AM_RANGE(0xf9a0, 0xf9a1) AM_WRITE8(vram_sw_w, 0x00ff)
AM_RANGE(0xf9b0, 0xf9b3) AM_READWRITE8(mcu_r, mcu_w, 0x00ff) // 8741 comms
AM_RANGE(0xf9c0, 0xf9c3) AM_DEVREADWRITE8("usart1",mc2661_device,read,write,0xffff) // UARTs
AM_RANGE(0xf9d0, 0xf9d3) AM_DEVREADWRITE8("usart2",mc2661_device,read,write,0xffff)
AM_RANGE(0xf9e0, 0xf9e3) AM_DEVREADWRITE8("usart3",mc2661_device,read,write,0xffff)
AM_RANGE(0xf980, 0xf987) AM_DEVWRITE8("crtc", scn2674_device, mpu4_vid_scn2674_w, 0x00ff)
AM_RANGE(0xf980, 0xf987) AM_DEVREAD8("crtc", scn2674_device, mpu4_vid_scn2674_r, 0xff00)
// AM_RANGE(0xfa00, 0xfa7f) // pcs4-n (peripheral chip select)
AM_RANGE(0x0000, 0xffff) AM_READWRITE(nmi_io_r, nmi_io_w)
AM_RANGE(0xfb00, 0xfb01) AM_READWRITE8(detect_r, detect_w, 0xff00) // expansion card detection?
AM_RANGE(0xfb00, 0xffff) AM_READWRITE8(nmi_io_r, nmi_io_w, 0xffff)
ADDRESS_MAP_END
@ -231,8 +319,13 @@ ADDRESS_MAP_END
static SLOT_INTERFACE_START( pcd_floppies )
SLOT_INTERFACE("55f", TEAC_FD_55F)
SLOT_INTERFACE("55g", TEAC_FD_55G)
SLOT_INTERFACE("525dsqd", FLOPPY_525_QD) // the devices above cause a crash in floppy_image_format_t::generate_track_from_levels
SLOT_INTERFACE_END
FLOPPY_FORMATS_MEMBER( pcd_state::floppy_formats )
FLOPPY_PC_FORMAT
FLOPPY_FORMATS_END
static MACHINE_CONFIG_START( pcd, pcd_state )
MCFG_CPU_ADD("maincpu", I80186, XTAL_16MHz)
MCFG_CPU_PROGRAM_MAP(pcd_map)
@ -258,13 +351,13 @@ static MACHINE_CONFIG_START( pcd, pcd_state )
MCFG_OMTI5100_ADD("sasi")
// floppy disk controller
MCFG_WD2793x_ADD("fdc", XTAL_16MHz/8)
MCFG_WD2793x_ADD("fdc", XTAL_16MHz/8/2)
MCFG_WD_FDC_INTRQ_CALLBACK(DEVWRITELINE("pic1", pic8259_device, ir6_w))
MCFG_WD_FDC_DRQ_CALLBACK(DEVWRITELINE("maincpu", i80186_cpu_device, drq1_w))
// floppy drives
MCFG_FLOPPY_DRIVE_ADD("fdc:0", pcd_floppies, "55g", floppy_image_device::default_floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("fdc:1", pcd_floppies, "55g", floppy_image_device::default_floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("fdc:0", pcd_floppies, "525dsqd", pcd_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("fdc:1", pcd_floppies, "525dsqd", pcd_state::floppy_formats)
// usart
MCFG_DEVICE_ADD("usart1", MC2661, XTAL_4_9152MHz)
@ -284,14 +377,15 @@ static MACHINE_CONFIG_START( pcd, pcd_state )
MCFG_SCREEN_SIZE(640, 350)
MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 349)
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_UPDATE_DRIVER(pcd_state, screen_update)
MCFG_SCREEN_UPDATE_DEVICE("crtc", scn2674_device, screen_update)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", empty)
MCFG_PALETTE_ADD_BLACK_AND_WHITE("palette")
MCFG_SCN2674_VIDEO_ADD("crtc", 0, NULL);
MCFG_SCN2674_GFXDECODE("gfxdecode")
MCFG_SCN2674_PALETTE("palette")
MCFG_SCN2674_TEXT_CHARACTER_WIDTH(8)
MCFG_SCN2674_GFX_CHARACTER_WIDTH(16)
MCFG_SCN2674_DRAW_CHARACTER_CALLBACK_OWNER(pcd_state, display_pixels)
// rtc
MCFG_MC146818_ADD("rtc", XTAL_32_768kHz)
@ -309,8 +403,10 @@ ROM_START( pcd )
ROM_LOAD16_BYTE("s26361-d359.d43", 0x0000, 0x2000, CRC(e03db2ec) SHA1(fcae8b0c9e7543706817b0a53872826633361fda))
ROM_FILL(0xb64, 1, 0xe2) // post expects 0xd0 fdc command to be instant, give it a delay
ROM_FILL(0xb65, 1, 0xfe)
ROM_FILL(0x3ffe, 1, 0xb4) // fix csum
ROM_FILL(0x3fff, 1, 0x22)
ROM_FILL(0xb35, 1, 0x90) // fdc delay_register_commit is too long
ROM_FILL(0xb36, 1, 0x90)
ROM_FILL(0x3ffe, 1, 0xf4) // fix csum
ROM_FILL(0x3fff, 1, 0x3d)
// gfx card (scn2674 with 8741), to be moved
ROM_REGION(0x400, "graphics", 0)

View File

@ -327,6 +327,7 @@ VIDEOS += UPD7227
VIDEOS += V9938
VIDEOS += VIC4567
#VIDEOS += VOODOO
VIDEOS += SCN2674
#-------------------------------------------------
# specify available machine cores
@ -940,7 +941,6 @@ $(MESSOBJ)/mame.a: \
$(MAME_VIDEO)/vectrex.o \
$(MAME_DRIVERS)/cps1.o \
$(MAME_VIDEO)/cps1.o \
$(MAME_VIDEO)/scn2674.o \
#-------------------------------------------------