diff options
author | R. Belmont <rb6502@users.noreply.github.com> | 2019-10-28 10:32:37 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-28 10:32:37 -0400 |
commit | 0c491e7bd7aee2c3d350d96d8689a8f39490263b (patch) | |
tree | 0bbc75a5d9c6ee485240cc1d87dd4cd8f7c21677 /src/devices/video | |
parent | 45e0de9785ad856975745d7c31c3ee778591ae42 (diff) | |
parent | c1459feacc7566a6a4d91ffb4426cdc4c16bb38f (diff) |
Merge pull request #5787 from cam900/megaplay_lcm
315_5313.cpp : Allow LCM scaling of horizontal resolution
Diffstat (limited to 'src/devices/video')
-rw-r--r-- | src/devices/video/315_5124.cpp | 13 | ||||
-rw-r--r-- | src/devices/video/315_5124.h | 3 | ||||
-rw-r--r-- | src/devices/video/315_5313.cpp | 98 | ||||
-rw-r--r-- | src/devices/video/315_5313.h | 4 |
4 files changed, 72 insertions, 46 deletions
diff --git a/src/devices/video/315_5124.cpp b/src/devices/video/315_5124.cpp index 837f1af5215..15a599cf3d3 100644 --- a/src/devices/video/315_5124.cpp +++ b/src/devices/video/315_5124.cpp @@ -204,6 +204,7 @@ sega315_5124_device::sega315_5124_device(const machine_config &mconfig, device_t , device_memory_interface(mconfig, *this) , device_video_interface(mconfig, *this) , device_mixer_interface(mconfig, *this, 2) + , m_hcounter_divide(1) , m_cram_size(cram_size) , m_line_timing(line_timing) , m_palette_offset(palette_offset) @@ -361,7 +362,7 @@ u8 sega315_5124_device::vcount_read() const int active_scr_start = m_frame_timing[VERTICAL_SYNC] + m_frame_timing[TOP_BLANKING] + m_frame_timing[TOP_BORDER]; int vpos = screen().vpos(); - if (screen().hpos() < m_line_timing[VCOUNT_CHANGE_HPOS]) + if (screen_hpos() < m_line_timing[VCOUNT_CHANGE_HPOS]) { vpos--; if (vpos < 0) @@ -382,7 +383,7 @@ u8 sega315_5124_device::hcount_read() void sega315_5124_device::hcount_latch() { /* The hcount value returned by the VDP seems to be based on the previous hpos */ - int hclock = screen().hpos() - 1; + int hclock = screen_hpos() - 1; if (hclock < 0) hclock += WIDTH; @@ -677,7 +678,7 @@ void sega315_5124_device::check_pending_flags() return some position in the beginning of next line. To ensure the instruction will get updated status, here a maximum hpos is set if the timer reports no remaining time, what could also occur due to the ahead time of the timeslice. */ - int const hpos = (m_pending_flags_timer->remaining() == attotime::zero) ? (WIDTH - 1) : screen().hpos(); + int const hpos = (m_pending_flags_timer->remaining() == attotime::zero) ? (WIDTH - 1) : screen_hpos(); if ((m_pending_hint) && hpos >= m_line_timing[HINT_HPOS]) { @@ -853,11 +854,11 @@ void sega315_5124_device::control_write(u8 data) break; case 1: set_display_settings(); - if (screen().hpos() <= DISPLAY_DISABLED_HPOS) + if (screen_hpos() <= DISPLAY_DISABLED_HPOS) m_display_disabled = !BIT(m_reg[0x01], 6); break; case 8: - if (screen().hpos() <= m_line_timing[XSCROLL_HPOS]) + if (screen_hpos() <= m_line_timing[XSCROLL_HPOS]) m_reg8copy = m_reg[0x08]; } @@ -1303,7 +1304,7 @@ void sega315_5313_mode4_device::sprite_collision(int line, int sprite_col_x) // This function is been used to check for sprite collision of // the 315-5313 VDP, that occurs before the active screen is // drawn, so it must not flag a collision again when drawing. - if (screen().hpos() < m_draw_time) + if (screen_hpos() < m_draw_time) { m_pending_status |= STATUS_SPRCOL; m_pending_sprcol_x = m_line_timing[SPRCOL_BASEHPOS]; diff --git a/src/devices/video/315_5124.h b/src/devices/video/315_5124.h index f5bb3cc02f5..1836660da9b 100644 --- a/src/devices/video/315_5124.h +++ b/src/devices/video/315_5124.h @@ -55,6 +55,7 @@ public: // construction/destruction sega315_5124_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + void set_hcounter_divide(unsigned divide) { m_hcounter_divide = divide; } void set_is_pal(bool is_pal) { m_is_pal = is_pal; } auto vblank() { return m_vblank_cb.bind(); } @@ -102,6 +103,7 @@ protected: void sega315_5124(address_map &map); + virtual int screen_hpos() { return screen().hpos() / ((m_hcounter_divide == 0) ? 1 : m_hcounter_divide); } void set_display_settings(); void set_frame_timing(); virtual void vblank_end(int vpos); @@ -130,6 +132,7 @@ protected: void draw_scanline_mode0(int *line_buffer, int line); void check_pending_flags(); + unsigned m_hcounter_divide; u8 m_reg[16]; /* All the registers */ u8 m_status; /* Status register */ u8 m_pending_status; /* Pending status flags */ diff --git a/src/devices/video/315_5313.cpp b/src/devices/video/315_5313.cpp index 891e9ad0328..77bd8a9094a 100644 --- a/src/devices/video/315_5313.cpp +++ b/src/devices/video/315_5313.cpp @@ -153,6 +153,12 @@ static constexpr u8 line_315_5313_mode4[8] = { , 37 /* SPRCOL_BASEHPOS */ }; +static const unsigned hres[4] = { 256, 256, 320, 320 }; +static const unsigned hres_mul[4] = { 5, 5, 4, 4 }; + +inline u8 sega315_5313_device::get_hres() { return (MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1)) & 3; } +int sega315_5313_device::screen_hpos() { return screen().hpos() / (m_lcm_scaling ? hres_mul[get_hres()] : 1); } + #define MAX_HPOSITION 480 @@ -187,6 +193,7 @@ sega315_5313_device::sega315_5313_device(const machine_config &mconfig, const ch , m_scanline_counter(0) , m_vblank_flag(0) , m_imode(0) + , m_lcm_scaling(false) , m_visible_scanlines(0) , m_irq6_scanline(0) , m_z80irq_scanline(0) @@ -337,9 +344,9 @@ void sega315_5313_device::device_start() memset(m_palette_lookup.get(), 0x00, 0x40 * 2); if (!m_use_alt_timing) - m_render_bitmap = std::make_unique<bitmap_rgb32>(320, 512); // allocate maximum sizes we're going to use, it's safer. + m_render_bitmap = std::make_unique<bitmap_rgb32>(1280, 512); // allocate maximum sizes we're going to use, it's safer. else - m_render_line = std::make_unique<u32[]>(320); + m_render_line = std::make_unique<u32[]>(1280); m_render_line_raw = std::make_unique<u16[]>(320); @@ -351,7 +358,7 @@ void sega315_5313_device::device_start() save_pointer(NAME(m_palette_lookup), 0x40); save_pointer(NAME(m_render_line_raw), 320); if (m_use_alt_timing) - save_pointer(NAME(m_render_line), 320); + save_pointer(NAME(m_render_line), 1280); m_irq6_on_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sega315_5313_device::irq6_on_timer_callback), this)); m_irq4_on_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sega315_5313_device::irq4_on_timer_callback), this)); @@ -1237,7 +1244,7 @@ u16 sega315_5313_device::get_hposition() } else { - value4 = screen().hpos(); + value4 = screen_hpos(); } return value4; @@ -1381,7 +1388,7 @@ void sega315_5313_device::render_spriteline_to_spritebuffer(int scanline) int maxpixels = 0; u16 base_address = 0; - const int screenwidth = MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1); + const int screenwidth = get_hres(); switch (screenwidth & 3) { @@ -1657,14 +1664,15 @@ void sega315_5313_device::render_videoline_to_videobuffer(int scanline) int non_window_lastcol; const int screenheight = MEGADRIVE_REG01_240_LINE ? 240 : 224; struct nametable_t tile; + unsigned horz = m_lcm_scaling ? hres[get_hres()] : 320; /* Clear our Render Buffer */ - for (int x = 0; x < 320; x++) + for (int x = 0; x < horz; x++) { m_video_renderline[x] = MEGADRIVE_REG07_BGCOLOUR | 0x20000; // mark as BG } - memset(m_highpri_renderline.get(), 0, 320); + memset(m_highpri_renderline.get(), 0, horz); /* is this line enabled? */ if (!MEGADRIVE_REG01_DISP_ENABLE) @@ -1687,7 +1695,7 @@ void sega315_5313_device::render_videoline_to_videobuffer(int scanline) const u16 window_down = MEGADRIVE_REG12_WINDOW_DOWN; // const u16 window_vpos = MEGADRIVE_REG12_WINDOW_VPOS; - const int screenwidth = MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1); + const int screenwidth = get_hres(); switch (screenwidth) { @@ -1980,7 +1988,7 @@ void sega315_5313_device::render_videoline_to_videobuffer(int scanline) /* MEGADRIVE_REG0C_SHADOW_HIGLIGHT */ /* Low Priority Sprites */ - for (int x = 0; x < 320; x++) + for (int x = 0; x < horz; x++) { if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT) { @@ -2023,7 +2031,7 @@ void sega315_5313_device::render_videoline_to_videobuffer(int scanline) } /* High Priority A+B Tiles */ - for (int x = 0; x < 320; x++) + for (int x = 0; x < horz; x++) { if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT) { @@ -2049,7 +2057,7 @@ void sega315_5313_device::render_videoline_to_videobuffer(int scanline) } /* High Priority Sprites */ - for (int x = 0; x < 320; x++) + for (int x = 0; x < horz; x++) { if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT) { @@ -2092,6 +2100,8 @@ void sega315_5313_device::render_videobuffer_to_screenbuffer(int scanline) { const unsigned palette_per_scanline = scanline * 64; u32 *lineptr; + unsigned horz = m_lcm_scaling ? hres[get_hres()] : 320; + unsigned mul = m_lcm_scaling ? hres_mul[get_hres()] : 1; if (!m_use_alt_timing) { @@ -2117,27 +2127,27 @@ void sega315_5313_device::render_videobuffer_to_screenbuffer(int scanline) } } - for (int x = 0; x < 320; x++) + for (int srcx = 0, xx = 0, dstx = 0; srcx < horz; dstx++) { - const u32 dat = m_video_renderline[x]; + const u32 dat = m_video_renderline[srcx]; const u16 clut = (dat & 0x3f) + palette_per_scanline; if (!(dat & 0x20000)) - m_render_line_raw[x] = 0x100; + m_render_line_raw[srcx] = 0x100; else - m_render_line_raw[x] = 0x000; + m_render_line_raw[srcx] = 0x000; if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT) { if (dat & 0x10000) { - lineptr[x] = m_gfx_palette->pen(clut); - m_render_line_raw[x] |= (dat & 0x3f) | 0x080; + lineptr[dstx] = m_gfx_palette->pen(clut); + m_render_line_raw[srcx] |= (dat & 0x3f) | 0x080; } else { - lineptr[x] = m_gfx_palette->pen(clut); - m_render_line_raw[x] |= (dat & 0x3f) | 0x040; + lineptr[dstx] = m_gfx_palette->pen(clut); + m_render_line_raw[srcx] |= (dat & 0x3f) | 0x040; } } else @@ -2151,26 +2161,26 @@ void sega315_5313_device::render_videobuffer_to_screenbuffer(int scanline) case 0x10000: // (sprite) low priority, no shadow sprite, no highlight = shadow case 0x12000: // (sprite) low priority, shadow sprite, no highlight = shadow case 0x16000: // (sprite) normal pri, shadow sprite, no highlight = shadow? - lineptr[x] = m_gfx_palette_shadow->pen(clut); - m_render_line_raw[x] |= (dat & 0x3f) | 0x000; + lineptr[dstx] = m_gfx_palette_shadow->pen(clut); + m_render_line_raw[srcx] |= (dat & 0x3f) | 0x000; break; case 0x4000: // normal pri, no shadow sprite, no highlight = normal; case 0x8000: // low pri, highlight sprite = normal; - lineptr[x] = m_gfx_palette->pen(clut); - m_render_line_raw[x] |= (dat & 0x3f) | 0x040; + lineptr[dstx] = m_gfx_palette->pen(clut); + m_render_line_raw[srcx] |= (dat & 0x3f) | 0x040; break; case 0x14000: // (sprite) normal pri, no shadow sprite, no highlight = normal; case 0x18000: // (sprite) low pri, highlight sprite = normal; - lineptr[x] = m_gfx_palette->pen(clut); - m_render_line_raw[x] |= (dat & 0x3f) | 0x080; + lineptr[dstx] = m_gfx_palette->pen(clut); + m_render_line_raw[srcx] |= (dat & 0x3f) | 0x080; break; case 0x0c000: // normal pri, highlight set = highlight? case 0x1c000: // (sprite) normal pri, highlight set = highlight? - lineptr[x] = m_gfx_palette_hilight->pen(clut); - m_render_line_raw[x] |= (dat & 0x3f) | 0x0c0; + lineptr[dstx] = m_gfx_palette_hilight->pen(clut); + m_render_line_raw[srcx] |= (dat & 0x3f) | 0x0c0; break; case 0x0a000: // shadow set, highlight set - not possible @@ -2178,18 +2188,30 @@ void sega315_5313_device::render_videobuffer_to_screenbuffer(int scanline) case 0x1a000: // (sprite)shadow set, highlight set - not possible case 0x1e000: // (sprite)shadow set, highlight set, normal set, not possible default: - lineptr[x] = m_render_line_raw[x] |= (machine().rand() & 0x3f); + lineptr[dstx] = m_render_line_raw[srcx] |= (machine().rand() & 0x3f); break; } } + if (++xx >= mul) + { + srcx++; + xx = 0; + } } if (!m_32x_scanline_helper_func.isnull()) m_32x_scanline_helper_func(scanline); if (!m_32x_scanline_func.isnull()) { - for (int x = 0; x < 320; x++) - m_32x_scanline_func(x, m_video_renderline[x] & 0x20000, lineptr[x]); + for (int srcx = 0, xx = 0, dstx = 0; srcx < horz; dstx++) + { + m_32x_scanline_func(srcx, m_video_renderline[srcx] & 0x20000, lineptr[dstx]); + if (++xx >= mul) + { + srcx++; + xx = 0; + } + } } } @@ -2283,6 +2305,7 @@ void sega315_5313_device::vdp_handle_eof() { rectangle visarea; int scr_width = 320; + int scr_mul = 1; m_vblank_flag = 0; //m_irq6_pending = 0; /* NO! (breaks warlock) */ @@ -2318,19 +2341,14 @@ void sega315_5313_device::vdp_handle_eof() m_z80irq_scanline <<= 1; } - switch (MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1)) - { - /* note, add 240 mode + init new timings! */ - case 0: scr_width = 256; break; - case 1: scr_width = 256; break; - case 2: scr_width = 320; break; - case 3: scr_width = 320; break; - } + /* note, add 240 mode + init new timings! */ + scr_mul = m_lcm_scaling ? hres_mul[get_hres()] : 1; + scr_width = hres[get_hres()] * scr_mul; // osd_printf_debug("my mode %02x", m_regs[0x0c]); visarea.set(0, scr_width - 1, 0, m_visible_scanlines - 1); - screen().configure(480, m_total_scanlines, visarea, screen().frame_period().attoseconds()); + screen().configure(480 * scr_mul, m_total_scanlines, visarea, screen().frame_period().attoseconds()); } @@ -2356,7 +2374,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(sega315_5313_device::megadriv_scanline_timer_callba { if (param == 0) { - //printf("where are we? %d %d\n", screen().vpos(), screen().hpos()); + //printf("where are we? %d %d\n", screen().vpos(), screen_hpos()); vdp_handle_eof(); //vdp_clear_bitmap(); } diff --git a/src/devices/video/315_5313.h b/src/devices/video/315_5313.h index 72fcd51a6ed..565f5d06f09 100644 --- a/src/devices/video/315_5313.h +++ b/src/devices/video/315_5313.h @@ -32,6 +32,7 @@ public: auto lv6_irq() { return m_lv6irqline_callback.bind(); } auto lv4_irq() { return m_lv4irqline_callback.bind(); } + void set_lcm_scaling(bool lcm_scaling) { m_lcm_scaling = lcm_scaling; } void set_alt_timing(int use_alt_timing) { m_use_alt_timing = use_alt_timing; } void set_pal_write_base(int palwrite_base) { m_palwrite_base = palwrite_base; } template <typename T> void set_ext_palette(T &&tag) { m_ext_palette.set_tag(std::forward<T>(tag)); } @@ -116,6 +117,7 @@ protected: md_32x_interrupt_delegate m_32x_interrupt_func; md_32x_scanline_helper_delegate m_32x_scanline_helper_func; + virtual int screen_hpos() override; private: // vdp code defines const u8 CODE_DMA() { return m_vdp_code & 0x20; } @@ -142,6 +144,7 @@ private: void get_nametable(gfx_element *tile_gfx, u16 tile_base, nametable_t &tile, int vcolumn); inline void draw_tile(nametable_t tile, int start, int end, int &dpos, bool is_fg); + inline u8 get_hres(); int m_command_pending; // 2nd half of command pending.. u16 m_command_part1; u16 m_command_part2; @@ -159,6 +162,7 @@ private: int m_imode; + bool m_lcm_scaling; int m_visible_scanlines; int m_irq6_scanline; int m_z80irq_scanline; |