diff options
Diffstat (limited to 'src/devices/video/huc6270.cpp')
-rw-r--r-- | src/devices/video/huc6270.cpp | 895 |
1 files changed, 895 insertions, 0 deletions
diff --git a/src/devices/video/huc6270.cpp b/src/devices/video/huc6270.cpp new file mode 100644 index 00000000000..c0fe5225c8e --- /dev/null +++ b/src/devices/video/huc6270.cpp @@ -0,0 +1,895 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +/********************************************************************** + + NEC HuC6270 Video Display Controller + + The HuC6270 basically outputs a 9-bit stream of pixel data which + holds a color index, a palette index, and an indication whether + the pixel contains background data or from sprite data. + + This data can be used by a colour encoder to output graphics. + + A regular screen is displayed as follows: + + |<- HDS ->|<-- HDW -->|<- HDE ->|<- HSW ->| + |---------|-----------------------|---------|---------| + VSW | | + |---------|-----------------------|---------|---------| + VDS | | + | overscan | + |---------|-----------------------|---------|---------| + | | | | + | | | | + | | | | + | | | | + VDW | overscan| active display | overscan | + | | | | + | | | | + | | | | + | | | | + |---------|-----------------------|---------|---------| + VCR | overscan | + | | + |---------|-----------------------|---------|---------| + ^end hsync + ^start vsync (30 cycles after hsync) + + +KNOWN ISSUES + - Violent Soldier (probably connected): + - In the intro some artefacts appear at the top of the + screen every now and then. + - In ccovell's splitres test not all sections seem to be aligned properly. + - Side Arms: Seems to be totally broken. + + +TODO + - Fix timing of VRAM-SATB DMA + - Implement VRAM-VRAM DMA + - DMA speeds differ depending on the dot clock selected in the huc6270 + +**********************************************************************/ + +#include "emu.h" +#include "huc6270.h" + +#define LOG 0 + +enum { + MAWR = 0x00, + MARR = 0x01, + VxR = 0x02, + CR = 0x05, + RCR = 0x06, + BXR = 0x07, + BYR = 0x08, + MWR = 0x09, + HSR = 0x0A, + HDR = 0x0B, + VPR = 0x0C, + VDW = 0x0D, + VCR = 0x0E, + DCR = 0x0F, + SOUR = 0x10, + DESR = 0x11, + LENR = 0x12, + DVSSR = 0x13 +}; + +ALLOW_SAVE_TYPE(huc6270_device::huc6270_v_state); +ALLOW_SAVE_TYPE(huc6270_device::huc6270_h_state); + + +/* Bits in the VDC status register */ +#define HUC6270_BSY 0x40 /* Set when the VDC accesses VRAM */ +#define HUC6270_VD 0x20 /* Set when in the vertical blanking period */ +#define HUC6270_DV 0x10 /* Set when a VRAM > VRAM DMA transfer is done */ +#define HUC6270_DS 0x08 /* Set when a VRAM > SATB DMA transfer is done */ +#define HUC6270_RR 0x04 /* Set when the current scanline equals the RCR register */ +#define HUC6270_OR 0x02 /* Set when there are more than 16 sprites on a line */ +#define HUC6270_CR 0x01 /* Set when sprite #0 overlaps with another sprite */ + + +const device_type HUC6270 = &device_creator<huc6270_device>; + + +const UINT8 huc6270_device::vram_increments[4] = { 1, 32, 64, 128 }; + +huc6270_device::huc6270_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, HUC6270, "HuC6270 VDC", tag, owner, clock, "huc6270", __FILE__), + m_vram_size(0), + m_irq_changed_cb(*this) +{ +} + + +/* + Read one row of tile data from video ram +*/ +inline void huc6270_device::fetch_bat_tile_row() +{ + UINT16 bat_data, data1, data2, data3, data4, tile_palette; + int i; + + bat_data = m_vram[ m_bat_address & m_vram_mask ]; + tile_palette = ( bat_data >> 8 ) & 0xF0; + data1 = m_vram[ ( ( ( bat_data & 0x0FFF ) << 4 ) + m_bat_row + 0 ) & m_vram_mask ]; + data2 = ( data1 >> 7 ) & 0x1FE; + data3 = m_vram[ ( ( ( bat_data & 0x0FFF ) << 4 ) + m_bat_row + 8 ) & m_vram_mask ]; + data4 = ( data3 >> 5 ) & 0x7F8; + data3 <<= 2; + + for ( i = 7; i >= 0; i-- ) + { + UINT16 c = ( data1 & 0x01 ) | ( data2 & 0x02 ) | ( data3 & 0x04 ) | ( data4 & 0x08 ); + + /* Colour 0 for background tiles is always taken from palette 0 */ + if ( c ) + c |= tile_palette; + + m_bat_tile_row[i] = c; + + data1 >>= 1; + data2 >>= 1; + data3 >>= 1; + data4 >>= 1; + } +} + + +void huc6270_device::add_sprite( int index, int x, int pattern, int line, int flip_x, int palette, int priority, int sat_lsb ) +{ + int i = m_sprites_this_line; + + if ( i < 16 ) + { + UINT32 b0, b1, b2, b3; + int j; + + if ( flip_x ) + flip_x = 0x0F; + + pattern += ( ( line >> 4 ) << 1 ); + + if ( ( m_mwr & 0x0c ) == 0x04 ) + { + if ( ! sat_lsb ) + { + b0 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x00 ) & m_vram_mask ]; + b1 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x10 ) & m_vram_mask ] << 1; + } + else + { + b0 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x20 ) & m_vram_mask ]; + b1 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x30 ) & m_vram_mask ] << 1; + } + b2 = 0; + b3 = 0; + } + else + { + b0 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x00 ) & m_vram_mask ]; + b1 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x10 ) & m_vram_mask ] << 1; + b2 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x20 ) & m_vram_mask ] << 2; + b3 = m_vram[ ( ( pattern * 0x40 ) + ( line & 0x0F ) + 0x30 ) & m_vram_mask ] << 3; + } + + for ( j = 15; j >= 0; j-- ) + { + UINT8 data = ( b3 & 0x08 ) | ( b2 & 0x04 ) | ( b1 & 0x02 ) | ( b0 & 0x01 ); + + if ( data ) + { + data |= palette << 4; + + if ( x + ( j ^ flip_x ) < 1024 ) + { + if (! m_sprite_row[ x + ( j ^ flip_x ) ] ) + { + m_sprite_row[ x + ( j ^ flip_x ) ] = ( priority ? 0x4000 : 0x0000 ) | ( index << 8 ) | data; + } + else + { + if ( ! ( m_sprite_row[ x + ( j ^ flip_x ) ] & 0xFF00 ) ) + { + /* Sprite 0 collission */ + m_sprite_row[ x + ( j ^ flip_x ) ] |= 0x8000; + } + } + } + } + + b0 >>= 1; + b1 >>= 1; + b2 >>= 1; + b3 >>= 1; + } + + m_sprites_this_line += 1; + } +} + + +void huc6270_device::select_sprites() +{ + int i; + + m_sprites_this_line = 0; + memset( m_sprite_row, 0, sizeof( m_sprite_row ) ); + m_sprite_row_index = 0x20; + + for ( i = 0; i < 4 * 64; i += 4 ) + { + static const int cgy_table[4] = { 16, 32, 64, 64 }; + int cgy = ( m_sat[i+3] >> 12 ) & 0x03; + int height = cgy_table[ cgy ]; + int sprite_line = m_raster_count - m_sat[i]; + + if ( sprite_line >= 0 && sprite_line < height ) + { + int pattern = m_sat[i+2] >> 1; + int sat_lsb = m_sat[i+2] & 0x01; + int palette = m_sat[i+3] & 0x0F; + int priority = m_sat[i+3] & 0x80; + int cgx = m_sat[i+3] & 0x0100; + + /* If CGY is set to 1, bit 1 of the sprite pattern index is forced to 0 */ + if ( cgy & 1 ) + pattern &= ~0x0002; + + /* If CGY is set to 2 or 3, bits 1 and 2 of the sprite pattern index are forced to 0 */ + if ( cgy & 2 ) + pattern &= ~0x0006; + + /* Recalculate line index when sprite is flipped vertically */ + if ( m_sat[i+3] & 0x8000 ) + sprite_line = ( height - 1 ) - sprite_line; + + /* Is the sprite 32 pixels wide */ + if ( cgx ) + { + /* If CGX is set, bit 0 of the sprite pattern index is forced to 0 */ + pattern &= ~0x0001; + + /* Check for horizontal flip */ + if ( m_sat[i+3] & 0x0800 ) + { + /* Add to our list of sprites for this line */ + add_sprite( i/4, m_sat[i+1], pattern + 1, sprite_line, 1, palette, priority, sat_lsb ); + add_sprite( i/4, m_sat[i+1] + 16, pattern, sprite_line, 1, palette, priority, sat_lsb ); + } + else + { + /* Add to our list of sprites for this line */ + add_sprite( i/4, m_sat[i+1], pattern, sprite_line, 0, palette, priority, sat_lsb ); + add_sprite( i/4, m_sat[i+1] + 16, pattern + 1, sprite_line, 0, palette, priority, sat_lsb ); + } + } + else + { + /* Add to our list of sprites for this line */ + add_sprite( i/4, m_sat[i+1], pattern, sprite_line, m_sat[i+3] & 0x0800, palette, priority, sat_lsb ); + } + } + } + + /* Check for sprite overflow */ + if ( m_sprites_this_line >= 16 ) + { + /* note: flag is set only if irq is taken, Mizubaku Daibouken relies on this behaviour */ + if ( m_cr & 0x02 ) + { + m_status |= HUC6270_OR; + m_irq_changed_cb( ASSERT_LINE ); + } + } +} + + +inline void huc6270_device::handle_vblank() +{ + if ( ! m_vd_triggered ) + { + if ( m_cr & 0x08 ) + { + m_status |= HUC6270_VD; + m_irq_changed_cb( ASSERT_LINE ); + } + + /* Should we initiate a VRAM->SATB DMA transfer. + The timing for this is incorrect. + */ + if ( m_dvssr_written || ( m_dcr & 0x10 ) ) + { + int i; + + if (LOG) logerror("SATB transfer from %05x\n", m_dvssr << 1 ); + for ( i = 0; i < 4 * 64; i += 4 ) + { + m_sat[i + 0] = m_vram[ ( m_dvssr + i + 0 ) & m_vram_mask ] & 0x03FF; + m_sat[i + 1] = m_vram[ ( m_dvssr + i + 1 ) & m_vram_mask ] & 0x03FF; + m_sat[i + 2] = m_vram[ ( m_dvssr + i + 2 ) & m_vram_mask ] & 0x07FF; + m_sat[i + 3] = m_vram[ ( m_dvssr + i + 3 ) & m_vram_mask ]; + } + m_dvssr_written = 0; + + /* Generate SATB interrupt if requested */ + if ( m_dcr & 0x01 ) + { + m_satb_countdown = 4; +// m_status |= HUC6270_DS; +// m_irq_changed_cb( ASSERT_LINE ); + } + } + + m_vd_triggered = 1; + } +} + + +inline void huc6270_device::next_vert_state() +{ + switch ( m_vert_state ) + { + case HUC6270_VSW: + m_vert_state = HUC6270_VDS; + m_vert_to_go = ( ( m_vpr >> 8 ) & 0xFF ) + 2; + break; + + case HUC6270_VDS: + m_vert_state = HUC6270_VDW; + m_vert_to_go = ( m_vdw & 0x1FF ) + 1; + m_byr_latched = m_byr; + m_vd_triggered = 0; + break; + + case HUC6270_VDW: + m_vert_state = HUC6270_VCR; + m_vert_to_go = ( m_vcr & 0xFF ); + handle_vblank(); + break; + + case HUC6270_VCR: + m_vert_state = HUC6270_VSW; + m_vert_to_go = ( m_vpr & 0x1F ) + 1; + break; + } +} + + +inline void huc6270_device::next_horz_state() +{ + switch ( m_horz_state ) + { + case HUC6270_HDS: + m_bxr_latched = m_bxr; +//if (LOG) printf("latched bxr vpos=%d, hpos=%d\n", video_screen_get_vpos(device->machine->first_screen()), video_screen_get_hpos(device->machine->first_screen())); + m_horz_state = HUC6270_HDW; + m_horz_to_go = ( m_hdr & 0x7F ) + 1; + { + static const int width_shift[4] = { 5, 6, 7, 7 }; + UINT16 v; + + v = ( m_byr_latched ) & ( ( m_mwr & 0x40 ) ? 0x1FF : 0xFF ); + m_bat_row = v & 7; + m_bat_address_mask = ( 1 << width_shift[ ( m_mwr >> 4 ) & 0x03 ] ) - 1; + m_bat_address = ( ( v >> 3 ) << ( width_shift[ ( m_mwr >> 4 ) & 0x03 ] ) ) + | ( ( m_bxr_latched >> 3 ) & m_bat_address_mask ); + m_bat_column = m_bxr & 7; + fetch_bat_tile_row(); + } + break; + + case HUC6270_HDW: + m_horz_state = HUC6270_HDE; + m_horz_to_go = ( ( m_hdr >> 8 ) & 0x7F ) + 1; + break; + + case HUC6270_HDE: + m_horz_state = HUC6270_HSW; + m_horz_to_go = ( m_hsr & 0x1F ) + 1; + break; + + case HUC6270_HSW: + m_horz_state = HUC6270_HDS; + m_horz_to_go = MAX( ( ( m_hsr >> 8 ) & 0x7F ), 2 ) + 1; + + /* If section has ended, advance to next vertical state */ + while ( m_vert_to_go == 0 ) + next_vert_state(); + + /* Select sprites for the coming line */ + select_sprites(); + break; + } + m_horz_steps = 0; +} + + +READ16_MEMBER( huc6270_device::next_pixel ) +{ + UINT16 data = HUC6270_SPRITE; + + /* Check if we're on an active display line */ + if ( m_vert_state == HUC6270_VDW ) + { + /* Check if we're in active display area */ + if ( m_horz_state == HUC6270_HDW ) + { + UINT8 sprite_data = m_sprite_row[ m_sprite_row_index ] & 0x00FF; + int collission = ( m_sprite_row[ m_sprite_row_index ] & 0x8000 ) ? 1 : 0; + + if ( m_cr & 0x80 ) + { + data = HUC6270_BACKGROUND | m_bat_tile_row[ m_bat_column ]; + if ( sprite_data && ( m_cr & 0x40 ) ) + { + if ( m_sprite_row[ m_sprite_row_index ] & 0x4000 ) + { + data = HUC6270_SPRITE | sprite_data; + } + else + { + if ( data == HUC6270_BACKGROUND ) + { + data = HUC6270_SPRITE | sprite_data; + } + } + } + } + else + { + if ( m_cr & 0x40 ) + { + data = HUC6270_SPRITE | sprite_data; + } + } + + m_sprite_row_index = m_sprite_row_index + 1; + m_bat_column += 1; + if ( m_bat_column >= 8 ) + { + m_bat_address = ( m_bat_address & ~m_bat_address_mask ) + | ( ( m_bat_address + 1 ) & m_bat_address_mask ); + m_bat_column = 0; + fetch_bat_tile_row(); + } + + if ( collission && ( m_cr & 0x01 ) ) + { + m_status |= HUC6270_CR; + m_irq_changed_cb( ASSERT_LINE ); + } + } + } + + m_horz_steps++; + if ( m_horz_steps == 8 ) + { + m_horz_to_go -= 1; + m_horz_steps = 0; + while ( m_horz_to_go == 0 ) + next_horz_state(); + } + return data; +} + + +//inline READ16_MEMBER( huc6270_device::time_until_next_event ) +//{ +// return m_horz_to_go * 8 + m_horz_steps; +//} + + +WRITE_LINE_MEMBER( huc6270_device::vsync_changed ) +{ + state &= 0x01; + if ( m_vsync != state ) + { + /* Check for low->high VSYNC transition */ + if ( state ) + { + m_vert_state = HUC6270_VCR; + m_vert_to_go = 0; + + while ( m_vert_to_go == 0 ) + next_vert_state(); + } + else + /* High->low transition */ + { + handle_vblank(); + + /* Should we perform VRAM-VRAM dma. + The timing for this is incorrect. + */ + if ( m_dma_enabled ) + { + int desr_inc = ( m_dcr & 0x0008 ) ? -1 : +1; + int sour_inc = ( m_dcr & 0x0004 ) ? -1 : +1; + + if (LOG) logerror("doing dma sour = %04x, desr = %04x, lenr = %04x\n", m_sour, m_desr, m_lenr ); + do { + UINT16 data = m_vram[ m_sour & m_vram_mask ]; + m_vram[ m_desr & m_vram_mask ] = data; + m_sour += sour_inc; + m_desr += desr_inc; + m_lenr -= 1; + } while ( m_lenr != 0xFFFF ); + + if ( m_dcr & 0x0002 ) + { + m_status |= HUC6270_DV; + m_irq_changed_cb( ASSERT_LINE ); + } + m_dma_enabled = 0; + } + } + } + + m_vsync = state; +} + + +WRITE_LINE_MEMBER( huc6270_device::hsync_changed ) +{ + state &= 0x01; + + /* Check for high->low HSYNC transition */ + /* Check for low->high HSYNC transition */ + if( ! m_hsync && state ) + { + if ( m_satb_countdown ) + { + m_satb_countdown--; + + if ( m_satb_countdown == 0 ) + { + m_status |= HUC6270_DS; + m_irq_changed_cb( ASSERT_LINE ); + } + } + + m_horz_state = HUC6270_HSW; + m_horz_to_go = 0; + m_horz_steps = 0; + m_byr_latched += 1; + m_raster_count += 1; + if ( m_vert_to_go == 1 && m_vert_state == HUC6270_VDS ) + { + m_raster_count = 0x40; + } + + m_vert_to_go -= 1; + + while ( m_horz_to_go == 0 ) + next_horz_state(); + + if ( m_raster_count == m_rcr && ( m_cr & 0x04 ) ) + { + m_status |= HUC6270_RR; + m_irq_changed_cb( ASSERT_LINE ); + } + } + + m_hsync = state; +} + + +READ8_MEMBER( huc6270_device::read ) +{ + UINT8 data = 0x00; + + switch ( offset & 3 ) + { + case 0x00: /* status */ + data = m_status; + m_status &= ~( HUC6270_VD | HUC6270_DV | HUC6270_RR | HUC6270_CR | HUC6270_OR | HUC6270_DS ); + m_irq_changed_cb( CLEAR_LINE ); + break; + + case 0x02: + data = m_vrr & 0xFF; + break; + + case 0x03: + data = m_vrr >> 8; + if ( m_register_index == VxR ) + { + m_marr += vram_increments[ ( m_cr >> 11 ) & 3 ]; + m_vrr = m_vram[ m_marr & m_vram_mask ]; + } + break; + } + return data; +} + + +WRITE8_MEMBER( huc6270_device::write ) +{ + if (LOG) logerror("%s: huc6270 write %02x <- %02x ", machine().describe_context(), offset, data); + + switch ( offset & 3 ) + { + case 0x00: /* VDC register select */ + m_register_index = data & 0x1F; + break; + + case 0x02: /* VDC data LSB */ + switch ( m_register_index ) + { + case MAWR: /* memory address write register LSB */ + m_mawr = ( m_mawr & 0xFF00 ) | data; + break; + + case MARR: /* memory address read register LSB */ + m_marr = ( m_marr & 0xFF00 ) | data; + m_vrr = m_vram[ m_marr & m_vram_mask ]; + break; + + case VxR: /* vram write data LSB */ + m_vwr = ( m_vwr & 0xFF00 ) | data; + break; + + case CR: /* control register LSB */ + m_cr = ( m_cr & 0xFF00 ) | data; + break; + + case RCR: /* raster compare register LSB */ + m_rcr = ( m_rcr & 0x0300 ) | data; +//printf("%s: RCR set to %03x\n", machine().describe_context(), m_rcr); +// if ( m_raster_count == m_rcr && m_cr & 0x04 ) +// { +// m_status |= HUC6270_RR; +// m_irq_changed_cb( ASSERT_LINE ); +// } +//if (LOG) printf("%04x: RCR (%03x) written at %d,%d\n", activecpu_get_pc(), huc6270->m_rcr, video_screen_get_vpos(device->machine->first_screen()), video_screen_get_hpos(device->machine->first_screen()) ); + break; + + case BXR: /* background x-scroll register LSB */ + m_bxr = ( m_bxr & 0x0300 ) | data; +//if (LOG) printf("*********************** BXR written %d at %d,%d\n", m_bxr, video_screen_get_vpos(device->machine->first_screen()), video_screen_get_hpos(device->machine->first_screen()) ); + break; + + case BYR: /* background y-scroll register LSB */ + m_byr = ( m_byr & 0x0100 ) | data; + m_byr_latched = m_byr; +//if (LOG) printf("******************** BYR written %d at %d,%d\n", huc6270->m_byr, video_screen_get_vpos(device->machine->first_screen()), video_screen_get_hpos(device->machine->first_screen()) ); + break; + + case MWR: /* memory width register LSB */ + m_mwr = ( m_mwr & 0xFF00 ) | data; + break; + + case HSR: /* horizontal sync register LSB */ + m_hsr = ( m_hsr & 0xFF00 ) | data; + break; + + case HDR: /* horizontal display register LSB */ + m_hdr = ( m_hdr & 0xFF00 ) | data; + break; + + case VPR: /* vertical sync register LSB */ + m_vpr = ( m_vpr & 0xFF00 ) | data; + break; + + case VDW: /* vertical display register LSB */ + m_vdw = ( m_vdw & 0xFF00 ) | data; + break; + + case VCR: /* vertical display end position register LSB */ + m_vcr = ( m_vcr & 0xFF00 ) | data; + break; + + case DCR: /* DMA control register LSB */ + m_dcr = ( m_dcr & 0xFF00 ) | data; + break; + + case SOUR: /* DMA source address register LSB */ + m_sour = ( m_sour & 0xFF00 ) | data; + break; + + case DESR: /* DMA destination address register LSB */ + m_desr = ( m_desr & 0xFF00 ) | data; + break; + + case LENR: /* DMA length register LSB */ + m_lenr = ( m_lenr & 0xFF00 ) | data; + break; + + case DVSSR: /* Sprite attribute table LSB */ + m_dvssr = ( m_dvssr & 0xFF00 ) | data; + m_dvssr_written = 1; + break; + } + break; + + case 0x03: /* VDC data MSB */ + switch ( m_register_index ) + { + case MAWR: /* memory address write register MSB */ + m_mawr = ( m_mawr & 0x00FF ) | ( data << 8 ); + break; + + case MARR: /* memory address read register MSB */ + m_marr = ( m_marr & 0x00FF ) | ( data << 8 ); + m_vrr = m_vram[ m_marr & m_vram_mask ]; + break; + + case VxR: /* vram write data MSB */ + m_vwr = ( m_vwr & 0x00FF ) | ( data << 8 ); + m_vram[ m_mawr & m_vram_mask ] = m_vwr; + m_mawr += vram_increments[ ( m_cr >> 11 ) & 3 ]; + break; + + case CR: /* control register MSB */ + m_cr = ( m_cr & 0x00FF ) | ( data << 8 ); + break; + + case RCR: /* raster compare register MSB */ + m_rcr = ( m_rcr & 0x00FF ) | ( ( data & 0x03 ) << 8 ); +//printf("%s: RCR set to %03x\n", machine().describe_context(), m_rcr); +// if ( m_raster_count == m_rcr && m_cr & 0x04 ) +// { +// m_status |= HUC6270_RR; +// m_irq_changed_cb( ASSERT_LINE ); +// } + break; + + case BXR: /* background x-scroll register MSB */ + m_bxr = ( m_bxr & 0x00FF ) | ( ( data & 0x03 ) << 8 ); + break; + + case BYR: /* background y-scroll register MSB */ + m_byr = ( m_byr & 0x00FF ) | ( ( data & 0x01 ) << 8 ); + m_byr_latched = m_byr; + break; + + case MWR: /* memory width register MSB */ + m_mwr = ( m_mwr & 0x00FF ) | ( data << 8 ); + break; + + case HSR: /* horizontal sync register MSB */ + m_hsr = ( m_hsr & 0x00FF ) | ( data << 8 ); + break; + + case HDR: /* horizontal display register MSB */ + m_hdr = ( m_hdr & 0x00FF ) | ( data << 8 ); + break; + + case VPR: /* vertical sync register MSB */ + m_vpr = ( m_vpr & 0x00FF ) | ( data << 8 ); + break; + + case VDW: /* vertical display register MSB */ + m_vdw = ( m_vdw & 0x00FF ) | ( data << 8 ); + break; + + case VCR: /* vertical display end position register MSB */ + m_vcr = ( m_vcr & 0x00FF ) | ( data << 8 ); + break; + + case DCR: /* DMA control register MSB */ + m_dcr = ( m_dcr & 0x00FF ) | ( data << 8 ); + break; + + case SOUR: /* DMA source address register MSB */ + m_sour = ( m_sour & 0x00FF ) | ( data << 8 ); + break; + + case DESR: /* DMA destination address register MSB */ + m_desr = ( m_desr & 0x00FF ) | ( data << 8 ); + break; + + case LENR: /* DMA length register MSB */ + m_lenr = ( m_lenr & 0x00FF ) | ( data << 8 ); + m_dma_enabled = 1; +//logerror("DMA is not supported yet.\n"); + break; + + case DVSSR: /* Sprite attribute table MSB */ + m_dvssr = ( m_dvssr & 0x00FF ) | ( data << 8 ); + m_dvssr_written = 1; + break; + } + break; + } + if (LOG) logerror("\n"); +} + + +void huc6270_device::device_start() +{ + /* Resolve callbacks */ + m_irq_changed_cb.resolve_safe(); + + m_vram = auto_alloc_array_clear(machine(), UINT16, m_vram_size/sizeof(UINT16)); + m_vram_mask = (m_vram_size >> 1) - 1; + + save_pointer(NAME(m_vram), m_vram_size/sizeof(UINT16)); + + save_item(NAME(m_register_index)); + save_item(NAME(m_mawr)); + save_item(NAME(m_marr)); + save_item(NAME(m_vrr)); + save_item(NAME(m_vwr)); + save_item(NAME(m_cr)); + save_item(NAME(m_rcr)); + save_item(NAME(m_bxr)); + save_item(NAME(m_byr)); + save_item(NAME(m_mwr)); + save_item(NAME(m_hsr)); + save_item(NAME(m_hdr)); + save_item(NAME(m_vpr)); + save_item(NAME(m_vdw)); + save_item(NAME(m_vcr)); + save_item(NAME(m_dcr)); + save_item(NAME(m_sour)); + save_item(NAME(m_desr)); + save_item(NAME(m_lenr)); + save_item(NAME(m_dvssr)); + save_item(NAME(m_status)); + save_item(NAME(m_hsync)); + save_item(NAME(m_vsync)); + save_item(NAME(m_vert_state)); + save_item(NAME(m_horz_state)); + save_item(NAME(m_vd_triggered)); + save_item(NAME(m_vert_to_go)); + save_item(NAME(m_horz_to_go)); + save_item(NAME(m_horz_steps)); + save_item(NAME(m_raster_count)); + save_item(NAME(m_dvssr_written)); + save_item(NAME(m_satb_countdown)); + save_item(NAME(m_dma_enabled)); + save_item(NAME(m_byr_latched)); + save_item(NAME(m_bxr_latched)); + save_item(NAME(m_bat_address)); + save_item(NAME(m_bat_address_mask)); + save_item(NAME(m_bat_row)); + save_item(NAME(m_bat_column)); + save_item(NAME(m_bat_tile_row)); + save_item(NAME(m_sat)); + save_item(NAME(m_sprites_this_line)); + save_item(NAME(m_sprite_row_index)); + save_item(NAME(m_sprite_row)); +} + + +void huc6270_device::device_reset() +{ + m_mawr = 0; + m_marr = 0; + m_vrr = 0; + m_vwr = 0; + m_cr = 0; + m_rcr = 0; + m_bxr = 0; + m_byr = 0; + m_mwr = 0; + m_hsr = 0x0202; /* Take some defaults for horizontal timing */ + m_hdr = 0x041f; + m_vpr = 0x0f02; /* Take some defaults for vertical timing */ + m_vdw = 0x00ef; + m_vcr = 0x0004; + m_dcr = 0; + m_sour = 0; + m_lenr = 0; + m_dvssr = 0; + m_status = 0; + m_vd_triggered = 0; + m_dvssr_written = 0; + m_satb_countdown = 0; + m_raster_count = 0x4000; + m_vert_to_go = 0; + m_vert_state = HUC6270_VSW; + m_horz_steps = 0; + m_horz_to_go = 0; + m_horz_state = HUC6270_HDS; + m_hsync = 0; + m_vsync = 0; + m_dma_enabled = 0; + m_byr_latched = 0; + + memset(m_sat, 0, sizeof(m_sat)); +} |