summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2022-04-13 16:53:26 +0200
committer angelosa <lordkale4@gmail.com>2022-04-13 16:53:30 +0200
commit6b43a40500193a8342aa64e6849fcba5e7402565 (patch)
tree0a272abc690c208e8b712d05eaa6f26ca23b4ebf
parentc3a817660d87e2c3803a569ea64564b69f40b9ad (diff)
arm_iomd.cpp: improve serial DAC overrun/int handling, makes SFXs to work better in ppcar;
acorn_vidc.cpp: workaround missing default QS1000 sounds in ssfindo/tetfight by disabling DAC outputs for the time being;
-rw-r--r--src/devices/machine/acorn_vidc.cpp95
-rw-r--r--src/devices/machine/acorn_vidc.h18
-rw-r--r--src/devices/machine/arm_iomd.cpp34
-rw-r--r--src/devices/machine/arm_iomd.h13
-rw-r--r--src/mame/drivers/ssfindo.cpp20
5 files changed, 119 insertions, 61 deletions
diff --git a/src/devices/machine/acorn_vidc.cpp b/src/devices/machine/acorn_vidc.cpp
index df95dba9079..f055d11b886 100644
--- a/src/devices/machine/acorn_vidc.cpp
+++ b/src/devices/machine/acorn_vidc.cpp
@@ -12,8 +12,10 @@
* nebulus: 20 lines off with aa310;
* lotustc2: abuses color flipping;
* quazer: needs in-flight DMA;
- - improve sound DAC writes;
- - subclass this for VIDC20 emulation (RiscPC);
+ - move DAC handling into a separate sub-device(s),
+ particularly needed for proper VIDC20 mixing and likely for fixing aliasing
+ issues in VIDC10;
+ - complete VIDC20 emulation (RiscPC/ssfindo.cpp);
- Are CRTC values correct? VGA modes have a +1 in display line;
**********************************************************************************************/
@@ -208,7 +210,7 @@ void acorn_vidc10_device::device_reset()
{
m_cursor_enable = false;
memset(m_stereo_image, 4, m_sound_max_channels);
- for (int ch=0;ch<m_sound_max_channels;ch++)
+ for (int ch = 0; ch < m_sound_max_channels; ch++)
refresh_stereo_image(ch);
m_video_timer->adjust(attotime::never);
m_sound_timer->adjust(attotime::never);
@@ -317,11 +319,11 @@ inline void acorn_vidc10_device::update_4bpp_palette(u16 index, u32 paldata)
void acorn_vidc10_device::pal_data_display_w(offs_t offset, u32 data)
{
- update_4bpp_palette(offset+0x100, data);
+ update_4bpp_palette(offset + 0x100, data);
//printf("%02x: %01x %01x %01x [%d]\n",offset,r,g,b,screen().vpos());
// 8bpp
- for(int idx=0;idx<0x100;idx+=0x10)
+ for (int idx = 0; idx < 0x100; idx += 0x10)
{
int b = ((data & 0x700) >> 8) | ((idx & 0x80) >> 4);
int g = ((data & 0x030) >> 4) | ((idx & 0x60) >> 3);
@@ -415,8 +417,8 @@ inline void acorn_vidc10_device::refresh_stereo_image(u8 channel)
const float left_gain[8] = { 1.0f, 2.0f, 1.66f, 1.34f, 1.0f, 0.66f, 0.34f, 0.0f };
const float right_gain[8] = { 1.0f, 0.0f, 0.34f, 0.66f, 1.0f, 1.34f, 1.66f, 2.0f };
- m_lspeaker->set_input_gain(channel,left_gain[m_stereo_image[channel]]*m_sound_input_gain);
- m_rspeaker->set_input_gain(channel,right_gain[m_stereo_image[channel]]*m_sound_input_gain);
+ m_lspeaker->set_input_gain(channel, left_gain[m_stereo_image[channel]] * m_sound_input_gain);
+ m_rspeaker->set_input_gain(channel, right_gain[m_stereo_image[channel]] * m_sound_input_gain);
//printf("%d %f %f\n",channel,m_lspeaker->input(channel).gain(),m_rspeaker->input(channel).gain());
}
@@ -454,7 +456,7 @@ void acorn_vidc10_device::refresh_sound_frequency()
{
// TODO: Range is between 3 and 256 usecs
double sndhz = 1e6 / ((m_sound_frequency_latch & 0xff) + 2);
- sndhz /= m_sound_internal_divider;
+ sndhz /= get_dac_mode() == true ? 2.0 : 8.0;
m_sound_timer->adjust(attotime::zero, 0, attotime::from_hz(sndhz));
//printf("VIDC: audio DMA start, sound freq %d, sndhz = %f\n", (m_crtc_regs[0xc0] & 0xff)-2, sndhz);
}
@@ -479,17 +481,17 @@ void acorn_vidc10_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect,
//printf("%d %d %d %d\n",ystart, ysize, cliprect.min_y, cliprect.max_y);
- for (int srcy = raster_ystart; srcy<ysize; srcy++)
+ for (int srcy = raster_ystart; srcy < ysize; srcy++)
{
- int dsty = (srcy + ystart)*(m_crtc_interlace+1);
- for (int srcx = 0; srcx<xsize; srcx++)
+ int dsty = (srcy + ystart) * (m_crtc_interlace+1);
+ for (int srcx = 0; srcx < xsize; srcx++)
{
u8 pen = vram[srcx + srcy * xsize];
int dstx = (srcx*xchar_size) + xstart;
- for (int xi=0;xi<xchar_size;xi++)
+ for (int xi = 0; xi < xchar_size; xi++)
{
- u16 dot = ((pen>>(xi*pen_byte_size)) & pen_mask);
+ u16 dot = (pen >> (xi * pen_byte_size)) & pen_mask;
if (is_cursor == true && dot == 0)
continue;
dot += pen_base;
@@ -556,7 +558,11 @@ READ_LINE_MEMBER(acorn_vidc10_device::flyback_r)
return false;
}
-// VIDC20
+/*
+ *
+ * VIDC20 overrides
+ *
+ */
void arm_vidc20_device::regs_map(address_map &map)
{
@@ -564,6 +570,7 @@ void arm_vidc20_device::regs_map(address_map &map)
map(0x10, 0x1f).w(FUNC(arm_vidc20_device::vidc20_pal_data_index_w));
map(0x40, 0x7f).w(FUNC(arm_vidc20_device::vidc20_pal_data_cursor_w));
map(0x80, 0x9f).w(FUNC(arm_vidc20_device::vidc20_crtc_w));
+// map(0xa0, 0xa7) stereo image
map(0xb0, 0xb0).w(FUNC(arm_vidc20_device::vidc20_sound_frequency_w));
map(0xb1, 0xb1).w(FUNC(arm_vidc20_device::vidc20_sound_control_w));
map(0xd0, 0xdf).w(FUNC(arm_vidc20_device::fsynreg_w));
@@ -572,6 +579,7 @@ void arm_vidc20_device::regs_map(address_map &map)
arm_vidc20_device::arm_vidc20_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: acorn_vidc10_device(mconfig, ARM_VIDC20, tag, owner, clock, 2)
+ , m_dac32(*this, "serial_dac_%u", 0)
{
m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, -2, address_map_constructor(FUNC(arm_vidc20_device::regs_map), this));
m_pal_4bpp_base = 0x000;
@@ -583,8 +591,20 @@ arm_vidc20_device::arm_vidc20_device(const machine_config &mconfig, const char *
void arm_vidc20_device::device_add_mconfig(machine_config &config)
{
acorn_vidc10_device::device_add_mconfig(config);
- // ...
- // TODO: for simplicity we may as well add separate DACs for 32-bit mode
+
+ // FIXME: disable DACs for the time being
+ // so that it won't mixin with QS1000 source for ssfindo.cpp games
+ for (int i = 0; i < m_sound_max_channels; i++)
+ {
+ m_dac[i]->reset_routes();
+ m_dac[i]->add_route(0, m_lspeaker, 0.0);
+ m_dac[i]->add_route(0, m_rspeaker, 0.0);
+ }
+
+ // For simplicity we separate DACs for 32-bit mode
+ // TODO: how stereo image copes with this if at all?
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac32[0], 0).add_route(ALL_OUTPUTS, m_lspeaker, 0.25);
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac32[1], 0).add_route(ALL_OUTPUTS, m_rspeaker, 0.25);
}
void arm_vidc20_device::device_config_complete()
@@ -623,13 +643,30 @@ void arm_vidc20_device::device_reset()
// TODO: sensible defaults
m_vco_r_modulo = 1;
m_vco_v_modulo = 1;
+
+ // make sure DACs don't output any undefined behaviour for now
+ // (will cause wild DC offset in ssfindo.cpp games)
+ for (int ch = 0; ch < 8; ch ++)
+ write_dac(ch, 0);
+
+ write_dac32(0, 0);
+ write_dac32(1, 0);
}
void arm_vidc20_device::device_timer(emu_timer &timer, device_timer_id id, int param)
{
acorn_vidc10_device::device_timer(timer, id, param);
+ // TODO: other timers
+}
+
+inline void arm_vidc20_device::refresh_stereo_image(u8 channel)
+{
+ // TODO: set_input_gain hampers with both QS1000 and serial DAC mode
+ // Best option is to move the legacy DAC handling into a separate device,
+ // make it proper 8 channel output while clients are responsible of mix-ins
}
+
inline void arm_vidc20_device::update_8bpp_palette(u16 index, u32 paldata)
{
int r,g,b;
@@ -732,7 +769,7 @@ void arm_vidc20_device::vidc20_control_w(u32 data)
// ---- --00: VCLK
// ---- --01: HCLK
// ---- --10: RCLK ("recommended" 24 MHz)
- // ---- --11: undefined, prolly same as RCLK
+ // ---- --11: undefined, probably same as RCLK
m_pixel_source = data & 3;
m_pixel_rate = (data & 0x1c) >> 2;
// (data & 0x700) >> 8 FIFO load
@@ -750,6 +787,26 @@ void arm_vidc20_device::vidc20_sound_control_w(u32 data)
{
// TODO: VIDC10 mode, ext clock bit 0
m_dac_serial_mode = BIT(data, 1);
+
+ if (m_dac_serial_mode)
+ {
+ m_dac32[0]->set_output_gain(0, 1.0);
+ m_dac32[1]->set_output_gain(0, 1.0);
+
+ for (int ch = 0; ch < m_sound_max_channels; ch++)
+ m_dac[ch]->set_output_gain(0, 0.0);
+ }
+ else
+ {
+ m_dac32[0]->set_output_gain(0, 0.0);
+ m_dac32[1]->set_output_gain(0, 0.0);
+
+ for (int ch = 0; ch < m_sound_max_channels; ch++)
+ {
+ //m_dac[ch]->set_output_gain(0, 0.0);
+ refresh_stereo_image(ch);
+ }
+ }
}
void arm_vidc20_device::vidc20_sound_frequency_w(u32 data)
@@ -761,7 +818,7 @@ void arm_vidc20_device::vidc20_sound_frequency_w(u32 data)
void arm_vidc20_device::write_dac32(u8 channel, u16 data)
{
- m_dac[channel & 1]->write(data);
+ m_dac32[channel & 1]->write(data);
}
bool arm_vidc20_device::get_dac_mode()
@@ -774,5 +831,3 @@ u32 arm_vidc20_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap
// TODO: support for true color modes
return acorn_vidc10_device::screen_update(screen, bitmap, cliprect);
}
-
-
diff --git a/src/devices/machine/acorn_vidc.h b/src/devices/machine/acorn_vidc.h
index 5b68aefc559..d5e86cb1e30 100644
--- a/src/devices/machine/acorn_vidc.h
+++ b/src/devices/machine/acorn_vidc.h
@@ -46,6 +46,8 @@ public:
void set_cursor_enable(bool state) { m_cursor_enable = state; }
u32 get_cursor_size() { return (m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR]) * (32/4); }
+ virtual bool get_dac_mode() { return false; }
+
protected:
acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int dac_type);
@@ -81,7 +83,6 @@ protected:
u16 m_pal_4bpp_base;
u16 m_pal_cursor_base;
u16 m_pal_border_base;
- const double m_sound_internal_divider = 8.0;
u8 m_bpp_mode, m_crtc_interlace;
u8 m_sound_frequency_latch;
@@ -90,9 +91,12 @@ protected:
required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
int m_dac_type;
-private:
required_device<speaker_device> m_lspeaker;
required_device<speaker_device> m_rspeaker;
+
+ virtual void refresh_stereo_image(u8 channel);
+ const int m_sound_max_channels = 8;
+private:
devcb_write_line m_vblank_cb;
devcb_write_line m_sound_drq_cb;
@@ -124,9 +128,7 @@ private:
bool m_sound_frequency_test_bit;
u8 m_stereo_image[8];
const float m_sound_input_gain = 0.05f;
- const int m_sound_max_channels = 8;
int16_t m_ulaw_lookup[256];
- inline void refresh_stereo_image(u8 channel);
};
class acorn_vidc1_device : public acorn_vidc10_device
@@ -154,7 +156,7 @@ public:
arm_vidc20_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
void write_dac32(u8 channel, u16 data);
- bool get_dac_mode();
+ virtual bool get_dac_mode() override;
protected:
virtual void device_add_mconfig(machine_config &config) override;
@@ -167,8 +169,6 @@ protected:
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
virtual u32 get_pixel_clock() override;
- const double m_sound_internal_divider = 1.0;
-
private:
void vidc20_pal_data_display_w(offs_t offset, u32 data);
void vidc20_pal_data_index_w(u32 data);
@@ -186,6 +186,10 @@ private:
u8 m_pixel_rate;
u8 m_vco_r_modulo;
u8 m_vco_v_modulo;
+
+ required_device_array<dac_16bit_r2r_twos_complement_device, 2> m_dac32;
+
+ virtual void refresh_stereo_image(u8 channel) override;
};
DECLARE_DEVICE_TYPE(ARM_VIDC20, arm_vidc20_device)
diff --git a/src/devices/machine/arm_iomd.cpp b/src/devices/machine/arm_iomd.cpp
index af71ab3f53a..2880c46e714 100644
--- a/src/devices/machine/arm_iomd.cpp
+++ b/src/devices/machine/arm_iomd.cpp
@@ -259,8 +259,6 @@ void arm_iomd_device::device_start()
save_item(NAME(m_sndend));
save_item(NAME(m_sound_dma_on));
save_item(NAME(m_sndcur_buffer));
- save_item(NAME(m_snd_overrun));
- save_item(NAME(m_snd_int));
save_pointer(NAME(m_sndcur_reg), sounddma_ch_size);
save_pointer(NAME(m_sndend_reg), sounddma_ch_size);
@@ -303,11 +301,11 @@ void arm_iomd_device::device_reset()
m_irq_mask[i] = 0;
}
- for (i=0; i<timer_ch_size; i++)
+ for (i = 0; i < timer_ch_size; i++)
m_timer[i]->adjust(attotime::never);
m_sound_dma_on = false;
- for (i=0; i<sounddma_ch_size; i++)
+ for (i = 0; i < sounddma_ch_size; i++)
{
m_sndbuffer_ok[i] = false;
m_sndcur_reg[i] = 0;
@@ -555,8 +553,6 @@ u32 arm_iomd_device::version_r()
return m_version;
}
-u32 version_r();
-
// sound DMA
template <unsigned Which> u32 arm_iomd_device::sdcur_r() { return m_sndcur_reg[Which]; }
@@ -572,6 +568,7 @@ template <unsigned Which> void arm_iomd_device::sdend_w(offs_t offset, u32 data,
m_sndend_reg[Which] &= 0x00fffff0;
m_sndstop_reg[Which] = BIT(data, 31);
m_sndlast_reg[Which] = BIT(data, 30);
+ m_sndbuffer_ok[Which] = true;
}
u32 arm_iomd_device::sdcr_r()
@@ -594,12 +591,19 @@ void arm_iomd_device::sdcr_w(u32 data)
// ...
}
- // TODO: bit 7 resets sound DMA
+ // TODO: sound DMA reset
+ // eats samples in ppcar
+// if (BIT(data, 7))
+// m_sndbuffer_ok[0] = m_sndbuffer_ok[1] = false;
}
u32 arm_iomd_device::sdst_r()
{
- return (m_snd_overrun << 2) | (m_snd_int << 1) | m_sndcur_buffer;
+ // TODO: confirm implementation
+ bool sound_overrun = m_sndbuffer_ok[0] == false && m_sndbuffer_ok[1] == false;
+ bool sound_int = m_sndbuffer_ok[0] == false || m_sndbuffer_ok[1] == false;
+
+ return (sound_overrun << 2) | (sound_int << 1) | m_sndcur_buffer;
}
// video DMA
@@ -706,11 +710,7 @@ inline void arm_iomd_device::sounddma_swap_buffer()
{
m_sndcur = m_sndcur_reg[m_sndcur_buffer];
m_sndend = m_sndcur + (m_sndend_reg[m_sndcur_buffer] + 0x10);
- m_sndbuffer_ok[m_sndcur_buffer] = true;
-
- // TODO: actual condition for int
- m_snd_overrun = false;
- m_snd_int = false;
+// m_sndbuffer_ok[m_sndcur_buffer] = true;
}
WRITE_LINE_MEMBER( arm_iomd_device::sound_drq )
@@ -720,21 +720,21 @@ WRITE_LINE_MEMBER( arm_iomd_device::sound_drq )
if (m_vidc->get_dac_mode() == true)
{
- for (int ch=0;ch<2;ch++)
+ if (!m_sndbuffer_ok[m_sndcur_buffer])
+ return;
+
+ for (int ch = 0; ch < 2; ch++)
m_vidc->write_dac32(ch, (m_host_space->read_word(m_sndcur + ch*2)));
m_sndcur += 4;
if (m_sndcur >= m_sndend)
{
- // TODO: interrupt bit
-
m_vidc->update_sound_mode(m_sound_dma_on);
if (m_sound_dma_on)
{
m_sndbuffer_ok[m_sndcur_buffer] = false;
m_sndcur_buffer ^= 1;
- m_snd_overrun = (m_sndbuffer_ok[m_sndcur_buffer] == false);
sounddma_swap_buffer();
}
else
diff --git a/src/devices/machine/arm_iomd.h b/src/devices/machine/arm_iomd.h
index c7c98035e85..8600c55cf22 100644
--- a/src/devices/machine/arm_iomd.h
+++ b/src/devices/machine/arm_iomd.h
@@ -118,13 +118,12 @@ private:
void cursinit_w(offs_t offset, u32 data, u32 mem_mask = ~0);
static constexpr int sounddma_ch_size = 2;
- u32 m_sndcur, m_sndend;
- u32 m_sndcur_reg[sounddma_ch_size], m_sndend_reg[sounddma_ch_size];
- bool m_sndstop_reg[sounddma_ch_size], m_sndlast_reg[sounddma_ch_size];
- bool m_sndbuffer_ok[sounddma_ch_size];
- bool m_sound_dma_on;
- u8 m_sndcur_buffer;
- bool m_snd_overrun, m_snd_int;
+ u32 m_sndcur = 0, m_sndend = 0;
+ u32 m_sndcur_reg[sounddma_ch_size]{}, m_sndend_reg[sounddma_ch_size]{};
+ bool m_sndstop_reg[sounddma_ch_size]{}, m_sndlast_reg[sounddma_ch_size]{};
+ bool m_sndbuffer_ok[sounddma_ch_size]{};
+ bool m_sound_dma_on = false;
+ u8 m_sndcur_buffer = 0;
inline void sounddma_swap_buffer();
template <unsigned Which> u32 sdcur_r();
template <unsigned Which> void sdcur_w(offs_t offset, u32 data, u32 mem_mask = ~0);
diff --git a/src/mame/drivers/ssfindo.cpp b/src/mame/drivers/ssfindo.cpp
index c653b76e3a8..ce06865870f 100644
--- a/src/mame/drivers/ssfindo.cpp
+++ b/src/mame/drivers/ssfindo.cpp
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Tomasz Slanina
-/************************************************************************
+/**************************************************************************************************
'RISC PC' hardware
@@ -17,10 +17,10 @@ TODO:
- timing
- unknown reads/writes
- improve sound hook up
- - ppcar uses the VIDC internal DAC for SFX and the QS1000 for music. It's configured to use the undumped internal ROM.
+ - ppcar: uses the VIDC internal DAC for SFX and the QS1000 for music.
+ It's configured to use the undumped internal ROM.
-
-*************************************************************************************************************
+===================================================================================================
See See Find Out
Icarus, 1999
@@ -69,7 +69,7 @@ Notes:
mounting pads for 4 more of these ROMs but they're not populated.
-**************************************************************************************************************
+===================================================================================================
Pong Pong Car
Icarus, 1999
@@ -124,7 +124,7 @@ Notes:
DU5, DU6 These ROMs are mounted on a small plug-in daughterboard. There are additional
mounting pads for 4 more of these ROMs but they're not populated.
-*/
+**************************************************************************************************/
#include "emu.h"
#include "cpu/arm7/arm7.h"
@@ -235,7 +235,7 @@ private:
uint32_t tetfight_unk_r();
};
-//TODO: eeprom 24c01 & 24c02
+// TODO: eeprom 24c01 & 24c02
// TODO: untangle, kill hacks
uint8_t ssfindo_state::iolines_r()
{
@@ -616,8 +616,8 @@ void ssfindo_state::ssfindo(machine_config &config)
qs1000_device &qs1000(QS1000(config, "qs1000", 24_MHz_XTAL));
qs1000.set_external_rom(true);
// qs1000.p1_out().set(FUNC()); // TODO: writes something here
- qs1000.add_route(0, "lspeaker", 1.0);
- qs1000.add_route(1, "rspeaker", 1.0);
+ qs1000.add_route(0, "lspeaker", 0.25);
+ qs1000.add_route(1, "rspeaker", 0.25);
}
void ssfindo_state::ppcar(machine_config &config)
@@ -740,4 +740,4 @@ void tetfight_state::init_tetfight()
GAME( 1999, ssfindo, 0, ssfindo, ssfindo, ssfindo_state, init_ssfindo, ROT0, "Icarus", "See See Find Out", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 1999, ppcar, 0, ppcar, ppcar, ssfindo_state, init_ppcar, ROT0, "Icarus", "Pang Pang Car", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 2001, tetfight,0, tetfight, tetfight, tetfight_state, init_tetfight, ROT0, "Sego", "Tetris Fighters", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
+GAME( 2001, tetfight,0, tetfight, tetfight, tetfight_state, init_tetfight, ROT0, "Sego", "Tetris Fighters", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // severe frame hiccups