315_5313.cpp DMA / Timer Updates, Correct refresh rate and timer rate related to systems when using mega drive VDP (#5470)

* Correct timer rate related to screen refresh rate for 315_5313.cpp, megacd.cpp, mega32x.cpp
315_5313.cpp : Simplify DMA behavior, Add notes, Simplify handlers, Fix spacing, Reduce unnecessary lines, Use shorter / correct type values, Fix debugger issue
megadriv.cpp, segac2.cpp, calcune.cpp : Correct screen refresh rate, Add notes (source : https://segaretro.org/Sega_Mega_Drive/Technical_specifications)
megadriv.cpp : Allow Z80 VDP reading, Correct VDP sound output
calcune.cpp : Fix naming, Add notes

* 315_5313.cpp : Reduce unnecessary lines, Fix spacings

* 315_5313.cpp : Use struct for nametable, Reduce duplicates, Fix spacing, Reduce unnecessary lines

* 315_5313.cpp : Fix spacing

* 315_5313.cpp : Fix spacing, Reduce duplicates, Unnecessary lines, Fix type values
This commit is contained in:
cam900 2019-08-14 02:20:07 +09:00 committed by R. Belmont
parent 98e518f1b6
commit d1acfba2c7
11 changed files with 878 additions and 1394 deletions

File diff suppressed because it is too large Load Diff

View File

@ -15,15 +15,15 @@ class sega315_5313_device : public sega315_5313_mode4_device
{
public:
template <typename T>
sega315_5313_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag)
sega315_5313_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&cpu_tag)
: sega315_5313_device(mconfig, tag, owner, clock)
{
m_cpu68k.set_tag(std::forward<T>(cpu_tag));
}
sega315_5313_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
sega315_5313_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
typedef device_delegate<void (int x, uint32_t priority, uint32_t &lineptr)> md_32x_scanline_delegate;
typedef device_delegate<void (int x, u32 priority, u32 &lineptr)> md_32x_scanline_delegate;
typedef device_delegate<void (int scanline, int irq6)> md_32x_interrupt_delegate;
typedef device_delegate<void (int scanline)> md_32x_scanline_helper_delegate;
@ -44,8 +44,8 @@ public:
int m_palwrite_base; // if we want to write to the actual MAME palette..
DECLARE_READ16_MEMBER( vdp_r );
DECLARE_WRITE16_MEMBER( vdp_w );
u16 vdp_r(offs_t offset, u16 mem_mask = ~0);
void vdp_w(offs_t offset, u16 data, u16 mem_mask = ~0);
int get_scanline_counter();
@ -65,10 +65,9 @@ public:
void set_vdp_pal(bool pal) { m_vdp_pal = pal ? 1 : 0; }
void set_use_cram(int cram) { m_use_cram = cram; }
void set_dma_delay(int delay) { m_dma_delay = delay; }
int get_framerate() { return m_framerate; }
double get_framerate() { return has_screen() ? screen().frame_period().as_hz() : double(m_framerate); }
int get_imode() { return m_imode; }
void vdp_clear_bitmap()
{
if (m_render_bitmap)
@ -76,14 +75,14 @@ public:
}
std::unique_ptr<bitmap_rgb32> m_render_bitmap;
std::unique_ptr<uint32_t[]> m_render_line;
std::unique_ptr<uint16_t[]> m_render_line_raw;
std::unique_ptr<u32[]> m_render_line;
std::unique_ptr<u16[]> m_render_line_raw;
TIMER_DEVICE_CALLBACK_MEMBER( megadriv_scanline_timer_callback_alt_timing );
TIMER_DEVICE_CALLBACK_MEMBER( megadriv_scanline_timer_callback );
TIMER_DEVICE_CALLBACK_MEMBER(megadriv_scanline_timer_callback_alt_timing);
TIMER_DEVICE_CALLBACK_MEMBER(megadriv_scanline_timer_callback);
timer_device* m_megadriv_scanline_timer;
inline uint16_t vdp_get_word_from_68k_mem(uint32_t source);
inline u16 vdp_get_word_from_68k_mem(u32 source);
protected:
virtual void device_start() override;
@ -100,13 +99,37 @@ protected:
md_32x_scanline_helper_delegate m_32x_scanline_helper_func;
private:
// vdp code defines
const u8 CODE_DMA() { return m_vdp_code & 0x20; }
const u8 CODE_VRAM_COPY() { return m_vdp_code & 0x10; }
const u8 CODE_VRAM_READ() { return (m_vdp_code & 0x0f) == 0x00; }
const u8 CODE_VRAM_WRITE() { return (m_vdp_code & 0x0f) == 0x01; }
const u8 CODE_CRAM_WRITE() { return (m_vdp_code & 0x0f) == 0x03; }
const u8 CODE_VSRAM_READ() { return (m_vdp_code & 0x0f) == 0x04; }
const u8 CODE_VSRAM_WRITE() { return (m_vdp_code & 0x0f) == 0x05; }
const u8 CODE_CRAM_READ() { return (m_vdp_code & 0x0f) == 0x08; }
//const u8 CODE_VRAM_READ_BYTE() { return (m_vdp_code & 0x0f) == 0x0c; } // undocumented, unhandled
// nametable
struct nametable_t {
u16 addr;
bool xflip;
bool yflip;
u16 colour;
u16 pri;
};
void get_window_tilebase(int &tile_base, u16 base, int vcolumn, int window_hsize, int hcolumn);
void get_vcolumn_tilebase(int &vcolumn, int &tile_base, u16 base, int vscroll, int scanline, int vsize, int hsize, int hcolumn);
void get_nametable(u16 tile_base, nametable_t &tile, int vcolumn);
inline void draw_tile(nametable_t tile, int start, int end, int &dpos, bool is_fg);
int m_command_pending; // 2nd half of command pending..
uint16_t m_command_part1;
uint16_t m_command_part2;
uint8_t m_vdp_code;
uint16_t m_vdp_address;
uint8_t m_vram_fill_pending;
uint16_t m_vram_fill_length;
u16 m_command_part1;
u16 m_command_part2;
u8 m_vdp_code;
u16 m_vdp_address;
u8 m_vram_fill_pending;
u16 m_vram_fill_length;
int m_irq4counter;
int m_imode_odd_frame;
int m_sprite_collision;
@ -129,13 +152,13 @@ private:
int m_use_cram; // c2 uses it's own palette ram, so it sets this to 0
int m_dma_delay; // SVP and SegaCD have some 'lag' in DMA transfers
std::unique_ptr<uint16_t[]> m_regs;
std::unique_ptr<uint16_t[]> m_vram;
std::unique_ptr<uint16_t[]> m_cram;
std::unique_ptr<uint16_t[]> m_vsram;
std::unique_ptr<u16[]> m_regs;
std::unique_ptr<u16[]> m_vram;
std::unique_ptr<u16[]> m_cram;
std::unique_ptr<u16[]> m_vsram;
/* The VDP keeps a 0x400 byte on-chip cache of the Sprite Attribute Table
to speed up processing, Castlevania Bloodlines abuses this on the upside down level */
std::unique_ptr<uint16_t[]> m_internal_sprite_attribute_table;
std::unique_ptr<u16[]> m_internal_sprite_attribute_table;
// these are used internally by the VDP to schedule when after the start of a scanline
// to trigger the various interrupts / rendering to our bitmap, bit of a hack really
@ -143,29 +166,30 @@ private:
emu_timer* m_irq4_on_timer;
emu_timer* m_render_timer;
uint16_t vdp_vram_r(void);
uint16_t vdp_vsram_r(void);
uint16_t vdp_cram_r(void);
u16 vdp_vram_r(void);
u16 vdp_vsram_r(void);
u16 vdp_cram_r(void);
void insta_68k_to_cram_dma(uint32_t source,uint16_t length);
void insta_68k_to_vsram_dma(uint32_t source,uint16_t length);
void insta_68k_to_vram_dma(uint32_t source,int length);
void insta_vram_copy(uint32_t source, uint16_t length);
void insta_68k_to_cram_dma(u32 source, u16 length);
void insta_68k_to_vsram_dma(u32 source, u16 length);
void insta_68k_to_vram_dma(u32 source, int length);
void insta_vram_copy(u32 source, u16 length);
void vdp_vram_write(uint16_t data);
void vdp_cram_write(uint16_t data);
void vdp_vram_write(u16 data);
void vdp_cram_write(u16 data);
void write_cram_value(int offset, int data);
void vdp_vsram_write(uint16_t data);
void vdp_vsram_write(u16 data);
void vdp_set_register(int regnum, uint8_t value);
void vdp_address_inc();
void vdp_set_register(int regnum, u8 value);
void handle_dma_bits();
uint16_t get_hposition();
uint16_t megadriv_read_hv_counters();
u16 get_hposition();
u16 megadriv_read_hv_counters();
uint16_t ctrl_port_r();
uint16_t data_port_r();
u16 ctrl_port_r();
u16 data_port_r();
void data_port_w(int data);
void ctrl_port_w(int data);
void update_code_and_address(void);
@ -176,10 +200,10 @@ private:
void render_videobuffer_to_screenbuffer(int scanline);
/* variables used during emulation - not saved */
std::unique_ptr<uint8_t[]> m_sprite_renderline;
std::unique_ptr<uint8_t[]> m_highpri_renderline;
std::unique_ptr<uint32_t[]> m_video_renderline;
std::unique_ptr<uint16_t[]> m_palette_lookup;
std::unique_ptr<u8[]> m_sprite_renderline;
std::unique_ptr<u8[]> m_highpri_renderline;
std::unique_ptr<u32[]> m_video_renderline;
std::unique_ptr<u16[]> m_palette_lookup;
address_space *m_space68k;
required_device<m68000_base_device> m_cpu68k;

View File

@ -24,7 +24,7 @@
#include "emupal.h"
#include "speaker.h"
#define MASTER_CLOCK_NTSC 53693175
#define OSC1_CLOCK 53693175 // same as NTSC genesis / mega drive master clock
class calcune_state : public driver_device
{
@ -111,17 +111,17 @@ WRITE16_MEMBER(calcune_state::cal_770000_w)
READ16_MEMBER(calcune_state::cal_vdp_r)
{
if (!vdp_state)
return m_vdp->vdp_r(space, offset, mem_mask);
return m_vdp->vdp_r(offset, mem_mask);
else
return m_vdp2->vdp_r(space, offset, mem_mask);
return m_vdp2->vdp_r(offset, mem_mask);
}
WRITE16_MEMBER(calcune_state::cal_vdp_w)
{
if (!vdp_state)
m_vdp->vdp_w(space, offset, data, mem_mask);
m_vdp->vdp_w(offset, data, mem_mask);
else
m_vdp2->vdp_w(space, offset, data, mem_mask);
m_vdp2->vdp_w(offset, data, mem_mask);
}
void calcune_state::calcune_map(address_map &map)
@ -251,23 +251,24 @@ MACHINE_START_MEMBER(calcune_state,calcune)
void calcune_state::calcune(machine_config &config)
{
M68000(config, m_maincpu, MASTER_CLOCK_NTSC / 7); /* 7.67 MHz */
M68000(config, m_maincpu, OSC1_CLOCK / 7); /* 7.67 MHz */
m_maincpu->set_addrmap(AS_PROGRAM, &calcune_state::calcune_map);
m_maincpu->set_irq_acknowledge_callback(FUNC(calcune_state::genesis_int_callback));
Z80(config, "z80", MASTER_CLOCK_NTSC / 15).set_disable(); /* 3.58 MHz, no code is ever uploaded for the Z80, so it's unused here even if it is present on the PCB */
Z80(config, "z80", OSC1_CLOCK / 15).set_disable(); /* 3.58 MHz, no code is ever uploaded for the Z80, so it's unused here even if it is present on the PCB */
MCFG_MACHINE_START_OVERRIDE(calcune_state,calcune)
MCFG_MACHINE_RESET_OVERRIDE(calcune_state,calcune)
screen_device &screen(SCREEN(config, "megadriv", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_refresh_hz(double(OSC1_CLOCK) / 10.0 / 262.0 / 342.0); // same as SMS?
// screen.set_refresh_hz(double(OSC1_CLOCK) / 8.0 / 262.0 / 427.0); // or 427 Htotal?
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually.
screen.set_size(64*8, 620);
screen.set_visarea(0, 40*8-1, 0, 28*8-1);
screen.set_screen_update(FUNC(calcune_state::screen_update_calcune));
SEGA315_5313(config, m_vdp, MASTER_CLOCK_NTSC, m_maincpu);
SEGA315_5313(config, m_vdp, OSC1_CLOCK, m_maincpu);
m_vdp->set_is_pal(false);
m_vdp->snd_irq().set(FUNC(calcune_state::vdp_sndirqline_callback_genesis_z80));
m_vdp->lv6_irq().set(FUNC(calcune_state::vdp_lv6irqline_callback_genesis_68k));
@ -278,7 +279,7 @@ void calcune_state::calcune(machine_config &config)
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.25);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.25);
SEGA315_5313(config, m_vdp2, MASTER_CLOCK_NTSC, m_maincpu);
SEGA315_5313(config, m_vdp2, OSC1_CLOCK, m_maincpu);
m_vdp2->set_is_pal(false);
// are these not hooked up or should they OR with the other lines?
// m_vdp2->snd_irq().set(FUNC(calcune_state::vdp_sndirqline_callback_genesis_z80));

View File

@ -609,18 +609,17 @@ void md_cons_state::genesis_32x(machine_config &config)
m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback), this);
m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback), this);
m_vdp->reset_routes();
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.25)/2);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.25)/2);
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2);
SEGA_32X_NTSC(config, m_32x, (MASTER_CLOCK_NTSC * 3) / 7, m_maincpu, m_scan_timer);
m_32x->set_screen("megadriv");
subdevice<screen_device>("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console));
// we need to remove and re-add the YM because the balance is different
// due to MAME / MESS having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!)
config.device_remove("ymsnd");
YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7);
m_ymsnd->reset_routes();
m_ymsnd->add_route(0, "lspeaker", (0.50)/2);
m_ymsnd->add_route(1, "rspeaker", (0.50)/2);
@ -643,18 +642,17 @@ void md_cons_state::mdj_32x(machine_config &config)
m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback), this);
m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback), this);
m_vdp->reset_routes();
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.25)/2);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.25)/2);
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2);
SEGA_32X_NTSC(config, m_32x, (MASTER_CLOCK_NTSC * 3) / 7, m_maincpu, m_scan_timer);
m_32x->set_screen("megadriv");
subdevice<screen_device>("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console));
// we need to remove and re-add the sound system because the balance is different
// due to MAME / MESS having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!)
config.device_remove("ymsnd");
YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7);
m_ymsnd->reset_routes();
m_ymsnd->add_route(0, "lspeaker", (0.50)/2);
m_ymsnd->add_route(1, "rspeaker", (0.50)/2);
@ -677,18 +675,17 @@ void md_cons_state::md_32x(machine_config &config)
m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback), this);
m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback), this);
m_vdp->reset_routes();
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.25)/2);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.25)/2);
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2);
SEGA_32X_PAL(config, m_32x, (MASTER_CLOCK_PAL * 3) / 7, m_maincpu, m_scan_timer);
m_32x->set_screen("megadriv");
subdevice<screen_device>("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console));
// we need to remove and re-add the sound system because the balance is different
// due to MAME / MESS having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!)
config.device_remove("ymsnd");
YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7);
m_ymsnd->reset_routes();
m_ymsnd->add_route(0, "lspeaker", (0.50)/2);
m_ymsnd->add_route(1, "rspeaker", (0.50)/2);
@ -744,6 +741,7 @@ void md_cons_state::genesis_scd(machine_config &config)
SEGA_SEGACD_US(config, m_segacd, 0);
m_segacd->set_palette("gen_vdp:palette");
m_segacd->set_hostcpu(m_maincpu);
m_segacd->set_screen("megadriv");
CDROM(config, "cdrom").set_interface("scd_cdrom");
@ -762,6 +760,7 @@ void md_cons_state::md_scd(machine_config &config)
SEGA_SEGACD_EUROPE(config, m_segacd, 0);
m_segacd->set_palette("gen_vdp:palette");
m_segacd->set_hostcpu(m_maincpu);
m_segacd->set_screen("megadriv");
CDROM(config, "cdrom").set_interface("scd_cdrom");
@ -780,6 +779,7 @@ void md_cons_state::mdj_scd(machine_config &config)
SEGA_SEGACD_JAPAN(config, m_segacd, 0);
m_segacd->set_palette("gen_vdp:palette");
m_segacd->set_hostcpu(m_maincpu);
m_segacd->set_screen("megadriv");
CDROM(config, "cdrom").set_interface("scd_cdrom");
@ -795,6 +795,7 @@ void md_cons_state::genesis_32x_scd(machine_config &config)
SEGA_SEGACD_US(config, m_segacd, 0);
m_segacd->set_palette("gen_vdp:palette");
m_segacd->set_hostcpu(m_maincpu);
m_segacd->set_screen("megadriv");
CDROM(config, "cdrom").set_interface("scd_cdrom");
@ -814,6 +815,7 @@ void md_cons_state::md_32x_scd(machine_config &config)
SEGA_SEGACD_EUROPE(config, m_segacd, 0);
m_segacd->set_palette("gen_vdp:palette");
m_segacd->set_hostcpu(m_maincpu);
m_segacd->set_screen("megadriv");
CDROM(config, "cdrom").set_interface("scd_cdrom");
@ -833,6 +835,7 @@ void md_cons_state::mdj_32x_scd(machine_config &config)
SEGA_SEGACD_JAPAN(config, m_segacd, 0);
m_segacd->set_palette("gen_vdp:palette");
m_segacd->set_hostcpu(m_maincpu);
m_segacd->set_screen("megadriv");
CDROM(config, "cdrom").set_interface("scd_cdrom");

