From 397ec2cb40efd19e71f6133505d0c6c8b6e6cd0c Mon Sep 17 00:00:00 2001 From: angelosa Date: Tue, 5 Nov 2024 18:24:20 +0100 Subject: video/upd7220.cpp: implement experimental partition fetch fn nec/pc9821.cpp: add 31 kHz monitor setting --- src/devices/video/upd7220.cpp | 24 +++++++++++++++++++++--- src/devices/video/upd7220.h | 3 +++ src/mame/nec/pc9821.cpp | 42 +++++++++++++++++++++--------------------- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/devices/video/upd7220.cpp b/src/devices/video/upd7220.cpp index f823196d9f2..56ae1acff10 100644 --- a/src/devices/video/upd7220.cpp +++ b/src/devices/video/upd7220.cpp @@ -392,6 +392,11 @@ 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() { // microbx2 wants horizontal multiplier of x16 @@ -613,6 +618,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 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); +} //************************************************************************** @@ -1838,12 +1856,12 @@ void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &clip { // according to documentation only areas 0-1-2 can be drawn in bitmap mode // - 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? + // - 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 && !force_bitmap) - break; + break; // 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. diff --git a/src/devices/video/upd7220.h b/src/devices/video/upd7220.h index 1df278e5729..41d901bc07f 100644 --- a/src/devices/video/upd7220.h +++ b/src/devices/video/upd7220.h @@ -87,6 +87,8 @@ public: void ext_sync_w(int state); void lpen_w(int state); + std::tuple get_area_partition_props(int line); + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); protected: @@ -100,6 +102,7 @@ protected: virtual space_config_vector memory_space_config() const override; virtual int translate_command(uint8_t data); + virtual void device_clock_changed() override; TIMER_CALLBACK_MEMBER(hsync_update); TIMER_CALLBACK_MEMBER(vsync_update); diff --git a/src/mame/nec/pc9821.cpp b/src/mame/nec/pc9821.cpp index 5b70ff30793..dcf07de2ffd 100644 --- a/src/mame/nec/pc9821.cpp +++ b/src/mame/nec/pc9821.cpp @@ -51,32 +51,35 @@ uint32_t pc9821_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap if(m_video_ff[DISPLAY_REG] != 0) { - // TODO: following is wrong: definitely requires GDC latches - // flashb (pitch=512) and skinpan (two areas on title screen) - // aitd sets pitch=40, which means something else inside 7220 should do the bump. - - // PEGC 256 mode is linear VRAM picked from a specific VRAM buffer. - // It doesn't latch values from GDC, it runs on its own renderer instead. - // Is the DAC really merging two pixels not unlike VGA correlated Mode 13h? - // https://github.com/joncampbell123/dosbox-x/issues/1289#issuecomment-543025016 - // TODO: getter cliprect from bitmap GDC if (m_ex_video_ff[ANALOG_256_MODE]) { rgb_t const *const palette = m_palette->palette()->entry_list_raw(); u8 *ext_gvram = (u8 *)m_ext_gvram.target(); int base_y = cliprect.min_y; + u32 base_address; + u16 pitch; + u8 im; for (int y = cliprect.min_y; y <= cliprect.max_y; y++) { + const int rel_y = y - base_y; + + std::tie(base_address, pitch, im) = m_hgdc[1]->get_area_partition_props(rel_y); + // aitd sets PITCH=40 (320), guess: assume im == 0 doing the trick + const u8 pitch_shift = im ^ 1; + for (int x = cliprect.min_x; x <= cliprect.max_x; x += 8) { - u32 address = (y - base_y) * (640 / 8) + (x >> 3); + // Mask is confirmed by flashb: + // does double buffering at SAD $38fc and $fffc, except when + // it goes single on title, drawing on current bank displayed. + u32 address = (((base_address << 1) + (rel_y) * (pitch << pitch_shift) + (x >> 3)) & 0xffff) << 3; for(int xi = 0; xi < 8; xi ++) { int res_x = x + xi; int res_y = y; - u16 pen = ext_gvram[(address << 3) + xi + (m_vram_disp * 0x40000)]; + u16 pen = ext_gvram[(address + xi) + (m_vram_disp * 0x40000)]; bitmap.pix(res_y, res_x) = palette[(pen & 0xff) + 0x20]; } @@ -307,20 +310,17 @@ void pc9821_state::pc9821_mode_ff_w(u8 data) { const u8 mode_ff = data & 0xfe; const u8 setting = BIT(data, 0); - // Monitor setting + // 24/31 kHz Monitor setting // BA / BX / PC-H98 / PC-9821 / 98NOTE uses this f/f in place of 15/24 kHz switch // TODO: better compose + // TODO: both frequencies needs to be verified + // 31 kHz from standard VGA clock (flashb) if (mode_ff == 0x20) { - if (!setting) - { - const XTAL screen_clock = XTAL(21'052'600) / 8; + const XTAL screen_clock = (setting ? XTAL(25'175'000) : XTAL(21'052'600)) / 8; - m_hgdc[0]->set_unscaled_clock(screen_clock); - m_hgdc[1]->set_unscaled_clock(screen_clock); - } - else - popmessage("pc9821_mode_ff_w: 31 kHz mode selected"); + m_hgdc[0]->set_unscaled_clock(screen_clock); + m_hgdc[1]->set_unscaled_clock(screen_clock); } } @@ -338,7 +338,7 @@ void pc9821_state::pegc_mmio_map(address_map &map) map(0x100, 0x100).lw8( NAME([this] (u8 data) { m_pegc.packed_mode = bool(BIT(data, 0)); - logerror("$e0100 packed mode %02x\n", data); + logerror("$e0100 packed mode %02x\n", data); }) ); // map(0x102, 0x102) enable pegc linear VRAM at upper addresses -- cgit v1.2.3