Sync with MESS (nw)

This commit is contained in:
Wilbert Pol 2012-08-20 20:15:14 +00:00
parent 857f3e767b
commit 695fef3595
4 changed files with 495 additions and 0 deletions

2
.gitattributes vendored
View File

@ -1388,6 +1388,8 @@ src/emu/video/huc6202.c svneol=native#text/plain
src/emu/video/huc6202.h svneol=native#text/plain
src/emu/video/huc6260.c svneol=native#text/plain
src/emu/video/huc6260.h svneol=native#text/plain
src/emu/video/huc6261.c svneol=native#text/plain
src/emu/video/huc6261.h svneol=native#text/plain
src/emu/video/huc6270.c svneol=native#text/plain
src/emu/video/huc6270.h svneol=native#text/plain
src/emu/video/i8275.c svneol=native#text/plain

View File

@ -287,6 +287,7 @@ EMUVIDEOOBJS = \
$(EMUVIDEO)/hd63484.o \
$(EMUVIDEO)/huc6202.o \
$(EMUVIDEO)/huc6260.o \
$(EMUVIDEO)/huc6261.o \
$(EMUVIDEO)/huc6270.o \
$(EMUVIDEO)/i8275.o \
$(EMUVIDEO)/k053250.o \

409
src/emu/video/huc6261.c Normal file
View File

