diff options
Diffstat (limited to 'src/devices/video/upd7220.cpp')
-rw-r--r-- | src/devices/video/upd7220.cpp | 783 |
1 files changed, 449 insertions, 334 deletions
diff --git a/src/devices/video/upd7220.cpp b/src/devices/video/upd7220.cpp index ab135fd5a29..95fe02f0326 100644 --- a/src/devices/video/upd7220.cpp +++ b/src/devices/video/upd7220.cpp @@ -1,60 +1,74 @@ // license:BSD-3-Clause // copyright-holders:Angelo Salese, Miodrag Milanovic, Carl, Brian Johnson -/********************************************************************** +/************************************************************************************************** + +Intel 82720 Graphics Display Controller emulation +a.k.a. NEC uPD7220 + +TODO: +- implement FIFO as ring buffer; +- incomplete / unimplemented FIGD / GCHRD draw modes; +\- FIGD character +\- slanted character +- read-modify-write cycle (fixed by now?); +- a5105: has a FIFO bug with the RDAT, should be a lot larger when it scrolls up. + Can be fixed with a DRDY mechanism for RDAT/WDAT (fixed by now?); +- later pc9801/pc9821 machines: throws "Invalid command byte 05" (zettmj on Epson logo), + actual undocumented command to reset something? +- wide mode (32-bit access); +- microbx2: sets mode=0x1f (interlace), oddly cuts off area scroll on prompt (double height chars?) + while DEMO.1 don't. +- repeat fields interlace mode; +- support non-draw on retrace mode (pc98 bitmap layer -> potential raster effects), better + honoring of visible area (bail out thru m_al, cutting off unnecessary comparisons); +- light pen; + +**************************************************************************************************/ - Intel 82720 Graphics Display Controller emulation - also known as NEC uPD7220 - -**********************************************************************/ - -/* - - TODO: - - - implement FIFO as ring buffer - - incomplete / unimplemented FIGD / GCHRD draw modes - - FIGD character - - slanted character - - read-modify-write cycle - - read data - - modify data - - write data - - compis2 SAD address for bitmap is 0x20000 for whatever reason (presumably missing banking); - - A5105 has a FIFO bug with the RDAT, should be a lot larger when it scrolls up. - Can be fixed with a DRDY mechanism for RDAT/WDAT; - - Some later SWs on PC-98 throws "Invalid command byte 05" (zettmj on Epson logo), - actual undocumented command to reset something or perhaps just check if upd7220 isn't really a upd72120 instead? - - - honor visible area - - wide mode (32-bit access) - - light pen -*/ #include "emu.h" #include "upd7220.h" #include "screen.h" -//#define VERBOSE 1 -#include "logmacro.h" +#define LOG_CRTC (1U << 1) +#define LOG_DRAW (1U << 2) +#define LOG_AREA (1U << 3) // printout works best with -oslog +#define LOG_CMD (1U << 4) +#define LOG_CMD2 (1U << 5) // DE related commands +#define LOG_CMD3 (1U << 6) // memory interface (RDAT/WDAT) +#define LOG_CMD4 (1U << 7) // DMA +#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" +#define LOGCRTC(...) LOGMASKED(LOG_CRTC, __VA_ARGS__) +#define LOGDRAW(...) LOGMASKED(LOG_DRAW, __VA_ARGS__) +#define LOGAREA(...) LOGMASKED(LOG_AREA, __VA_ARGS__) +#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__) +#define LOGCMD2(...) LOGMASKED(LOG_CMD2, __VA_ARGS__) +#define LOGCMD3(...) LOGMASKED(LOG_CMD3, __VA_ARGS__) +#define LOGCMD4(...) LOGMASKED(LOG_CMD4, __VA_ARGS__) //************************************************************************** // MACROS / CONSTANTS //************************************************************************** -// todo typedef +// TODO: typedef enum { COMMAND_INVALID = -1, COMMAND_RESET, + COMMAND_RESET2, + COMMAND_RESET3, COMMAND_SYNC, COMMAND_VSYNC, COMMAND_CCHAR, COMMAND_START, - COMMAND_BCTRL, + COMMAND_BLANK, + COMMAND_BLANK2, COMMAND_ZOOM, COMMAND_CURS, COMMAND_PRAM, @@ -69,8 +83,7 @@ enum COMMAND_LPRD, COMMAND_DMAR, COMMAND_DMAW, - COMMAND_5A, - COMMAND_05 + COMMAND_5A }; enum @@ -87,12 +100,14 @@ enum }; #define UPD7220_COMMAND_RESET 0x00 +#define UPD7220_COMMAND_RESET2 0x01 +#define UPD7220_COMMAND_RESET3 0x09 #define UPD7220_COMMAND_SYNC 0x0e // & 0xfe #define UPD7220_COMMAND_VSYNC 0x6e // & 0xfe #define UPD7220_COMMAND_CCHAR 0x4b #define UPD7220_COMMAND_START 0x6b -#define UPD7220_COMMAND_BCTRL 0x0c // & 0xfe -#define UPD7220_COMMAND_05 0x05 +#define UPD7220_COMMAND_BLANK 0x0c // & 0xfe +#define UPD7220_COMMAND_BLANK2 0x05 #define UPD7220_COMMAND_ZOOM 0x46 #define UPD7220_COMMAND_CURS 0x49 #define UPD7220_COMMAND_PRAM 0x70 // & 0xf0 @@ -142,6 +157,7 @@ static constexpr int y_dir[8] = { 1, 1, 0,-1,-1,-1, 0, 1}; // devices DEFINE_DEVICE_TYPE(UPD7220, upd7220_device, "upd7220", "NEC uPD7220") +DEFINE_DEVICE_TYPE(UPD7220A, upd7220a_device, "upd7220a", "NEC uPD7220A") // default address map @@ -159,6 +175,11 @@ ROM_START( upd7220 ) ROM_LOAD( "upd7220.bin", 0x000, 0x100, CRC(3c92b218) SHA1(e154b3106a80c9c98d9f2ee18efcd7f4b4aa7d49) ) ROM_END +ROM_START( upd7220a ) + ROM_REGION( 0x100, "upd7220", 0 ) + ROM_LOAD( "upd7220a.bin", 0x000, 0x100, NO_DUMP ) +ROM_END + //------------------------------------------------- // memory_space_config - return a description of @@ -182,6 +203,10 @@ const tiny_rom_entry *upd7220_device::device_rom_region() const return ROM_NAME( upd7220 ); } +const tiny_rom_entry *upd7220a_device::device_rom_region() const +{ + return ROM_NAME( upd7220a ); +} //************************************************************************** @@ -306,6 +331,12 @@ inline void upd7220_device::dequeue(uint8_t *data, int *flag) if (m_fifo_ptr == -1) m_sr &= ~UPD7220_SR_DATA_READY; } + else + { + // TODO: underflow details + // pc9821:skinpan does SR checks over the wrong port during intro ... + *data = 0xff; + } } @@ -315,7 +346,12 @@ inline void upd7220_device::dequeue(uint8_t *data, int *flag) inline void upd7220_device::update_vsync_timer(int state) { - int next_y = state ? m_vs : 0; + const int vert_mult = (m_mode & UPD7220_MODE_INTERLACE_MASK) == UPD7220_MODE_INTERLACE_ON ? 2 : 1; + + // page 6-68, route vsync so that top is start of back porch, end is at sync time + // (at bottom of MAME vpos() mechanism) + // - pc9801:lemmings and pc9801:spindiz2 cares + int next_y = state ? 0 : (m_vbp + m_al + m_vfp) * vert_mult; attotime duration = screen().time_until_pos(next_y, 0); @@ -329,10 +365,11 @@ inline void upd7220_device::update_vsync_timer(int state) inline void upd7220_device::update_hsync_timer(int state) { + const int horiz_mult = (m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_GRAPHICS ? 16 : 8; int y = screen().vpos(); - int next_x = state ? m_hs : 0; - int next_y = state ? y : ((y + 1) % m_al); + int next_x = state ? m_hs * horiz_mult : 0; + int next_y = state ? y : ((y + 1) % (m_vs + m_vbp + m_al + m_vfp - 1)); attotime duration = screen().time_until_pos(next_y, next_x); @@ -361,19 +398,18 @@ inline void upd7220_device::update_blank_timer(int state) // recompute_parameters - //------------------------------------------------- +void upd7220_device::device_clock_changed() +{ + recompute_parameters(); +} + inline void upd7220_device::recompute_parameters() { - int horiz_mult = 16, vert_mult = 1; - /* TODO: assume that the pitch also controls number of horizontal pixels in a single cell */ - // horiz_mult = 4 if both mixed and interlace? - if((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_MIXED) - horiz_mult = 8; - else if((m_mode & UPD7220_MODE_INTERLACE_MASK) == UPD7220_MODE_INTERLACE_ON) - { - // in interlaced mode every line contains both fields - horiz_mult = 8; // TODO this breaks compis uhrg video, characters are 16 pixels wide in interlaced mode too - vert_mult = 2; - } + // microbx2 wants horizontal multiplier of x16 + // pc9801:diremono sets up m_mode to be specifically in character mode, wanting x8 here + // TODO: verify compis uhrg video & high reso Hyper 98 + const int horiz_mult = (m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_GRAPHICS ? 16 : 8; + const int vert_mult = (m_mode & UPD7220_MODE_INTERLACE_MASK) == UPD7220_MODE_INTERLACE_ON ? 2 : 1; int horiz_pix_total = (m_hs + m_hbp + m_hfp + m_aw) * horiz_mult; int vert_pix_total = (m_vs + m_vbp + m_al + m_vfp) * vert_mult; @@ -392,14 +428,15 @@ inline void upd7220_device::recompute_parameters() m_vbp, //m_vs + m_vbp; m_al * vert_mult + m_vbp - 1);//vert_pix_total - m_vfp - 1; - LOG("uPD7220 Screen: %u x %u @ %f Hz\n", horiz_pix_total, vert_pix_total, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); - LOG("Visible Area: (%u, %u) - (%u, %u)\n", visarea.left(), visarea.top(), visarea.right(), visarea.bottom()); - LOG("%d %d %d %d %d\n",m_hs,m_hbp,m_aw,m_hfp,m_pitch); - LOG("%d %d %d %d\n",m_vs,m_vbp,m_al,m_vfp); + LOGCRTC("New Screen setup: %u x %u @ %f Hz\n", horiz_pix_total, vert_pix_total, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); + LOGCRTC("Visible Area: (%u, %u) - (%u, %u)\n", visarea.left(), visarea.top(), visarea.right(), visarea.bottom()); + //LOGCRTC("%d %d %d %d %d\n",m_hs,m_hbp,m_aw,m_hfp,m_pitch); + //LOGCRTC("%d %d %d %d\n",m_vs,m_vbp,m_al,m_vfp); if (m_m) { screen().configure(horiz_pix_total, vert_pix_total, visarea, refresh); + screen().reset_origin(); update_hsync_timer(0); update_vsync_timer(0); @@ -427,7 +464,7 @@ inline void upd7220_device::reset_figs_param() m_figs.m_dm = 0xffff; m_figs.m_gd = 0; m_figs.m_figure_type = 0; - m_pattern = 0xffff; + m_pattern = (m_ra[8]) | (m_ra[9] << 8); } @@ -437,7 +474,7 @@ inline void upd7220_device::reset_figs_param() inline uint16_t upd7220_device::read_vram() { uint16_t const data = readword(m_ead); - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * get_pitch()); m_ead &= 0x3ffff; return data; @@ -447,28 +484,28 @@ inline void upd7220_device::rdat(uint8_t type, uint8_t mod) { if (type == 1) { - LOG("uPD7220 invalid type 1 RDAT parameter\n"); + LOG("invalid type 1 RDAT parameter\n"); return; } if (mod) - LOG("uPD7220 RDAT used with mod = %02x?\n",mod); + LOG("RDAT used with mod = %02x?\n",mod); while (m_figs.m_dc && m_fifo_ptr < (type ? 15 : 14)) { uint16_t const data = read_vram(); switch(type) { - case 0: - queue(data & 0xff, 0); - queue((data >> 8) & 0xff, 0); - break; - case 2: - queue(data & 0xff, 0); - break; - case 3: - queue((data >> 8) & 0xff, 0); - break; + case 0: + queue(data & 0xff, 0); + queue((data >> 8) & 0xff, 0); + break; + case 2: + queue(data & 0xff, 0); + break; + case 3: + queue((data >> 8) & 0xff, 0); + break; } m_figs.m_dc--; @@ -487,38 +524,38 @@ inline void upd7220_device::write_vram(uint8_t type, uint8_t mod, uint16_t data, switch(mod & 3) { - case 0x00: //replace - if(type == 0) - current = (current & (~mask)) | (data & mask); - if(type == 2) - current = (current & ~(mask & 0xff)) | (data & (mask & 0xff)); - if(type == 3) - current = (current & ~(mask & 0xff00)) | (data & (mask & 0xff00)); - break; - case 0x01: //complement - if(type == 0) - current = current ^ (data & mask); - if(type == 2) - current = current ^ (data & (mask & 0xff)); - if(type == 3) - current = current ^ (data & (mask & 0xff00)); - break; - case 0x02: //reset to zero - if(type == 0) - current = current & ~(data & mask); - if(type == 2) - current = current & ~(data & (mask & 0xff)); - if(type == 3) - current = current & ~(data & (mask & 0xff00)); - break; - case 0x03: //set to one - if(type == 0) - current = current | (data & mask); - if(type == 2) - current = current | (data & (mask & 0xff)); - if(type == 3) - current = current | (data & (mask & 0xff00)); - break; + case 0x00: //replace + switch (type) + { + case 0: current = (current & (~mask)) | (data & mask); break; + case 2: current = (current & ~(mask & 0xff)) | (data & (mask & 0xff)); break; + case 3: current = (current & ~(mask & 0xff00)) | (data & (mask & 0xff00)); break; + } + break; + case 0x01: //complement + switch (type) + { + case 0: current = current ^ (data & mask); break; + case 2: current = current ^ (data & (mask & 0xff)); break; + case 3: current = current ^ (data & (mask & 0xff00)); break; + } + break; + case 0x02: //reset to zero + switch (type) + { + case 0: current = current & ~(data & mask); break; + case 2: current = current & ~(data & (mask & 0xff)); break; + case 3: current = current & ~(data & (mask & 0xff00)); break; + } + break; + case 0x03: //set to one + switch (type) + { + case 0: current = current | (data & mask); break; + case 2: current = current | (data & (mask & 0xff)); break; + case 3: current = current | (data & (mask & 0xff00)); break; + } + break; } writeword(m_ead, current); } @@ -535,16 +572,16 @@ inline void upd7220_device::wdat(uint8_t type, uint8_t mod) switch(type) { - case 0: - result &= m_mask; - break; - case 2: - result &= (m_mask & 0xff); - break; - case 3: - result <<= 8; - result &= (m_mask & 0xff00); - break; + case 0: + result &= m_mask; + break; + case 2: + result &= (m_mask & 0xff); + break; + case 3: + result <<= 8; + result &= (m_mask & 0xff00); + break; } //if(result) @@ -557,7 +594,7 @@ inline void upd7220_device::wdat(uint8_t type, uint8_t mod) for(int i = 0; i < m_figs.m_dc + 1; i++) { write_vram(type, mod, result); - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * get_pitch()); m_ead &= 0x3ffff; } } @@ -588,6 +625,19 @@ inline void upd7220_device::get_graphics_partition(int index, uint32_t *sad, uin *wd = BIT(m_ra[(index * 4) + 3], 7); } +/* + * experimental, for non-canonical stuff such as PC9821 PEGC + */ +std::tuple<u32, u16, u8> upd7220_device::get_area_partition_props(int line) +{ + uint32_t sad; + uint16_t len; + int im, wd; + // TODO: multiareas (pc9821:skinpan title) + get_graphics_partition(0, &sad, &len, &im, &wd); + + return std::make_tuple(sad, m_pitch, im); +} //************************************************************************** @@ -598,8 +648,8 @@ inline void upd7220_device::get_graphics_partition(int index, uint32_t *sad, uin // upd7220_device - constructor //------------------------------------------------- -upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, UPD7220, tag, owner, clock), +upd7220_device::upd7220_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), device_memory_interface(mconfig, *this), device_video_interface(mconfig, *this), m_display_cb(*this), @@ -657,6 +707,16 @@ upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, d memset(&m_figs, 0x00, sizeof(m_figs)); } +upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : upd7220_device(mconfig, UPD7220, tag, owner, clock) +{ +} + +upd7220a_device::upd7220a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : upd7220_device(mconfig, UPD7220A, tag, owner, clock) +{ +} + //------------------------------------------------- // device_start - device-specific startup @@ -789,7 +849,7 @@ TIMER_CALLBACK_MEMBER(upd7220_device::blank_update) void upd7220_device::draw_pixel() { - LOG("uPD7220 dot check: %08x %04x %02x %02x %d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc); + LOGDRAW("draw_pixel(): EAD=%08x MASK=%04x MOD=%02x - FIGS DIR=%02x DC=%d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc); for(int i = 0; i <= m_figs.m_dc; ++i) { @@ -811,7 +871,7 @@ void upd7220_device::draw_line() int d2 = util::sext(m_figs.m_d2, 14); const uint8_t octant = m_figs.m_dir; - LOG("uPD7220 line check: %08x %04x %02x %02x %d %d %d %d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, d, d1, d2); + LOGDRAW("draw_line(): EAD=%08x MASK=%04x MOD=%02x - FIGS DIR=%02x DC=%d D=%d D1=%d D2=%d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, d, d1, d2); for(int i = 0; i <= m_figs.m_dc; ++i) { @@ -825,7 +885,7 @@ void upd7220_device::draw_line() { m_figs.m_dir = (d < 0) ? octant : (octant + 1) & 7; } - d += ((d < 0 ) ? d1 : d2); + d += ((d < 0) ? d1 : d2); next_pixel(m_figs.m_dir); } } @@ -841,7 +901,7 @@ void upd7220_device::draw_arc() const uint16_t octant = m_figs.m_dir; - LOG("uPD7220 arc check: %08x %04x %02x %02x %d %d %d %d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, m_figs.m_d, m_figs.m_d2, m_figs.m_dm); + LOGDRAW("draw_arc(): EAD=%08x MASK=%04x MOD=%02x - FIGS DIR=%02x DC=%d D=%d D2=%d DM=%d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, m_figs.m_d, m_figs.m_d2, m_figs.m_dm); for (int i = 0; i <= m_figs.m_dc; ++i) { @@ -872,7 +932,7 @@ void upd7220_device::draw_rectangle() { assert(m_figs.m_dc == 3); - LOG("uPD7220 rectangle check: %08x %04x %02x %02x %d %d %d\n",m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, m_figs.m_d, m_figs.m_d2); + LOGDRAW("draw_rectangle(): EAD=%08x MASK=%04x MOD=%02x - FIGS DIR=%02x DC=%d D=%d D2=%d\n",m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, m_figs.m_d, m_figs.m_d2); for (int i = 0; i <= m_figs.m_dc; ++i) { @@ -902,8 +962,7 @@ void upd7220_device::draw_char() }; const uint8_t type = (m_figs.m_figure_type & 0x10) >> 4; - - LOG("uPD7220 char check: %08x %04x %02x %02x %d %d %02x\n",m_ead,m_mask,m_bitmap_mod,m_figs.m_dir,m_figs.m_d,m_figs.m_dc,m_figs.m_figure_type); + LOGDRAW("draw_char(): EAD=%08x MASK=%04x MOD=%02x DIR=%02x D=%d DC=%d FIGURE=%02x\n",m_ead,m_mask,m_bitmap_mod,m_figs.m_dir,m_figs.m_d,m_figs.m_dc,m_figs.m_figure_type); for (int i = 0, di = 0; i < (m_figs.m_dc + 1); ++i) { @@ -984,58 +1043,58 @@ void upd7220_device::next_pixel(int direction) { switch(direction & 7) { - case 0: - m_ead += get_pitch(); - break; - case 1: - m_ead += get_pitch(); - if (m_mask & 0x8000) - { - m_ead += 1; - } - m_mask = rotate_left(m_mask); - break; - case 2: - if (m_mask & 0x8000) - { - m_ead += 1; - } - m_mask = rotate_left(m_mask); - break; - case 3: - m_ead -= get_pitch(); - if (m_mask & 0x8000) - { - m_ead += 1; - } - m_mask = rotate_left(m_mask); - break; - case 4: - m_ead -= get_pitch(); - break; - case 5: - m_ead -= get_pitch(); - if (m_mask & 0x1) - { - m_ead -= 1; - } - m_mask = rotate_right(m_mask); - break; - case 6: - if (m_mask & 0x1) - { - m_ead -= 1; - } - m_mask = rotate_right(m_mask); - break; - case 7: - m_ead += get_pitch(); - if (m_mask & 0x1) - { - m_ead -= 1; - } - m_mask = rotate_right(m_mask); - break; + case 0: + m_ead += get_pitch(); + break; + case 1: + m_ead += get_pitch(); + if (m_mask & 0x8000) + { + m_ead += 1; + } + m_mask = rotate_left(m_mask); + break; + case 2: + if (m_mask & 0x8000) + { + m_ead += 1; + } + m_mask = rotate_left(m_mask); + break; + case 3: + m_ead -= get_pitch(); + if (m_mask & 0x8000) + { + m_ead += 1; + } + m_mask = rotate_left(m_mask); + break; + case 4: + m_ead -= get_pitch(); + break; + case 5: + m_ead -= get_pitch(); + if (m_mask & 0x1) + { + m_ead -= 1; + } + m_mask = rotate_right(m_mask); + break; + case 6: + if (m_mask & 0x1) + { + m_ead -= 1; + } + m_mask = rotate_right(m_mask); + break; + case 7: + m_ead += get_pitch(); + if (m_mask & 0x1) + { + m_ead -= 1; + } + m_mask = rotate_right(m_mask); + break; } m_ead &= 0x3ffff; } @@ -1064,13 +1123,12 @@ int upd7220_device::translate_command(uint8_t data) case UPD7220_COMMAND_CURD: command = COMMAND_CURD; break; case UPD7220_COMMAND_LPRD: command = COMMAND_LPRD; break; case UPD7220_COMMAND_5A: command = COMMAND_5A; break; - case UPD7220_COMMAND_05: command = COMMAND_05; break; default: switch (data & 0xfe) { case UPD7220_COMMAND_SYNC: command = COMMAND_SYNC; break; case UPD7220_COMMAND_VSYNC: command = COMMAND_VSYNC; break; - case UPD7220_COMMAND_BCTRL: command = COMMAND_BCTRL; break; + case UPD7220_COMMAND_BLANK: command = COMMAND_BLANK; break; default: switch (data & 0xf0) { @@ -1090,6 +1148,20 @@ int upd7220_device::translate_command(uint8_t data) return command; } +int upd7220a_device::translate_command(uint8_t data) +{ + int command = upd7220_device::translate_command(data); + + switch (data) + { + case UPD7220_COMMAND_RESET2: command = COMMAND_RESET2; break; + case UPD7220_COMMAND_RESET3: command = COMMAND_RESET3; break; + case UPD7220_COMMAND_BLANK2: command = COMMAND_BLANK2; break; + } + + return command; +} + //------------------------------------------------- // process_fifo - @@ -1106,7 +1178,7 @@ void upd7220_device::process_fifo() if (flag == FIFO_COMMAND) { cr = translate_command(data); - if (cr != COMMAND_BCTRL) // workaround for Rainbow 100 Windows 1.03, needs verification + if (cr != COMMAND_BLANK) // workaround for Rainbow 100 Windows 1.03, needs verification { m_cr = data; m_param_ptr = 1; @@ -1131,16 +1203,29 @@ void upd7220_device::process_fifo() break; case COMMAND_RESET: /* reset */ + case COMMAND_RESET2: + case COMMAND_RESET3: switch (m_param_ptr) { - case 0: - LOG("uPD7220 RESET\n"); - - m_de = 0; - m_ra[0] = m_ra[1] = m_ra[2] = 0; - m_ra[3] = 0x19; + case 1: + LOGCMD("RESET %02x\n", cr); + + if (cr != COMMAND_RESET3) + m_de = 0; + // NOTE: a reset doesn't touch anything belonging to parameters, as stated in docs. + // pc9801:mightyhd won't program sad/len but just issue a reset after BIOS + // (which originally sets len = 0x1ff) + // with this on, it will len = 400 lines, repeating the bottommost two rows in a 432 setup. + //m_ra[0] = m_ra[1] = m_ra[2] = 0; + //m_ra[3] = 0x19; m_ead = 0; + // TODO: very unlikely, should be 0xffff assuming it's even touched ... m_mask = 0; + // FIFO, Command Processor and internal counters are cleared by this + // - pc9801rs BIOS starts up a DMAW command that spindiz2 will dislike during its boot sequences + m_sr &= ~UPD7220_SR_DRAWING_IN_PROGRESS; + fifo_clear(); + stop_dma(); break; case 9: @@ -1156,16 +1241,15 @@ void upd7220_device::process_fifo() m_pitch = m_aw; - LOG("uPD7220 Mode: %02x\n", m_mode); - LOG("uPD7220 AW: %u\n", m_aw); - LOG("uPD7220 HS: %u\n", m_hs); - LOG("uPD7220 VS: %u\n", m_vs); - LOG("uPD7220 HFP: %u\n", m_hfp); - LOG("uPD7220 HBP: %u\n", m_hbp); - LOG("uPD7220 VFP: %u\n", m_vfp); - LOG("uPD7220 AL: %u\n", m_al); - LOG("uPD7220 VBP: %u\n", m_vbp); - LOG("uPD7220 PITCH: %u\n", m_pitch); + if (type() == UPD7220A) + { + m_pitch = ((m_pr[5] & 0x40) << 2) | (m_pitch & 0xff); + m_al += (m_pr[6] >> 6) & 1; + } + + LOGCMD("- Mode: %02x\n", m_mode); + LOGCMD("- HS=%u HBP=%u AW=%u HFP=%u PITCH=%u\n", m_hs, m_hbp, m_aw, m_hfp, m_pitch); + LOGCMD("- VS=%u VBP=%u AL=%u VFP=%u\n", m_vs, m_vbp, m_al, m_vfp); recompute_parameters(); break; @@ -1176,8 +1260,10 @@ void upd7220_device::process_fifo() if (flag == FIFO_COMMAND) { m_de = m_cr & 1; + LOGCMD2("SYNC %u\n", m_de); } + // TODO: merge implementation with above if (m_param_ptr == 9) { m_mode = m_pr[1]; @@ -1192,16 +1278,15 @@ void upd7220_device::process_fifo() m_pitch = m_aw; - LOG("uPD7220 Mode: %02x\n", m_mode); - LOG("uPD7220 AW: %u\n", m_aw); - LOG("uPD7220 HS: %u\n", m_hs); - LOG("uPD7220 VS: %u\n", m_vs); - LOG("uPD7220 HFP: %u\n", m_hfp); - LOG("uPD7220 HBP: %u\n", m_hbp); - LOG("uPD7220 VFP: %u\n", m_vfp); - LOG("uPD7220 AL: %u\n", m_al); - LOG("uPD7220 VBP: %u\n", m_vbp); - LOG("uPD7220 PITCH: %u\n", m_pitch); + if (type() == UPD7220A) + { + m_pitch = ((m_pr[5] & 0x40) << 2) | (m_pitch & 0xff); + m_al += (m_pr[6] >> 6) & 1; + } + + LOGCMD("- Mode: %02x\n", m_mode); + LOGCMD("- HS=%u HBP=%u AW=%u HFP=%u PITCH=%u\n", m_hs, m_hbp, m_aw, m_hfp, m_pitch); + LOGCMD("- VS=%u VBP=%u AL=%u VFP=%u\n", m_vs, m_vbp, m_al, m_vfp); recompute_parameters(); } @@ -1210,55 +1295,54 @@ void upd7220_device::process_fifo() case COMMAND_VSYNC: /* vertical sync mode */ m_m = m_cr & 0x01; - LOG("uPD7220 M: %u\n", m_m); + LOGCMD("VSYNC M=%u\n", m_m); recompute_parameters(); break; case COMMAND_CCHAR: /* cursor & character characteristics */ - if(m_param_ptr == 2) + switch (m_param_ptr) { + case 2: m_lr = (m_pr[1] & 0x1f) + 1; m_dc = BIT(m_pr[1], 7); - LOG("uPD7220 LR: %u\n", m_lr); - LOG("uPD7220 DC: %u\n", m_dc); - } + LOGCMD("CCHAR LR=%u DC=%u\n", m_lr, m_dc); + break; - if(m_param_ptr == 3) - { + case 3: m_ctop = m_pr[2] & 0x1f; m_sc = BIT(m_pr[2], 5); m_br = (m_pr[2] >> 6); /* guess, assume that blink rate clears upper bits (if any) */ - LOG("uPD7220 CTOP: %u\n", m_ctop); - LOG("uPD7220 SC: %u\n", m_sc); - } + LOGCMD("- CTOP=%u SC=%u\n", m_ctop, m_sc); + break; - if(m_param_ptr == 4) - { + case 4: m_br = ((m_pr[3] & 0x07) << 2) | (m_pr[2] >> 6); m_cbot = m_pr[3] >> 3; - LOG("uPD7220 BR: %u\n", m_br); - LOG("uPD7220 CBOT: %u\n", m_cbot); + LOGCMD("- BR=%u CBOT=%u\n", m_br, m_cbot); + break; } break; case COMMAND_START: /* start display & end idle mode */ m_de = 1; - //LOG("uPD7220 '%s' DE: 1\n"); + LOGCMD2("START\n"); break; - case COMMAND_05: + case COMMAND_BLANK2: m_de = 0; + LOGCMD2("BLANK2\n"); + break; - case COMMAND_BCTRL: /* display blanking control */ + case COMMAND_BLANK: /* display blanking control */ m_de = data & 0x01; - //LOG("uPD7220 DE: %u\n", m_de); + LOGCMD2("BLANK %u\n", m_de); break; case COMMAND_ZOOM: /* zoom factors specify */ @@ -1267,8 +1351,7 @@ void upd7220_device::process_fifo() m_gchr = m_pr[1] & 0x0f; m_disp = m_pr[1] >> 4; - LOG("uPD7220 GCHR: %01x\n", m_gchr); - LOG("uPD7220 DISP: %01x\n", m_disp); + LOGCMD("ZOOM GCHR=%01x DISP=%01x\n", m_gchr, m_disp); } break; @@ -1279,12 +1362,12 @@ void upd7220_device::process_fifo() m_ead = (upper_addr << 16) | (m_pr[2] << 8) | m_pr[1]; - LOG("uPD7220 EAD: %06x\n", m_ead); + LOGCMD("CURS EAD: %06x\n", m_ead); if(m_param_ptr == 4) { m_mask = 1 << ((m_pr[3] >> 4) & 0x0f); - LOG("uPD7220 MASK: %04x\n", m_mask); + LOGCMD("- MASK: %04x\n", m_mask); } } break; @@ -1298,12 +1381,13 @@ void upd7220_device::process_fifo() { if (m_ra_addr < 16) { - LOG("uPD7220 RA%u: %02x\n", m_ra_addr, data); + LOGCMD("PRAM RA%u: %02x\n", m_ra_addr, data); - if (m_ra_addr == 8) - m_pattern = (m_pattern & 0xff00) | data; - else if (m_ra_addr == 9) - m_pattern = (m_pattern & 0xff) | (data << 8); + switch (m_ra_addr) + { + case 8: m_pattern = (m_pattern & 0xff00) | data; break; + case 9: m_pattern = (m_pattern & 0x00ff) | (data << 8); break; + } m_ra[m_ra_addr] = data; m_ra_addr++; } @@ -1313,11 +1397,21 @@ void upd7220_device::process_fifo() break; case COMMAND_PITCH: /* pitch specification */ - if (flag == FIFO_PARAMETER) + // pc9801:burai writes a spurious extra value during intro, effectively ignored + // (only first value matters) + if (flag == FIFO_PARAMETER && m_param_ptr == 2) { - m_pitch = data; + m_pitch = (m_pitch & 0x100) | data; - LOG("uPD7220 PITCH: %u\n", m_pitch); + if (m_pitch < 2) + { + // TODO: a pitch of zero will lead to a MAME crash in draw_graphics_line + // Coerce a fail-safe minimum, what should really happen is to be verified ... + popmessage("%s pitch == 0!", this->tag()); + m_pitch = 2; + } + + LOGCMD("PITCH %u\n", m_pitch); } break; @@ -1329,10 +1423,17 @@ void upd7220_device::process_fifo() m_pattern = (m_pattern & 0xff00) | m_pr[1]; if (m_param_ptr == 3) m_pattern = (m_pattern & 0xff) | (m_pr[2] << 8); - LOG("uPD7220 PATTERN: %04x\n", m_pattern); + LOGCMD3("WDAT PATTERN=%04x\n", m_pattern); if (m_figs.m_figure_type) break; - LOG("%02x = %02x %02x (%c) %06x %04x\n",m_cr,m_pr[2],m_pr[1],m_pr[1]?m_pr[1]:' ',m_ead,m_figs.m_dc); + LOGCMD3("- CR=%02x (%02x %02x) (%c) EAD=%06x - FIGS DC=%04x\n" + , m_cr + , m_pr[2] + , m_pr[1] + , m_pr[1] ? m_pr[1]:' ' + , m_ead + , m_figs.m_dc + ); fifo_set_direction(FIFO_WRITE); wdat((m_cr & 0x18) >> 3,m_cr & 3); @@ -1346,91 +1447,89 @@ void upd7220_device::process_fifo() { m_mask = (m_pr[2] << 8) | m_pr[1]; - LOG("uPD7220 MASK: %04x\n", m_mask); + LOGCMD("MASK %04x\n", m_mask); } break; case COMMAND_FIGS: /* figure drawing parameters specify */ - if (m_param_ptr == 2) + switch (m_param_ptr) { + case 2: m_figs.m_dir = m_pr[1] & 0x7; m_figs.m_figure_type = (m_pr[1] & 0xf8) >> 3; - LOG("uPD7220 DIR: %02x\n", m_figs.m_dir); - LOG("uPD7220 FIG: %02x\n", m_figs.m_figure_type); + LOGCMD("FIGS DIR=%02x FIGURE=%02x\n", m_figs.m_dir, m_figs.m_figure_type); //if(m_figs.m_dir != 2) // printf("DIR %02x\n",m_pr[1]); - } + break; - // the Decision Mate V during start-up test upload only 2 params before execute the - // RDAT command, so I assume this is the expected behaviour, but this needs to be verified. - if (m_param_ptr == 3) - { + // the Decision Mate V during start-up test upload only 2 params before execute the + // RDAT command, so I assume this is the expected behaviour, but this needs to be verified. + case 3: m_figs.m_dc = (m_pr[2]) | (m_figs.m_dc & 0x3f00); - LOG("uPD7220 DC: %04x\n", m_figs.m_dc); - } + LOGCMD("- DC=%04x (*)\n", m_figs.m_dc); + break; - if (m_param_ptr == 4) - { + case 4: m_figs.m_dc = (m_pr[2]) | ((m_pr[3] & 0x3f) << 8); m_figs.m_gd = (m_pr[3] & 0x40) && ((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_MIXED); - LOG("uPD7220 DC: %04x\n", m_figs.m_dc); - LOG("uPD7220 GD: %02x\n", m_figs.m_gd); - } + LOGCMD("- DC=%04x\n", m_figs.m_dc); + LOGCMD("- GD=%02x\n", m_figs.m_gd); + break; - if (m_param_ptr == 6) - { + case 6: m_figs.m_d = (m_pr[4]) | ((m_pr[5] & 0x3f) << 8); - LOG("uPD7220 D: %04x\n", m_figs.m_d); - } + LOGCMD("- D=%04x\n", m_figs.m_d); + break; - if (m_param_ptr == 8) - { + case 8: m_figs.m_d2 = (m_pr[6]) | ((m_pr[7] & 0x3f) << 8); - LOG("uPD7220 D2: %04x\n", m_figs.m_d2); - } + LOGCMD("- D2=%04x\n", m_figs.m_d2); + break; - if (m_param_ptr == 10) - { + case 10: m_figs.m_d1 = (m_pr[8]) | ((m_pr[9] & 0x3f) << 8); - LOG("uPD7220 D1: %04x\n", m_figs.m_d1); - } + LOGCMD("- D1=%04x\n", m_figs.m_d1); + break; - if (m_param_ptr == 12) - { + case 12: m_figs.m_dm = (m_pr[10]) | ((m_pr[11] & 0x3f) << 8); - LOG("uPD7220 DM: %04x\n", m_figs.m_dm); + LOGCMD("- DM=%04x\n", m_figs.m_dm); + break; } - break; case COMMAND_FIGD: /* figure draw start */ - if(m_figs.m_figure_type == 0) - draw_pixel(); - else if(m_figs.m_figure_type == 1) - draw_line(); - else if(m_figs.m_figure_type == 4) - draw_arc(); - else if(m_figs.m_figure_type == 8) - draw_rectangle(); - else - logerror("uPD7220 Unimplemented command FIGD %02x\n", m_figs.m_figure_type); - + LOGCMD("FIGD %u\n", m_figs.m_figure_type); + switch (m_figs.m_figure_type) + { + case 0: draw_pixel(); break; + case 1: draw_line(); break; + case 4: draw_arc(); break; + case 8: draw_rectangle(); break; + default: + popmessage("%s Unimplemented command FIGD %02x\n", this->tag(), m_figs.m_figure_type); + break; + } reset_figs_param(); m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS; break; case COMMAND_GCHRD: /* graphics character draw and area filling start */ + LOGCMD("GCHRD %u\n", m_figs.m_figure_type); + if((m_figs.m_figure_type & 0xf) == 2) draw_char(); else - logerror("uPD7220 Unimplemented command GCHRD %02x\n", m_figs.m_figure_type); + popmessage("%s Unimplemented command GCHRD %02x\n", this->tag(), m_figs.m_figure_type); reset_figs_param(); m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS; break; case COMMAND_RDAT: /* read data from display memory */ + LOGCMD3("RDAT %06x %02x\n", m_ead, m_cr); + fifo_set_direction(FIFO_READ); rdat((m_cr & 0x18) >> 3,m_cr & 3); @@ -1439,7 +1538,8 @@ void upd7220_device::process_fifo() break; case COMMAND_CURD: /* cursor address read */ - { + LOGCMD3("CURD %06x\n", m_ead, m_mask); + fifo_set_direction(FIFO_READ); queue(m_ead & 0xff, 0); @@ -1450,9 +1550,10 @@ void upd7220_device::process_fifo() m_sr |= UPD7220_SR_DATA_READY; break; - } case COMMAND_LPRD: /* light pen address read */ + LOGCMD3("LPRD %06x\n", m_lad); + fifo_set_direction(FIFO_READ); queue(m_lad & 0xff, 0); @@ -1464,6 +1565,7 @@ void upd7220_device::process_fifo() break; case COMMAND_DMAR: /* DMA read request */ + LOGCMD4("DMAR CR=%02x DC=%d D=%d\n", m_cr, m_figs.m_dc, m_figs.m_d); m_dma_type = (m_cr >> 3) & 3; m_dma_mod = m_cr & 3; m_dma_transfer_length = (m_figs.m_dc + 1) * (m_figs.m_d + 2); @@ -1471,6 +1573,7 @@ void upd7220_device::process_fifo() break; case COMMAND_DMAW: /* DMA write request */ + LOGCMD4("DMAW CR=%02x DC=%d D=%d\n", m_cr, m_figs.m_dc, m_figs.m_d); m_dma_type = (m_cr >> 3) & 3; m_dma_mod = m_cr & 3; m_dma_transfer_length = (m_figs.m_dc + 1) * (m_figs.m_d + 1); @@ -1557,27 +1660,27 @@ uint8_t upd7220_device::dack_r() uint8_t result = 0; switch(m_dma_type) { - case 0: - if (m_dma_transfer_length % 2 == 0) - { - m_dma_data = read_vram(); - result = m_dma_data & 0xff; - } - else - { - result = (m_dma_data >> 8) & 0xff; - } - break; - case 2: + case 0: + if (m_dma_transfer_length % 2 == 0) + { m_dma_data = read_vram(); result = m_dma_data & 0xff; - break; - case 3: - m_dma_data = read_vram(); + } + else + { result = (m_dma_data >> 8) & 0xff; - break; - default: - logerror("uPD7220 Invalid DMA Transfer Type\n"); + } + break; + case 2: + m_dma_data = read_vram(); + result = m_dma_data & 0xff; + break; + case 3: + m_dma_data = read_vram(); + result = (m_dma_data >> 8) & 0xff; + break; + default: + logerror("uPD7220 Invalid DMA Transfer Type\n"); } if (--m_dma_transfer_length == 0) { @@ -1595,33 +1698,33 @@ void upd7220_device::dack_w(uint8_t data) { switch(m_dma_type) { - case 0: - if (m_dma_transfer_length % 2) - { - m_dma_data = ((m_dma_data & 0xff) | data << 8) & m_mask; - write_vram(m_dma_type, m_dma_mod, m_dma_data); - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); - m_ead &= 0x3ffff; - } - else - { - m_dma_data = (m_dma_data & 0xff00) | data; - } - break; - case 2: - m_dma_data = data & (m_mask & 0xff); - write_vram(m_dma_type, m_dma_mod, m_dma_data); - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); - m_ead &= 0x3ffff; - break; - case 3: - m_dma_data = (data << 8) & (m_mask & 0xff00); + case 0: + if (m_dma_transfer_length % 2) + { + m_dma_data = ((m_dma_data & 0xff) | data << 8) & m_mask; write_vram(m_dma_type, m_dma_mod, m_dma_data); - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * get_pitch()); m_ead &= 0x3ffff; - break; - default: - logerror("uPD7220 Invalid DMA Transfer Type\n"); + } + else + { + m_dma_data = (m_dma_data & 0xff00) | data; + } + break; + case 2: + m_dma_data = data & (m_mask & 0xff); + write_vram(m_dma_type, m_dma_mod, m_dma_data); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * get_pitch()); + m_ead &= 0x3ffff; + break; + case 3: + m_dma_data = (data << 8) & (m_mask & 0xff00); + write_vram(m_dma_type, m_dma_mod, m_dma_data); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * get_pitch()); + m_ead &= 0x3ffff; + break; + default: + logerror("uPD7220 Invalid DMA Transfer Type\n"); } if (--m_dma_transfer_length == 0) { @@ -1707,7 +1810,7 @@ void upd7220_device::update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect for (y = sy; y < sy + len; y++) { uint32_t const addr = sad + (y * m_pitch); - m_draw_text_cb(bitmap, addr, (y * m_lr) + m_vbp, wd, m_pitch, m_lr, m_dc, m_ead); + m_draw_text_cb(bitmap, addr, (y * m_lr) + m_vbp, wd, m_pitch, m_lr, m_dc, m_ead, m_ctop, m_cbot); } sy = y + 1; @@ -1719,6 +1822,7 @@ void upd7220_device::update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect // draw_graphics_line - //------------------------------------------------- +// TODO: merge with update_graphics void upd7220_device::draw_graphics_line(bitmap_rgb32 &bitmap, uint32_t addr, int y, int wd, int mixed) { int al = bitmap.cliprect().height(); @@ -1727,7 +1831,7 @@ void upd7220_device::draw_graphics_line(bitmap_rgb32 &bitmap, uint32_t addr, int for (int sx = 0; sx < aw; sx++) { - if((sx << 4) < m_aw * 16 && y < al) + if(sx < m_aw && y < al) m_display_cb(bitmap, y, sx << 4, addr + (wd + 1) * (sx % pitch)); } } @@ -1744,30 +1848,39 @@ void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &clip int im, wd; int y = 0, tsy = 0, bsy = 0; int mixed = ((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_MIXED) ? 1 : 0; - uint8_t interlace = ((m_mode & UPD7220_MODE_INTERLACE_MASK) == UPD7220_MODE_INTERLACE_ON) ? 0 : 1; + uint8_t interlace = ((m_mode & UPD7220_MODE_INTERLACE_MASK) == UPD7220_MODE_INTERLACE_ON) ? 1 : 0; uint8_t zoom = m_disp + 1; + LOGAREA("FRAME=%d MODE=%02x FORCE BITMAP=%d ZOOM=%02x PITCH=%d\n", screen().frame_number(), m_mode, force_bitmap, zoom, m_pitch); + for(int area = 0; area < 4; area++) { get_graphics_partition(area, &sad, &len, &im, &wd); + LOGAREA("%s: AREA=%d BSY=%4d SAD=%06x len=%04x im=%d wd=%d\n", this->tag(), area, bsy, sad, len, im, wd); + + // pc9821:aitd (256 color mode) and pc9821:os2warp3 (16, installation screens) wants this shift + const u8 pitch_shift = force_bitmap ? im : mixed; + if(im || force_bitmap) { // according to documentation only areas 0-1-2 can be drawn in bitmap mode - // PC98 Quarth definitely needs area 2 for player section. + // - pc98:quarth definitely needs area 2 for player section. + // - pc98:steamhea wants area 3 for scrolling and dialogue screens to work together, + // contradicting the doc. Fixed in 7220A or applies just for mixed mode? // TODO: what happens if combined area size is smaller than display height? // documentation suggests that it should repeat from area 0, needs real HW verification (no known SW do it). - if(area >= 3) + if (area >= 3 && !force_bitmap) break; - // PC98 madoum1-3 sets up ALL areas to a length of 0 after initial intro screen. + // pc98:madoum1-3 sets up ALL areas to a length of 0 after initial intro screen. // madoum1: area 0 sad==0 on gameplay (PC=0x955e7), sad==0xaa0 on second intro screen (tower) then intentionally scrolls up and back to initial position. // Suggests that length should be treated as max size if this occurs, this is also proven to be correct via real HW verification. // TODO: check if text partition do the same. if (len == 0) len = 0x400; - if(!interlace) + if (interlace) len <<= 1; for(y = 0; y < len; y++) @@ -1776,12 +1889,14 @@ void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &clip // pc98 quarth doesn't seem to use pitch here and it definitely wants bsy to be /2 to make scrolling to work. // pc98 xevious wants the pitch to be fixed at 80, and wants bsy to be /1 // pc98 dbuster contradicts with Xevious with regards of the pitch tho ... - uint32_t const addr = (sad & 0x3ffff) + ((y / (mixed ? 1 : m_lr)) * (m_pitch >> mixed)); + uint32_t const addr = (sad & 0x3ffff) + ((y / (mixed ? 1 : m_lr)) * (m_pitch >> pitch_shift)); for(int z = 0; z <= m_disp; ++z) { int yval = (y*zoom)+z + (bsy + m_vbp); - if(yval <= cliprect.bottom()) - draw_graphics_line(bitmap, addr, yval, wd, mixed); + // pc9801:duel sets up bitmap layer with height 384 vs. 400 of text layer + // so we scissor here, interlace wants it bumped x2 (microbx2) + if(yval >= cliprect.top() && yval <= cliprect.bottom() && (yval - m_vbp) < m_al << interlace) + draw_graphics_line(bitmap, addr, yval, wd, pitch_shift); } } } @@ -1793,7 +1908,7 @@ void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &clip { uint32_t const addr = (sad & 0x3ffff) + ((y / m_lr) * m_pitch); int yval = y * zoom + (tsy + m_vbp); - m_draw_text_cb(bitmap, addr, yval, wd, m_pitch, m_lr, m_dc, m_ead); + m_draw_text_cb(bitmap, addr, yval, wd, m_pitch, m_lr, m_dc, m_ead, m_ctop, m_cbot); } } } @@ -1828,7 +1943,7 @@ uint32_t upd7220_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm break; case UPD7220_MODE_DISPLAY_INVALID: - LOG("uPD7220 Invalid Display Mode!\n"); + popmessage("%s Invalid Display Mode!", this->tag()); } } return 0; |