diff options
author | Wilbert Pol <wilbert@jdg.info> | 2012-08-20 20:15:14 +0000 |
---|---|---|
committer | Wilbert Pol <wilbert@jdg.info> | 2012-08-20 20:15:14 +0000 |
commit | 695fef3595327ddd102550e9dc4c6472c1b36d08 (patch) | |
tree | 6c46e45401b35a6fe620aea8286193e36a93e212 | |
parent | 857f3e767b17278c510faa8879b14c9584513134 (diff) |
Sync with MESS (nw)
-rw-r--r-- | .gitattributes | 2 | ||||
-rw-r--r-- | src/emu/emu.mak | 1 | ||||
-rw-r--r-- | src/emu/video/huc6261.c | 409 | ||||
-rw-r--r-- | src/emu/video/huc6261.h | 83 |
4 files changed, 495 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes index ec2c0266b8c..6770531efdf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 2c77f1f1261..6f5778eb7f2 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -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 \ diff --git a/src/emu/video/huc6261.c b/src/emu/video/huc6261.c new file mode 100644 index 00000000000..dab3a97839a --- /dev/null +++ b/src/emu/video/huc6261.c @@ -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 ) ); +} + diff --git a/src/emu/video/huc6261.h b/src/emu/video/huc6261.h new file mode 100644 index 00000000000..a4c49b23751 --- /dev/null +++ b/src/emu/video/huc6261.h @@ -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 |