@ -0,0 +1,409 @@
/**********************************************************************
Hudson/NEC HuC6261 Video Colour Encoder
The HuC6261 generates the tv control signals. A full line lasts
1365 "master" cycles (typically at 21.47727Mhz).
HSync is low for 237 and high for 1128 master cycles.
VSync is low for 4095 master cycles (3 lines).
VSync changes 30 master cycles after HSync would go low.
**********************************************************************/
#include "emu.h"
#include "profiler.h"
#include "huc6261.h"
#define LOG 0
#define HUC6261_HSYNC_LENGTH 237
#define HUC6261_HSYNC_START ( HUC6261_WPF - HUC6261_HSYNC_LENGTH )
const device_type HUC6261 = &device_creator<huc6261_device>;
void huc6261_device::device_config_complete()
{
const huc6261_interface *intf = reinterpret_cast<const huc6261_interface *>(static_config());
if ( intf != NULL )
{
*static_cast<huc6261_interface *>(this) = *intf;
}
else
{
}
}
huc6261_device::huc6261_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, HUC6261, "HuC6261", tag, owner, clock)
{
}
void huc6261_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
int vpos = m_screen->vpos();
int hpos = m_screen->hpos();
int h = m_last_h;
int v = m_last_v;
UINT32 *bitmap_line = &m_bmp->pix32(v);
while ( h != hpos || v != vpos )
{
if ( m_pixel_clock == 0 )
{
g_profiler.start( PROFILER_VIDEO );
/* Get next pixel information */
m_pixel_data = 0; //m_get_next_pixel_data( 0, 0xffff );
g_profiler.stop();
}
bitmap_line[ h ] = m_palette[ m_pixel_data ];
m_pixel_clock = ( m_pixel_clock + 1 ) % m_pixels_per_clock;
h = ( h + 1 ) % HUC6261_WPF;
switch( h )
{
case HUC6261_HSYNC_START: /* Start of HSync */
m_huc6270_a->hsync_changed( 0 );
m_huc6270_b->hsync_changed( 0 );
// if ( v == 0 )
// {
// /* Check if the screen should be resized */
// m_height = HUC6261_LPF - ( m_blur ? 1 : 0 );
// if ( m_height != video_screen_get_height( m_screen ) )
// {
// rectangle visible_area;
//
// /* TODO: Set proper visible area parameters */
// visible_area.min_x = 64;
// visible_area.min_y = 18;
// visible_area.max_x = 64 + 1024 + 64 - 1;
// visible_area.max_y = 18 + 242 - 1;
//
// video_screen_configure( m_screen, HUC6261_WPF, m_height, &visible_area, HZ_TO_ATTOSECONDS( device->clock / ( HUC6261_WPF * m_height ) ) );
// }
// }
break;
case 0: /* End of HSync */
m_huc6270_a->hsync_changed( 1 );
m_huc6270_b->hsync_changed( 1 );
m_pixel_clock = 0;
v = ( v + 1 ) % m_height;
bitmap_line = &m_bmp->pix32(v);
break;
case HUC6261_HSYNC_START + 30: /* End/Start of VSync */
if ( v>= m_height - 4 )
{
int vsync = ( v >= m_height - 4 && v < m_height - 1 ) ? 0 : 1;
m_huc6270_a->vsync_changed( vsync );
m_huc6270_b->vsync_changed( vsync );
}
break;
}
}
m_last_h = h;
m_last_v = v;
/* Reschedule timer */
if ( m_last_h < HUC6261_HSYNC_START )
{
/* Next event is start of HSync signal */
v = m_last_v;
h = HUC6261_HSYNC_START;
}
else if ( ( m_last_v == m_height - 4 || m_last_v == m_height - 1 ) && m_last_h < HUC6261_HSYNC_START + 30 )
{
/* Next event is start/end of VSync signal */
v = m_last_v;
h = HUC6261_HSYNC_START + 30;
}
else
{
/* Next event is end of HSync signal */
v = ( m_last_v + 1 ) % m_height;
h = 0;
}
/* Ask our slave device for time until next possible event */
{
UINT16 next_event_clocks = HUC6261_WPF; //m_get_time_til_next_event( 0, 0xffff );
int event_hpos, event_vpos;
/* Adjust for pixel clocks per pixel */
next_event_clocks *= m_pixels_per_clock;
/* Adjust for clocks left to go for current pixel */
next_event_clocks += ( m_pixels_per_clock - ( m_pixel_clock + 1 ) );
event_hpos = hpos + next_event_clocks;
event_vpos = vpos;
while ( event_hpos > HUC6261_WPF )
{
event_vpos += 1;
event_hpos -= HUC6261_WPF;
}
if ( event_vpos < v || ( event_vpos == v && event_hpos <= h ) )
{
if ( event_vpos > vpos || ( event_vpos == vpos && event_hpos > hpos ) )
{
v = event_vpos;
h = event_hpos;
}
}
}
m_timer->adjust( m_screen->time_until_pos( v, h ) );
}
void huc6261_device::video_update( bitmap_rgb32 &bitmap, const rectangle &cliprect )
{
copybitmap( bitmap, *m_bmp, 0, 0, 0, 0, cliprect );
}
READ16_MEMBER( huc6261_device::read )
{
UINT16 data = 0xFFFF;
switch ( offset & 1 )
{
/* Status info */
case 0x00:
{
UINT16 vpos = m_screen->vpos();
UINT16 hpos = m_screen->hpos();
data = ( vpos << 5 ) | ( m_register & 0x1F);
if ( vpos >= 22 && vpos < 262 && hpos < HUC6261_HSYNC_START )
{
data |= 0x8000;
}
}
break;
/* Register contents(?) */
case 0x01:
switch( m_register )
{
case 0x00:
data = m_control;
break;
case 0x01:
data = m_address;
break;
case 0x02:
case 0x03:
data = m_palette_latch;
m_address = ( m_address + 1 ) & 0x1FF;
m_palette_latch = m_palette[ m_address ];
break;
case 0x08:
data = m_priority[4] | ( m_priority[5] << 4 ) | ( m_priority[6] << 8 );
break;
case 0x09:
data = m_priority[0] | ( m_priority[1] << 4 ) | ( m_priority[2] << 8 ) | ( m_priority[3] << 12 );;
break;
}
break;
}
return data;
}
WRITE16_MEMBER( huc6261_device::write )
{
switch ( offset & 1 )
{
/* Register */
case 0x00:
m_register = data;
break;
case 0x01:
logerror("huc6261: writing 0x%04x to register 0x%02x\n", data, m_register );
switch( m_register )
{
/* Control register */
// -x-------------- Enable HuC6271: 0 - disabled, 1 - enabled
// --x------------- Enable HuC6272 BG3: 0 - disabled, 1 - enabled
// ---x------------ Enable HuC6272 BG2: 0 - disabled, 1 - enabled
// ----x----------- Enable Huc6272 BG1: 0 - disabled, 1 - enabled
// -----x---------- Enable HuC6272 BG0: 0 - disabled, 1 - enabled
// ------x--------- Enable HuC6270 SPR: 0 - disabled, 1 - enabled
// -------x-------- Enable HuC6270 BG: 0 - disabled, 1 - enabled
// --------x------- Number of SPR colors?: 0 - 16, 1 - 256
// ---------x------ Number of BG colors?: 0 - 16, 1 - 256
// ------------x--- Dot clock: 0 - 5MHz, 1 - 7MHz
// -------------x-- Synchronization: 0 - internal, 1 - external
// --------------xx Screen height: 00 - 262 lines, 01 - 263 lines, 10 - interlace, 11 - unknown/undefined
case 0x00:
m_control = data;
m_pixels_per_clock = ( data & 0x04 ) ? 3 : 4;
break;
// Palette address
case 0x01:
m_address = data & 0x1FF;
m_palette_latch = m_palette[ m_address ];
break;
// Palette data
case 0x02:
m_palette_latch = data;
m_palette[ m_address ] = m_palette_latch;
m_address = ( m_address + 1 ) & 0x1FF;
break;
// Palette offset 0
case 0x04:
break;
// Palette offset 1
case 0x05:
break;
// Palette offset 2
case 0x06:
break;
// Palette offset 3
case 0x07:
break;
// Priority 0
// -----xxx-------- HuC6271 Rainbow priority
// ---------xxx---- HuC6270 SPR priority
// -------------xxx HuC6270 BG priority
case 0x08:
m_priority[4] = ( data >> 0 ) & 0x07;
m_priority[5] = ( data >> 4 ) & 0x07;
m_priority[6] = ( data >> 8 ) & 0x07;
break;
// Priority 1
// -xxx------------ HuC6272 BG3 priority
// -----xxx-------- HuC6272 BG2 priority
// ---------xxx---- HuC6272 BG1 priority
// -------------xxx HuC6272 BG0 priority
case 0x09:
m_priority[0] = ( data >> 0 ) & 0x07;
m_priority[1] = ( data >> 4 ) & 0x07;
m_priority[2] = ( data >> 8 ) & 0x07;
m_priority[3] = ( data >> 12 ) & 0x07;
break;
// Chroma key Y
case 0x0A:
break;
// Chroma key U
case 0x0B:
break;
// Chroma key V
case 0x0C:
break;
//
case 0x0D:
break;
//
case 0x0E:
break;
//
case 0x0F:
break;
//
case 0x10:
break;
//
case 0x11:
break;
//
case 0x12:
break;
//
case 0x13:
break;
//
case 0x14:
break;
//
case 0x15:
break;
}
break;
}
}
void huc6261_device::device_start()
{
/* Make sure we are supplied all our mandatory tags */
assert( screen_tag != NULL );
assert( huc6270_a_tag != NULL );
assert( huc6270_b_tag != NULL );
m_timer = timer_alloc();
m_screen = machine().device<screen_device>( screen_tag );
m_huc6270_a = machine().device<huc6270_device>( huc6270_a_tag );
m_huc6270_b = machine().device<huc6270_device>( huc6270_b_tag );
m_bmp = auto_bitmap_rgb32_alloc( machine(), HUC6261_WPF, HUC6261_LPF );
/* We want to have valid devices */
assert( m_screen != NULL );
assert( m_huc6270_a != NULL );
assert( m_huc6270_b != NULL );
save_item(NAME(m_last_h));
save_item(NAME(m_last_v));
save_item(NAME(m_height));
save_item(NAME(m_palette));
save_item(NAME(m_palette_latch));
save_item(NAME(m_address));
save_item(NAME(m_register));
save_item(NAME(m_control));
save_item(NAME(m_priority));
save_item(NAME(m_pixels_per_clock));
save_item(NAME(m_pixel_data));
save_item(NAME(m_pixel_clock));
}
void huc6261_device::device_reset()
{
m_register = 0;
m_pixels_per_clock = 4;
m_height = 263;
m_last_v = m_screen->vpos();
m_last_h = m_screen->hpos();
m_timer->adjust( m_screen->time_until_pos( ( m_screen->vpos() + 1 ) % 263, 0 ) );
}

