diff options
Diffstat (limited to 'src/devices/video/v9938.cpp')
-rw-r--r-- | src/devices/video/v9938.cpp | 256 |
1 files changed, 169 insertions, 87 deletions
diff --git a/src/devices/video/v9938.cpp b/src/devices/video/v9938.cpp index 97c584fddc6..6a24e97f7d4 100644 --- a/src/devices/video/v9938.cpp +++ b/src/devices/video/v9938.cpp @@ -33,23 +33,22 @@ todo: - vdp engine -- make run at correct speed - vr/hr/fh flags: double-check all of that - make vdp engine work in exp. ram -- fix save state support */ #include "emu.h" #include "v9938.h" -#define LOG_WARN (1U<<1) -#define LOG_INT (1U<<2) -#define LOG_STATUS (1U<<3) -#define LOG_REGWRITE (1U<<4) -#define LOG_COMMAND (1U<<5) -#define LOG_MODE (1U<<6) -#define LOG_NOTIMP (1U<<7) -#define LOG_DETAIL (1U<<8) +#define LOG_WARN (1U << 1) +#define LOG_INT (1U << 2) +#define LOG_STATUS (1U << 3) +#define LOG_REGWRITE (1U << 4) +#define LOG_COMMAND (1U << 5) +#define LOG_MODE (1U << 6) +#define LOG_NOTIMP (1U << 7) +#define LOG_DETAIL (1U << 8) // Minimum log should be warnings -#define VERBOSE (LOG_GENERAL | LOG_WARN ) +#define VERBOSE (LOG_GENERAL | LOG_WARN) #include "logmacro.h" @@ -169,15 +168,15 @@ void v99x8_device::device_config_complete() (m_pal_config ? VVISIBLE_PAL : VVISIBLE_NTSC) * 2 - 1 - VERTICAL_ADJUST * 2); if (!screen().has_screen_update()) - screen().set_screen_update(screen_update_rgb32_delegate(FUNC(v99x8_device::screen_update), this)); + screen().set_screen_update(*this, FUNC(v99x8_device::screen_update)); } -void v99x8_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(v99x8_device::update_line) { int scanline = (m_scanline - (m_scanline_start + m_offset_y)); - update_command (); + update_command(); // set flags if (m_scanline == (m_scanline_start + m_offset_y)) @@ -242,14 +241,14 @@ void v99x8_device::set_screen_parameters() } else { - // NYSC + // NTSC m_scanline_start = (m_cont_reg[9] & 0x80) ? 16 : 26; m_scanline_max = (m_cont_reg[9] & 0x80) ? 234 : 244; } m_visible_y = (m_cont_reg[9] & 0x80) ? 212 : 192; } - +// FIXME: this doesn't really allow for external clock configuration void v99x8_device::configure_pal_ntsc() { if (m_pal_ntsc) @@ -609,7 +608,6 @@ void v99x8_device::register_w(uint8_t data) void v99x8_device::device_start() { - m_int_callback.resolve_safe(); m_vdp_ops_count = 1; m_vdp_engine = nullptr; @@ -627,7 +625,7 @@ void v99x8_device::device_start() for (int addr = m_vram_size; addr < 0x30000; addr++) m_vram_space->write_byte(addr, 0xff); } - m_line_timer = timer_alloc(TIMER_LINE); + m_line_timer = timer_alloc(FUNC(v99x8_device::update_line), this); palette_init(); @@ -643,9 +641,8 @@ void v99x8_device::device_start() save_item(NAME(m_stat_reg)); save_item(NAME(m_cont_reg)); save_item(NAME(m_read_ahead)); - // save_item(NAME(m_vram)); - // if ( m_vram_exp != nullptr ) - // save_pointer(NAME(m_vram_exp), 0x10000); + save_item(NAME(m_v9958_sp_mode)); + save_item(NAME(m_address_latch)); save_item(NAME(m_int_state)); save_item(NAME(m_scanline)); save_item(NAME(m_blink)); @@ -695,6 +692,7 @@ void v99x8_device::device_reset() m_cmd_write_first = m_pal_write_first = 0; m_int_state = 0; m_read_ahead = 0; m_address_latch = 0; // ??? + // FIXME: this drifts the scanline number wrt screen h/vpos m_scanline = 0; // MZ: The status registers 4 and 6 hold the high bits of the sprite // collision location. The unused bits are set to 1. @@ -716,7 +714,6 @@ void v99x8_device::device_reset() set_screen_parameters(); } - void v99x8_device::reset_palette() { // taken from V9938 Technical Data book, page 148. it's in G-R-B format @@ -814,6 +811,7 @@ void v99x8_device::check_int() ** called; because of this Mr. Ghost, Xevious and SD Snatcher don't ** run. As a patch it's called every scanline */ + // FIXME: breaks nichibutsu hrdvd.cpp & nichild.cpp, really needs INPUT_MERGER instead. m_int_callback(n); } @@ -1141,76 +1139,123 @@ void v99x8_device::mode_graphic1(uint32_t *ln, int line) void v99x8_device::mode_graphic23(uint32_t *ln, int line) { - pen_t fg, bg, pen; - int nametbl_addr, patterntbl_addr, colourtbl_addr; - int pattern, x, xx, line2, name, charcode, - colour, colourmask, patternmask, xxx; + const int colourmask = ((m_cont_reg[3] & 0x7f) << 3) | 7; + const int patternmask = ((m_cont_reg[4] & 0x03) << 8) | 0xff; + const int scrolled_y = (line + m_cont_reg[23]) & 0xff; + const int colourtbl_addr = ((m_cont_reg[3] & 0x80) << 6) + (m_cont_reg[10] << 14); + const int patterntbl_addr = ((m_cont_reg[4] & 0x3c) << 11); + const pen_t border_pen = pen16(m_cont_reg[7] & 0x0f); - colourmask = ((m_cont_reg[3] & 0x7f) * 8) | 7; - patternmask = ((m_cont_reg[4] & 0x03) * 256) | 0xff; + int nametbl_base = (m_cont_reg[2] << 10) + ((scrolled_y / 8) * 32); + int nametbl_offset = (m_cont_reg[26] & 0x1f); - nametbl_addr = (m_cont_reg[2] << 10); - colourtbl_addr = ((m_cont_reg[3] & 0x80) << 6) + (m_cont_reg[10] << 14); - patterntbl_addr = ((m_cont_reg[4] & 0x3c) << 11); + if (BIT(m_cont_reg[25], 0) && BIT(m_cont_reg[26], 5)) + nametbl_base ^= 0x8000; - line2 = (line + m_cont_reg[23]) & 255; - name = (line2/8)*32; + for (int x = m_offset_x * 2; x > 0; x--) + *ln++ = border_pen; - pen = pen16(m_cont_reg[7] & 0x0f); - xxx = m_offset_x * 2; - while (xxx--) *ln++ = pen; + int dot_scroll = m_cont_reg[27] & 0x07; + int pixels_to_mask = BIT(m_cont_reg[25], 1) ? 8 - dot_scroll : 0; + int pixels_to_draw = 256 - dot_scroll; + while (dot_scroll--) + { + *ln++ = border_pen; + *ln++ = border_pen; + } - for (x=0;x<32;x++) + do { - charcode = m_vram_space->read_byte(nametbl_addr + name) + (line2&0xc0)*4; - colour = m_vram_space->read_byte(colourtbl_addr + ((charcode&colourmask)*8+(line2&7))); - pattern = m_vram_space->read_byte(patterntbl_addr + ((charcode&patternmask)*8+(line2&7))); - fg = pen16(colour >> 4); - bg = pen16(colour & 15); - for (xx=0;xx<8;xx++) + const int charcode = m_vram_space->read_byte(nametbl_base + nametbl_offset) + ((scrolled_y & 0xc0) << 2); + const u8 colour = m_vram_space->read_byte(colourtbl_addr + ((charcode & colourmask) << 3) + (scrolled_y & 7)); + u8 pattern = m_vram_space->read_byte(patterntbl_addr + ((charcode & patternmask) << 3) + (scrolled_y & 7)); + const pen_t fg = pen16(colour >> 4); + const pen_t bg = pen16(colour & 0x0f); + for (int x = 0; x < 8 && pixels_to_draw > 0; x++) { - *ln++ = (pattern & 0x80) ? fg : bg; - *ln++ = (pattern & 0x80) ? fg : bg; + if (!pixels_to_mask) + { + *ln++ = (pattern & 0x80) ? fg : bg; + *ln++ = (pattern & 0x80) ? fg : bg; + } + else + { + pixels_to_mask--; + *ln++ = border_pen; + *ln++ = border_pen; + } + pixels_to_draw--; pattern <<= 1; } - name++; + nametbl_offset = (nametbl_offset + 1) & 0x1f; + if (BIT(m_cont_reg[25], 0) && !nametbl_offset) + nametbl_base ^= 0x8000; } + while (pixels_to_draw > 0); - xx = (16 - m_offset_x) * 2; - while (xx--) *ln++ = pen; + for (int x = (16 - m_offset_x) * 2; x > 0; x--) + *ln++ = border_pen; } void v99x8_device::mode_graphic4(uint32_t *ln, int line) { - int nametbl_addr, colour; - int line2, linemask, x, xx; - pen_t pen, pen_bg; + int linemask = ((m_cont_reg[2] & 0x1f) << 3) | 7; + const int scrolled_y = ((line + m_cont_reg[23]) & linemask) & 0xff; + const pen_t border_pen = pen16(m_cont_reg[7] & 0x0f); - linemask = ((m_cont_reg[2] & 0x1f) << 3) | 7; + int nametbl_base = ((m_cont_reg[2] & 0x40) << 10) + (scrolled_y << 7); + int nametbl_offset = (m_cont_reg[26] & 0x1f) << 2; + if (!BIT(m_cont_reg[25], 0) && BIT(m_cont_reg[2], 5) && v9938_second_field()) + nametbl_base += 0x8000; + if (BIT(m_cont_reg[25], 0) && BIT(m_cont_reg[26], 5)) + nametbl_base ^= 0x8000; - line2 = ((line + m_cont_reg[23]) & linemask) & 255; + for (int x = m_offset_x * 2; x > 0; x--) + *ln++ = border_pen; - nametbl_addr = ((m_cont_reg[2] & 0x40) << 10) + line2 * 128; - if ( (m_cont_reg[2] & 0x20) && v9938_second_field() ) - nametbl_addr += 0x8000; - - pen_bg = pen16(m_cont_reg[7] & 0x0f); - xx = m_offset_x * 2; - while (xx--) *ln++ = pen_bg; + int dot_scroll = m_cont_reg[27] & 0x07; + int pixels_to_mask = BIT(m_cont_reg[25], 1) ? 8 - dot_scroll : 0; + int pixels_to_draw = 256 - dot_scroll; + while (dot_scroll--) + { + *ln++ = border_pen; + *ln++ = border_pen; + } - for (x=0;x<128;x++) + do { - colour = m_vram_space->read_byte(nametbl_addr++); - pen = pen16(colour >> 4); - *ln++ = pen; - *ln++ = pen; - pen = pen16(colour & 15); - *ln++ = pen; - *ln++ = pen; + bool mask_pixel_1 = false; + bool mask_pixel_2 = false; + if (pixels_to_mask) + { + mask_pixel_1 = true; + pixels_to_mask--; + if (pixels_to_mask) + { + mask_pixel_2 = true; + pixels_to_mask--; + } + } + const u8 colour = m_vram_space->read_byte(nametbl_base + nametbl_offset); + const pen_t pen1 = mask_pixel_1 ? border_pen : pen16(colour >> 4); + const pen_t pen2 = mask_pixel_2 ? border_pen : pen16(colour & 0x0f); + *ln++ = pen1; + *ln++ = pen1; + pixels_to_draw--; + if (pixels_to_draw) + { + *ln++ = pen2; + *ln++ = pen2; + pixels_to_draw--; + } + nametbl_offset = (nametbl_offset + 1) & 0x7f; + if (BIT(m_cont_reg[25], 0) && !nametbl_offset) + nametbl_base ^= 0x8000; } + while (pixels_to_draw > 0); - xx = (16 - m_offset_x) * 2; - while (xx--) *ln++ = pen_bg; + for (int x = (16 - m_offset_x) * 2; x > 0; x--) + *ln++ = border_pen; } void v99x8_device::mode_graphic5(uint32_t *ln, int line) @@ -1427,20 +1472,17 @@ void v99x8_device::mode_graphic7(uint32_t *ln, int line) void v99x8_device::mode_unknown(uint32_t *ln, int line) { - pen_t fg, bg; - int x; + const pen_t fg = pen16(m_cont_reg[7] >> 4); + const pen_t bg = pen16(m_cont_reg[7] & 0x0f); - fg = pen16(m_cont_reg[7] >> 4); - bg = pen16(m_cont_reg[7] & 15); + for (int x = m_offset_x * 2; x > 0; x--) + *ln++ = bg; - x = m_offset_x * 2; - while (x--) *ln++ = bg; + for (int x = 512; x > 0; x--) + *ln++ = fg; - x = 512; - while (x--) *ln++ = fg; - - x = (16 - m_offset_x) * 2; - while (x--) *ln++ = bg; + for (int x = (16 - m_offset_x) * 2; x > 0; x--) + *ln++ = bg; } void v99x8_device::default_draw_sprite(uint32_t *ln, uint8_t *col) @@ -1866,12 +1908,12 @@ void v99x8_device::refresh_32(int line) if (m_cont_reg[9] & 0x08) { - ln = &m_bitmap.pix32(m_scanline*2+((m_stat_reg[2]>>1)&1)); + ln = &m_bitmap.pix(m_scanline*2+((m_stat_reg[2]>>1)&1)); } else { - ln = &m_bitmap.pix32(m_scanline*2); - ln2 = &m_bitmap.pix32(m_scanline*2+1); + ln = &m_bitmap.pix(m_scanline*2); + ln2 = &m_bitmap.pix(m_scanline*2+1); double_lines = true; } @@ -2918,13 +2960,11 @@ void v99x8_device::report_vdp_command(uint8_t Op) /*************************************************************/ uint8_t v99x8_device::command_unit_w(uint8_t Op) { - int SM; - // V9938 ops only work in SCREENs 5-8 - if (m_mode<5) + if (m_mode<5 || m_mode>8) return(0); - SM = m_mode-5; // Screen mode index 0..3 + int SM = m_mode-5; // Screen mode index 0..3 m_mmc.CM = Op>>4; if ((m_mmc.CM & 0x0C) != 0x0C && m_mmc.CM != 0) @@ -3059,3 +3099,45 @@ void v99x8_device::update_command() if(m_vdp_engine) (this->*m_vdp_engine)(); } } + +void v99x8_device::device_post_load() // TODO: is there a better way to restore this? +{ + switch(m_mmc.CM) + { + case CM_ABRT: + case CM_POINT: + case CM_PSET: + m_vdp_engine=nullptr; + break; + case CM_SRCH: + m_vdp_engine=&v99x8_device::srch_engine; + break; + case CM_LINE: + m_vdp_engine=&v99x8_device::line_engine; + break; + case CM_LMMV: + m_vdp_engine=&v99x8_device::lmmv_engine; + break; + case CM_LMMM: + m_vdp_engine=&v99x8_device::lmmm_engine; + break; + case CM_LMCM: + m_vdp_engine=&v99x8_device::lmcm_engine; + break; + case CM_LMMC: + m_vdp_engine=&v99x8_device::lmmc_engine; + break; + case CM_HMMV: + m_vdp_engine=&v99x8_device::hmmv_engine; + break; + case CM_HMMM: + m_vdp_engine=&v99x8_device::hmmm_engine; + break; + case CM_YMMM: + m_vdp_engine=&v99x8_device::ymmm_engine; + break; + case CM_HMMC: + m_vdp_engine=&v99x8_device::hmmc_engine; + break; + } +} |