View File

@ -1577,7 +1577,8 @@ void segac2_state::segac(machine_config &config)
TIMER(config, "scantimer").configure_scanline("gen_vdp", FUNC(sega315_5313_device::megadriv_scanline_timer_callback_alt_timing), "megadriv", 0, 1);
screen_device &screen(SCREEN(config, "megadriv", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_refresh_hz(double(XL2_CLOCK.value()) / 10.0 / 262.0 / 342.0); // same as SMS?
// screen.set_refresh_hz(double(XL2_CLOCK.value()) / 8.0 / 262.0 / 427.0); // or 427 Htotal?
screen.set_size(512, 262);
screen.set_visarea(0, 32*8-1, 0, 28*8-1);
screen.set_screen_update(FUNC(segac2_state::screen_update_segac2_new));

View File

@ -101,8 +101,8 @@ private:
DECLARE_WRITE_LINE_MEMBER(vdp_lv6irqline_callback_s18);
DECLARE_WRITE_LINE_MEMBER(vdp_lv4irqline_callback_s18);
DECLARE_READ16_MEMBER( genesis_vdp_r ) { return m_vdp->vdp_r(space, offset, mem_mask); }
DECLARE_WRITE16_MEMBER( genesis_vdp_w ) { m_vdp->vdp_w(space, offset, data, mem_mask); }
DECLARE_READ16_MEMBER( genesis_vdp_r ) { return m_vdp->vdp_r(offset, mem_mask); }
DECLARE_WRITE16_MEMBER( genesis_vdp_w ) { m_vdp->vdp_w(offset, data, mem_mask); }
DECLARE_WRITE16_MEMBER( tileram_w ) { m_segaic16vid->tileram_w(space, offset, data, mem_mask); }
DECLARE_WRITE16_MEMBER( textram_w ) { m_segaic16vid->textram_w(space, offset, data, mem_mask); }

View File

@ -225,6 +225,7 @@ DEFINE_DEVICE_TYPE(SEGA_32X_PAL, sega_32x_pal_device, "sega_32x_pal", "Sega 3
sega_32x_device::sega_32x_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_palette_interface(mconfig, *this)
, device_video_interface(mconfig, *this, false)
, m_sh2_shared(*this, "sh2_shared")
, m_main_cpu(*this, finder_base::DUMMY_TAG)
, m_master_cpu(*this, "32x_master_sh2")
@ -942,21 +943,25 @@ WRITE16_MEMBER( sega_32x_device::m68k_pwm_w )
uint16_t sega_32x_device::get_hposition(void)
{
attotime time_elapsed_since_megadriv_scanline_timer;
uint16_t value4;
time_elapsed_since_megadriv_scanline_timer = m_scan_timer->time_elapsed();
if (time_elapsed_since_megadriv_scanline_timer.attoseconds() < (ATTOSECONDS_PER_SECOND/m_framerate /m_total_scanlines))
if (get_framerate() > 0.0)
{
value4 = (uint16_t)(MAX_HPOSITION*((double)(time_elapsed_since_megadriv_scanline_timer.attoseconds()) / (double)(ATTOSECONDS_PER_SECOND/m_framerate /m_total_scanlines)));
}
else /* in some cases (probably due to rounding errors) we get some stupid results (the odd huge value where the time elapsed is much higher than the scanline time??!).. hopefully by clamping the result to the maximum we limit errors */
{
value4 = MAX_HPOSITION;
}
attotime time_elapsed_since_megadriv_scanline_timer;
uint16_t value4;
return value4;
time_elapsed_since_megadriv_scanline_timer = m_scan_timer->time_elapsed();
if (time_elapsed_since_megadriv_scanline_timer.attoseconds() < (ATTOSECONDS_PER_SECOND/get_framerate() /double(m_total_scanlines)))
{
value4 = (uint16_t)(MAX_HPOSITION*((double)(time_elapsed_since_megadriv_scanline_timer.attoseconds()) / (double)(ATTOSECONDS_PER_SECOND/get_framerate() /double(m_total_scanlines))));
}
else /* in some cases (probably due to rounding errors) we get some stupid results (the odd huge value where the time elapsed is much higher than the scanline time??!).. hopefully by clamping the result to the maximum we limit errors */
{
value4 = MAX_HPOSITION;
}
return value4;
}
return MAX_HPOSITION;
}
READ16_MEMBER( sega_32x_device::common_vdp_regs_r )

View File

@ -12,8 +12,9 @@
#include "machine/timer.h"
#include "sound/dac.h"
#include "emupal.h"
#include "screen.h"
class sega_32x_device : public device_t, public device_palette_interface
class sega_32x_device : public device_t, public device_palette_interface, public device_video_interface
{
public:
void pause_cpu();
@ -22,6 +23,7 @@ public:
void set_framerate(int rate) { m_framerate = rate; }
void set_32x_pal(bool pal) { m_32x_pal = pal ? 1 : 0; }
void set_total_scanlines(int total) { m_base_total_scanlines = total; } // this get set at start only
double get_framerate() { return has_screen() ? screen().frame_period().as_hz() : double(m_framerate); }
void screen_eof(bool mode3)
{

View File

@ -327,6 +327,7 @@ void sega_segacd_device::device_add_mconfig(machine_config &config)
sega_segacd_device::sega_segacd_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_gfx_interface(mconfig, *this, gfx_segacd)
, device_video_interface(mconfig, *this, false)
, m_scdcpu(*this, "segacd_68k")
, m_hostcpu(*this, finder_base::DUMMY_TAG)
, m_rfsnd(*this, "rfsnd")
@ -1843,7 +1844,7 @@ TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::dma_timer_callback )
// timed reset of flags
scd_mode_dmna_ret_flags |= 0x0021;
m_dma_timer->adjust(attotime::from_hz(m_framerate) / m_total_scanlines);
m_dma_timer->adjust(attotime::from_hz(get_framerate()) / double(m_total_scanlines));
}

View File

@ -10,8 +10,9 @@
#include "machine/lc89510.h"
#include "machine/megacdcd.h"
#include "sound/rf5c68.h"
#include "screen.h"
class sega_segacd_device : public device_t, public device_gfx_interface
class sega_segacd_device : public device_t, public device_gfx_interface, public device_video_interface
{
public:
template <typename T> void set_hostcpu(T &&tag) { m_hostcpu.set_tag(std::forward<T>(tag)); }
@ -20,6 +21,7 @@ public:
void set_framerate(int rate) { m_framerate = rate; }
void set_total_scanlines(int total) { m_base_total_scanlines = total; } // this gets set at start only
void update_total_scanlines(bool mode3) { m_total_scanlines = mode3 ? (m_base_total_scanlines * 2) : m_base_total_scanlines; } // this gets set at each EOF
double get_framerate() { return has_screen() ? screen().frame_period().as_hz() : double(m_framerate); }
DECLARE_READ16_MEMBER( segacd_dmaaddr_r );
DECLARE_WRITE16_MEMBER( segacd_dmaaddr_w );

View File

@ -703,21 +703,37 @@ WRITE8_MEMBER(md_base_state::megadriv_z80_vdp_write )
case 0x15:
case 0x17:
// accessed by either segapsg_device or sn76496_device
m_vdp->vdp_w(space, offset >> 1, data, 0x00ff);
m_vdp->vdp_w(offset >> 1, data, 0x00ff);
break;
default:
osd_printf_debug("unhandled z80 vdp write %02x %02x\n",offset,data);
}
}
READ8_MEMBER(md_base_state::megadriv_z80_vdp_read )
{
osd_printf_debug("megadriv_z80_vdp_read %02x\n",offset);
return machine().rand();
u8 ret = 0;
u8 shift = ((~offset & 1) << 3);
switch (offset & ~1)
{
case 0x04: // ctrl_port_r
case 0x06:
case 0x08: // H/V counter
case 0x0a:
case 0x0c:
case 0x0e:
ret = m_vdp->vdp_r(offset >> 1, 0xff << shift) >> shift;
break;
default:
if (!machine().side_effects_disabled())
osd_printf_debug("unhandled z80 vdp read %02x\n",offset);
ret = machine().rand();
break;
}
return ret;
}
READ8_MEMBER(md_base_state::megadriv_z80_unmapped_read )
@ -906,11 +922,12 @@ void md_base_state::md_ntsc(machine_config &config)
m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k));
m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k));
m_vdp->set_screen("megadriv");
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.25);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.25);
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
screen_device &screen(SCREEN(config, "megadriv", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_refresh_hz(double(MASTER_CLOCK_NTSC) / 10.0 / 262.0 / 342.0); // same as SMS?
// screen.set_refresh_hz(double(MASTER_CLOCK_NTSC) / 8.0 / 262.0 / 427.0); // or 427 Htotal?
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually.
screen.set_size(64*8, 620);
screen.set_visarea(0, 32*8-1, 0, 28*8-1);
@ -960,11 +977,12 @@ void md_base_state::md_pal(machine_config &config)
m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k));
m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k));
m_vdp->set_screen("megadriv");
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.25);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.25);
m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50);
m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
screen_device &screen(SCREEN(config, "megadriv", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(50);
screen.set_refresh_hz(double(MASTER_CLOCK_PAL) / 10.0 / 313.0 / 342.0); // same as SMS?
// screen.set_refresh_hz(double(MASTER_CLOCK_PAL) / 8.0 / 313.0 / 423.0); // or 423 Htotal?
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually.
screen.set_size(64*8, 620);
screen.set_visarea(0, 32*8-1, 0, 28*8-1);