83
src/emu/video/huc6261.h Normal file
View File

@ -0,0 +1,83 @@
/**********************************************************************
Hudson/NEC HuC6261 interface and definitions
**********************************************************************/
#ifndef __HUC6261_H_
#define __HUC6261_H_
#include "emu.h"
#include "machine/devhelpr.h"
#include "video/huc6270.h"
/* Screen timing stuff */
#define HUC6261_WPF 1365 /* width of a line in frame including blanking areas */
#define HUC6261_LPF 263 /* max number of lines in a single frame */
#define MCFG_HUC6261_ADD( _tag, clock, _intrf ) \
MCFG_DEVICE_ADD( _tag, HUC6261, clock ) \
MCFG_DEVICE_CONFIG( _intrf )
typedef struct _huc6261_interface huc6261_interface;
struct _huc6261_interface
{
/* Tag for the screen we will be drawing on */
const char *screen_tag;
/* Tags for the 2 HuC6270 devices */
const char *huc6270_a_tag;
const char *huc6270_b_tag;
};
class huc6261_device : public device_t,
public huc6261_interface
{
public:
// construction/destruction
huc6261_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
void video_update(bitmap_rgb32 &bitmap, const rectangle &cliprect);
DECLARE_READ16_MEMBER( read );
DECLARE_WRITE16_MEMBER( write );
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
screen_device *m_screen;
huc6270_device *m_huc6270_a;
huc6270_device *m_huc6270_b;
int m_last_h;
int m_last_v;
int m_height;
UINT16 m_palette[512];
UINT16 m_address;
UINT16 m_palette_latch;
UINT16 m_register;
UINT16 m_control;
UINT8 m_priority[7];
UINT8 m_pixels_per_clock; /* Number of pixels to output per colour clock */
UINT16 m_pixel_data;
UINT8 m_pixel_clock;
emu_timer *m_timer;
bitmap_rgb32 *m_bmp;
};
extern const device_type HUC6261;
#endif