mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
-mcd212: Various accuracy and timing improvements. [Ryan Holtz] (#9123)
* Added wait states on ROM and VRAM accesses. * Simplified pixel-duplication in 360/384-width modes. * Fixed DCA to process after VSR. * Switched to use raw parameters for screens. * Fixed some transparency-fill issues with disabled ICM/VSR.
This commit is contained in:
parent
db8b82e60f
commit
255e3d6f3f
@ -3,8 +3,8 @@
|
||||
/******************************************************************************
|
||||
|
||||
|
||||
Philips CD-I-based games
|
||||
------------------------
|
||||
Philips CD-i consoles and games
|
||||
-------------------------------
|
||||
|
||||
Preliminary MAME driver by Ryan Holtz
|
||||
Help provided by CD-i Fan
|
||||
@ -30,14 +30,18 @@ STATUS:
|
||||
* Philips IMS66490, "CDIC" ADPCM decoder
|
||||
* PC85010 DSP
|
||||
|
||||
Quizard:
|
||||
- Quizard 3 and 4 fail when going in-game, presumably due to CD-i emulation
|
||||
faults.
|
||||
|
||||
TODO:
|
||||
|
||||
- Screen clocks are a hack right now; they should be exactly CLOCK_A/2. However, the
|
||||
MCD-212 documentation states in both tables and timing diagrams that vertical retrace
|
||||
has an additional half-line even in non-interlaced mode, which cannot be represented
|
||||
in the current screen-timing framework. The input clock has been adjusted downward
|
||||
to factor out this half-line, resulting in the expected 50Hz exactly in PAL mode.
|
||||
|
||||
- Proper abstraction of the 68070's internal devices (UART, DMA, Timers, etc.)
|
||||
|
||||
- Mono-I: Full emulation of the CDIC, as well as the SERVO and SLAVE MCUs
|
||||
|
||||
- Mono-II: SERVO and SLAVE I/O device hookup
|
||||
- Mono-II: DSP56k hookup
|
||||
|
||||
@ -81,8 +85,8 @@ TODO:
|
||||
void cdi_state::cdimono1_mem(address_map &map)
|
||||
{
|
||||
map(0x000000, 0xffffff).rw(FUNC(cdi_state::bus_error_r), FUNC(cdi_state::bus_error_w));
|
||||
map(0x000000, 0x07ffff).ram().share("mcd212:planea");
|
||||
map(0x200000, 0x27ffff).ram().share("mcd212:planeb");
|
||||
map(0x000000, 0x07ffff).rw(FUNC(cdi_state::plane_r<0>), FUNC(cdi_state::plane_w<0>)).share("plane0");
|
||||
map(0x200000, 0x27ffff).rw(FUNC(cdi_state::plane_r<1>), FUNC(cdi_state::plane_w<1>)).share("plane1");
|
||||
map(0x300000, 0x303bff).rw(m_cdic, FUNC(cdicdic_device::ram_r), FUNC(cdicdic_device::ram_w));
|
||||
#if ENABLE_UART_PRINTING
|
||||
map(0x301400, 0x301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
|
||||
@ -91,7 +95,7 @@ void cdi_state::cdimono1_mem(address_map &map)
|
||||
map(0x310000, 0x317fff).rw(m_slave_hle, FUNC(cdislave_hle_device::slave_r), FUNC(cdislave_hle_device::slave_w));
|
||||
map(0x318000, 0x31ffff).noprw();
|
||||
map(0x320000, 0x323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
|
||||
map(0x400000, 0x47ffff).rom().region("maincpu", 0);
|
||||
map(0x400000, 0x47ffff).r(FUNC(cdi_state::main_rom_r));
|
||||
map(0x4fffe0, 0x4fffff).m(m_mcd212, FUNC(mcd212_device::map));
|
||||
map(0x500000, 0x57ffff).ram();
|
||||
map(0xd00000, 0xdfffff).ram(); // DVC RAM block 1
|
||||
@ -101,22 +105,21 @@ void cdi_state::cdimono1_mem(address_map &map)
|
||||
|
||||
void cdi_state::cdimono2_mem(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x07ffff).ram().share("mcd212:planea");
|
||||
map(0x200000, 0x27ffff).ram().share("mcd212:planeb");
|
||||
map(0x000000, 0x07ffff).ram().share("plane0");
|
||||
map(0x200000, 0x27ffff).ram().share("plane1");
|
||||
#if ENABLE_UART_PRINTING
|
||||
map(0x301400, 0x301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
|
||||
#endif
|
||||
map(0x320000, 0x323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
|
||||
map(0x400000, 0x47ffff).rom().region("maincpu", 0);
|
||||
map(0x400000, 0x47ffff).r(FUNC(cdi_state::main_rom_r));
|
||||
map(0x4fffe0, 0x4fffff).m(m_mcd212, FUNC(mcd212_device::map));
|
||||
}
|
||||
|
||||
void cdi_state::cdi910_mem(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x07ffff).ram().share("mcd212:planea");
|
||||
map(0x000000, 0x07ffff).ram().share("plane0");
|
||||
map(0x180000, 0x1fffff).rom().region("maincpu", 0); // boot vectors point here
|
||||
|
||||
map(0x200000, 0x27ffff).ram().share("mcd212:planeb");
|
||||
map(0x200000, 0x27ffff).ram().share("plane1");
|
||||
#if ENABLE_UART_PRINTING
|
||||
map(0x301400, 0x301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
|
||||
#endif
|
||||
@ -174,8 +177,8 @@ INPUT_PORTS_END
|
||||
|
||||
void cdi_state::machine_reset()
|
||||
{
|
||||
uint16_t *src = (uint16_t*)memregion("maincpu")->base();
|
||||
uint16_t *dst = m_planea;
|
||||
uint16_t *src = &m_main_rom[0];
|
||||
uint16_t *dst = &m_plane_ram[0][0];
|
||||
memcpy(dst, src, 0x8);
|
||||
}
|
||||
|
||||
@ -194,6 +197,31 @@ void quizard_state::machine_reset()
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
* Wait-State Handling *
|
||||
***************************/
|
||||
|
||||
template<int Channel>
|
||||
uint16_t cdi_state::plane_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
m_maincpu->eat_cycles(m_mcd212->ram_dtack_cycle_count<Channel>());
|
||||
return m_plane_ram[Channel][offset];
|
||||
}
|
||||
|
||||
template<int Channel>
|
||||
void cdi_state::plane_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
m_maincpu->eat_cycles(m_mcd212->ram_dtack_cycle_count<Channel>());
|
||||
COMBINE_DATA(&m_plane_ram[Channel][offset]);
|
||||
}
|
||||
|
||||
uint16_t cdi_state::main_rom_r(offs_t offset)
|
||||
{
|
||||
m_maincpu->eat_cycles(m_mcd212->rom_dtack_cycle_count());
|
||||
return m_main_rom[offset];
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* BERR Handling *
|
||||
**********************/
|
||||
@ -393,18 +421,14 @@ void cdi_state::cdimono1_base(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &cdi_state::cdimono1_mem);
|
||||
m_maincpu->iack4_callback().set(m_cdic, FUNC(cdicdic_device::intack_r));
|
||||
|
||||
MCD212(config, m_mcd212, CLOCK_A);
|
||||
MCD212(config, m_mcd212, CLOCK_A, m_plane_ram[0], m_plane_ram[1]);
|
||||
m_mcd212->set_screen("screen");
|
||||
m_mcd212->int_callback().set(m_maincpu, FUNC(scc68070_device::int1_w));
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(50);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.set_raw(14976000, 960, 0, 768, 312, 32, 312);
|
||||
screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
|
||||
screen.set_size(384, 312);
|
||||
screen.set_visarea(0, 384-1, 0, 312-1); // TODO: dynamic resolution
|
||||
screen.set_screen_update(m_mcd212, FUNC(mcd212_device::screen_update));
|
||||
screen.screen_vblank().set(m_mcd212, FUNC(mcd212_device::screen_vblank));
|
||||
|
||||
SCREEN(config, m_lcd, SCREEN_TYPE_RASTER);
|
||||
m_lcd->set_refresh_hz(50);
|
||||
@ -445,18 +469,14 @@ void cdi_state::cdimono2(machine_config &config)
|
||||
SCC68070(config, m_maincpu, CLOCK_A);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &cdi_state::cdimono2_mem);
|
||||
|
||||
MCD212(config, m_mcd212, CLOCK_A);
|
||||
MCD212(config, m_mcd212, CLOCK_A, m_plane_ram[0], m_plane_ram[1]);
|
||||
m_mcd212->set_screen("screen");
|
||||
m_mcd212->int_callback().set(m_maincpu, FUNC(scc68070_device::int1_w));
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.set_raw(14976000, 960, 0, 768, 312, 32, 312);
|
||||
screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
|
||||
screen.set_size(384, 312);
|
||||
screen.set_visarea(0, 384-1, 0, 312-1); // TODO: dynamic resolution
|
||||
screen.set_screen_update(m_mcd212, FUNC(mcd212_device::screen_update));
|
||||
screen.screen_vblank().set(m_mcd212, FUNC(mcd212_device::screen_vblank));
|
||||
|
||||
SCREEN(config, m_lcd, SCREEN_TYPE_RASTER);
|
||||
m_lcd->set_refresh_hz(60);
|
||||
@ -493,18 +513,14 @@ void cdi_state::cdi910(machine_config &config)
|
||||
SCC68070(config, m_maincpu, CLOCK_A);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &cdi_state::cdi910_mem);
|
||||
|
||||
MCD212(config, m_mcd212, CLOCK_A);
|
||||
MCD212(config, m_mcd212, CLOCK_A, m_plane_ram[0], m_plane_ram[1]);
|
||||
m_mcd212->set_screen("screen");
|
||||
m_mcd212->int_callback().set(m_maincpu, FUNC(scc68070_device::int1_w));
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(50);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.set_raw(14976000, 960, 0, 768, 312, 32, 312);
|
||||
screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
|
||||
screen.set_size(384, 312);
|
||||
screen.set_visarea(0, 384-1, 32, 312-1); // TODO: dynamic resolution
|
||||
screen.set_screen_update(m_mcd212, FUNC(mcd212_device::screen_update));
|
||||
screen.screen_vblank().set(m_mcd212, FUNC(mcd212_device::screen_vblank));
|
||||
|
||||
SCREEN(config, m_lcd, SCREEN_TYPE_RASTER);
|
||||
m_lcd->set_refresh_hz(60);
|
||||
|
@ -21,8 +21,9 @@ public:
|
||||
cdi_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_main_rom(*this, "maincpu")
|
||||
, m_lcd(*this, "lcd")
|
||||
, m_planea(*this, "mcd212:planea")
|
||||
, m_plane_ram(*this, "plane%u", 0U)
|
||||
, m_slave_hle(*this, "slave_hle")
|
||||
, m_servo(*this, "servo")
|
||||
, m_slave(*this, "slave")
|
||||
@ -42,6 +43,7 @@ protected:
|
||||
void cdimono1_mem(address_map &map);
|
||||
|
||||
required_device<scc68070_device> m_maincpu;
|
||||
required_region_ptr<uint16_t> m_main_rom;
|
||||
optional_device<screen_device> m_lcd;
|
||||
|
||||
private:
|
||||
@ -58,13 +60,18 @@ private:
|
||||
void cdimono2_mem(address_map &map);
|
||||
void cdi070_cpuspace(address_map &map);
|
||||
|
||||
template<int Channel> uint16_t plane_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
template<int Channel> void plane_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
uint16_t main_rom_r(offs_t offset);
|
||||
|
||||
uint16_t dvc_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void dvc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
uint16_t bus_error_r(offs_t offset);
|
||||
void bus_error_w(offs_t offset, uint16_t data);
|
||||
|
||||
required_shared_ptr<uint16_t> m_planea;
|
||||
required_shared_ptr_array<uint16_t, 2> m_plane_ram;
|
||||
optional_device<cdislave_hle_device> m_slave_hle;
|
||||
optional_device<m68hc05c8_device> m_servo;
|
||||
optional_device<m68hc05c8_device> m_slave;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,21 +35,34 @@ class mcd212_device : public device_t,
|
||||
public device_video_interface
|
||||
{
|
||||
public:
|
||||
template <typename T, typename U>
|
||||
mcd212_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&plane_a_tag, U &&plane_b_tag)
|
||||
: mcd212_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
m_planea.set_tag(std::forward<T>(plane_a_tag));
|
||||
m_planeb.set_tag(std::forward<U>(plane_b_tag));
|
||||
}
|
||||
|
||||
mcd212_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
auto int_callback() { return m_int_callback.bind(); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
template <int Channel> int ram_dtack_cycle_count();
|
||||
int rom_dtack_cycle_count();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(ica_tick);
|
||||
TIMER_CALLBACK_MEMBER(dca_tick);
|
||||
|
||||
uint8_t csr1_r();
|
||||
void csr1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t dcr1_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
@ -83,19 +96,18 @@ protected:
|
||||
CURCNT_BLKC = 0x400000, // Blink type
|
||||
CURCNT_EN = 0x800000, // Cursor enable
|
||||
|
||||
ICM_CS = 0x400000, // CLUT select
|
||||
ICM_NR = 0x080000, // Number of region flags
|
||||
ICM_NR_BIT = 19,
|
||||
ICM_EV = 0x040000, // External video
|
||||
ICM_MODE2 = 0x000f00, // Plane 2
|
||||
ICM_MODE2_SHIFT = 8,
|
||||
ICM_MODE1 = 0x00000f, // Plane 1
|
||||
ICM_MODE1_SHIFT = 0,
|
||||
ICM_MODE2 = 0x000f00, // Plane 2
|
||||
ICM_MODE2_SHIFT = 8,
|
||||
ICM_EV = 0x040000, // External video
|
||||
ICM_NR = 0x080000, // Number of region flags
|
||||
ICM_NR_BIT = 19,
|
||||
ICM_CS = 0x400000, // CLUT select
|
||||
|
||||
TCR_DISABLE_MX = 0x800000, // Mix disable
|
||||
TCR_TA = 0x00000f, // Plane A
|
||||
TCR_TB = 0x000f00, // Plane B
|
||||
TCR_TB_SHIFT = 8,
|
||||
TCR_TA = 0x00000f, // Plane A
|
||||
TCR_COND_1 = 0x0, // Transparent if: Always (Plane Disabled)
|
||||
TCR_COND_KEY_1 = 0x1, // Transparent if: Color Key = True
|
||||
TCR_COND_XLU_1 = 0x2, // Transparent if: Transparency Bit = 1
|
||||
@ -112,6 +124,7 @@ protected:
|
||||
TCR_COND_RF0KEY_0 = 0xd, // Transparent if: Region Flag 0 = False && Color Key = False
|
||||
TCR_COND_RF1KEY_0 = 0xe, // Transparent if: Region Flag 1 = False && Color Key = False
|
||||
TCR_COND_UNUSED1 = 0xf, // Unused
|
||||
TCR_DISABLE_MX = 0x800000, // Mix disable
|
||||
|
||||
POR_AB = 0, // Plane A in front of Plane B
|
||||
POR_BA = 1, // Plane B in front of Plane A
|
||||
@ -123,32 +136,47 @@ protected:
|
||||
RC_OP = 0xf00000, // Operation
|
||||
RC_OP_SHIFT = 20,
|
||||
|
||||
CSR1W_ST = 0x0002, // Standard
|
||||
CSR1W_BE = 0x0001, // Bus Error
|
||||
CSR1R_PA = 0x20, // Parity
|
||||
CSR1R_DA = 0x80, // Display Active
|
||||
|
||||
CSR2R_IT1 = 0x0004, // Interrupt 1
|
||||
CSR2R_IT2 = 0x0002, // Interrupt 2
|
||||
CSR2R_BE = 0x0001, // Bus Error
|
||||
CSR1W_BE = 0x0001, // Bus Error
|
||||
CSR1W_ST_BIT = 1, // Standard
|
||||
CSR1W_DD_BIT = 3,
|
||||
CSR1W_DD2 = 0x0300, // /DTACK Delay
|
||||
CSR1W_DD2_SHIFT = 8,
|
||||
CSR1W_DI1_BIT = 15,
|
||||
|
||||
DCR_DE = 0x8000, // Display Enable
|
||||
DCR_CF = 0x4000, // Crystal Frequency
|
||||
DCR_FD = 0x2000, // Frame Duration
|
||||
DCR_SM = 0x1000, // Scan Mode
|
||||
DCR_CM = 0x0800, // Color Mode Ch.1/2
|
||||
DCR_ICA = 0x0200, // ICA Enable Ch.1/2
|
||||
DCR_DCA = 0x0100, // DCA Enable Ch.1/2
|
||||
CSR2R_BE = 0x0001, // Bus Error
|
||||
CSR2R_IT2 = 0x0002, // Interrupt 2
|
||||
CSR2R_IT1 = 0x0004, // Interrupt 1
|
||||
|
||||
DDR_FT = 0x0300, // Display File Type
|
||||
DDR_FT_BMP = 0x0000, // Bitmap
|
||||
DDR_FT_BMP2 = 0x0100, // Bitmap (alt.)
|
||||
DDR_FT_RLE = 0x0200, // Run-Length Encoded
|
||||
DDR_FT_MOSAIC = 0x0300, // Mosaic
|
||||
DDR_MT = 0x0c00, // Mosaic File Type
|
||||
DDR_MT_2 = 0x0000, // 2x1
|
||||
DDR_MT_4 = 0x0400, // 4x1
|
||||
DDR_MT_8 = 0x0800, // 8x1
|
||||
DDR_MT_16 = 0x0c00, // 16x1
|
||||
DDR_MT_SHIFT = 10
|
||||
DCR_DCA_BIT = 8, // DCA Enable Ch.1/2
|
||||
DCR_ICA_BIT = 9, // ICA Enable Ch.1/2
|
||||
DCR_CM_BIT = 11, // Color Mode Ch.1/2
|
||||
DCR_SM_BIT = 12, // Scan Mode
|
||||
DCR_FD_BIT = 13, // Frame Duration
|
||||
DCR_CF_BIT = 14, // Crystal Frequency
|
||||
DCR_DE_BIT = 15, // Display Enable
|
||||
|
||||
DDR_MT = 0x0c00, // Mosaic File Type
|
||||
DDR_MT_2 = 0x0000, // 2x1
|
||||
DDR_MT_4 = 0x0400, // 4x1
|
||||
DDR_MT_8 = 0x0800, // 8x1
|
||||
DDR_MT_16 = 0x0c00, // 16x1
|
||||
DDR_MT_SHIFT = 10,
|
||||
DDR_FT = 0x0300, // Display File Type
|
||||
DDR_FT_BMP = 0x0000, // Bitmap
|
||||
DDR_FT_BMP2 = 0x0100, // Bitmap (alt.)
|
||||
DDR_FT_RLE = 0x0200, // Run-Length Encoded
|
||||
DDR_FT_MOSAIC = 0x0300, // Mosaic
|
||||
|
||||
ICM_OFF = 0x0,
|
||||
ICM_CLUT8 = 0x1,
|
||||
ICM_RGB555 = 0x2,
|
||||
ICM_CLUT7 = 0x3,
|
||||
ICM_CLUT77 = 0x4,
|
||||
ICM_DYUV = 0x5,
|
||||
ICM_CLUT4 = 0xb
|
||||
};
|
||||
|
||||
uint8_t m_csrr[2];
|
||||
@ -207,6 +235,8 @@ protected:
|
||||
bool m_region_flag[2][768];
|
||||
int m_ica_height;
|
||||
int m_total_height;
|
||||
emu_timer *m_ica_timer;
|
||||
emu_timer *m_dca_timer;
|
||||
|
||||
static const uint32_t s_4bpp_color[16];
|
||||
|
||||
@ -214,8 +244,9 @@ protected:
|
||||
uint8_t get_region_op(const uint32_t region_idx);
|
||||
void update_region_arrays();
|
||||
|
||||
void update_visible_area();
|
||||
uint32_t get_screen_width();
|
||||
int get_screen_width();
|
||||
int get_border_width();
|
||||
template <int Channel> int get_plane_width();
|
||||
|
||||
template <int Channel> void set_vsr(uint32_t value);
|
||||
template <int Channel> uint32_t get_vsr();
|
||||
@ -239,7 +270,6 @@ protected:
|
||||
template <bool MosaicA, bool MosaicB, bool OrderAB> void mix_lines(uint32_t *plane_a, bool *transparent_a, uint32_t *plane_b, bool *transparent_b, uint32_t *out);
|
||||
|
||||
void draw_cursor(uint32_t *scanline);
|
||||
void draw_scanline(bitmap_rgb32 &bitmap);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
|
Loading…
Reference in New Issue
Block a user