diff options
Diffstat (limited to 'src/devices/machine/acorn_vidc.cpp')
-rw-r--r-- | src/devices/machine/acorn_vidc.cpp | 340 |
1 files changed, 297 insertions, 43 deletions
diff --git a/src/devices/machine/acorn_vidc.cpp b/src/devices/machine/acorn_vidc.cpp index 4ad88d5d4df..94ddfb8b3c8 100644 --- a/src/devices/machine/acorn_vidc.cpp +++ b/src/devices/machine/acorn_vidc.cpp @@ -30,6 +30,7 @@ // device type definition DEFINE_DEVICE_TYPE(ACORN_VIDC10, acorn_vidc10_device, "acorn_vidc10", "Acorn VIDC10") DEFINE_DEVICE_TYPE(ACORN_VIDC10_LCD, acorn_vidc10_lcd_device, "acorn_vidc10_lcd", "Acorn VIDC10 with LCD monitor") +DEFINE_DEVICE_TYPE(ARM_VIDC20, arm_vidc20_device, "arm_vidc20", "ARM VIDC20") //************************************************************************** @@ -51,25 +52,23 @@ void acorn_vidc10_device::regs_map(address_map &map) } -acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) +acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, type, tag, owner, clock) , device_memory_interface(mconfig, *this) , device_palette_interface(mconfig, *this) , device_video_interface(mconfig, *this) - , m_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_device::regs_map), this)) + , m_bpp_mode(0) + , m_crtc_interlace(0) + , m_sound_frequency_latch(0) + , m_sound_mode(false) + , m_dac(*this, "dac%u", 0) , m_lspeaker(*this, "lspeaker") , m_rspeaker(*this, "rspeaker") - , m_dac(*this, "dac%u", 0) , m_vblank_cb(*this) , m_sound_drq_cb(*this) , m_pixel_clock(0) - , m_bpp_mode(0) - , m_crtc_interlace(0) , m_cursor_enable(false) - , m_sound_frequency_latch(0) , m_sound_frequency_test_bit(false) - , m_sound_mode(false) - { std::fill(std::begin(m_crtc_regs), std::end(m_crtc_regs), 0); std::fill(std::begin(m_stereo_image), std::end(m_stereo_image), 0); @@ -78,12 +77,21 @@ acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_t acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : acorn_vidc10_device(mconfig, ACORN_VIDC10, tag, owner, clock) { + m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_device::regs_map), this)); + m_pal_4bpp_base = 0x100; + m_pal_cursor_base = 0x10; + m_pal_border_base = 0x110; } -acorn_vidc10_lcd_device::acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +acorn_vidc10_lcd_device::acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : acorn_vidc10_device(mconfig, ACORN_VIDC10_LCD, tag, owner, clock) { + m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_lcd_device::regs_map), this)); + // TODO: confirm being identical to raster version + m_pal_4bpp_base = 0x100; + m_pal_cursor_base = 0x10; + m_pal_border_base = 0x110; } device_memory_interface::space_config_vector acorn_vidc10_device::memory_space_config() const @@ -118,7 +126,7 @@ void acorn_vidc10_lcd_device::device_add_mconfig(machine_config &config) // TODO: verify !Configure with automatic type detection, there must be an ID telling this is a LCD machine. } -uint32_t acorn_vidc10_device::palette_entries() const +u32 acorn_vidc10_device::palette_entries() const { return 0x100+0x10+4; // 8bpp + 1/2/4bpp + 2bpp for cursor } @@ -160,8 +168,9 @@ void acorn_vidc10_device::device_start() save_item(NAME(m_sound_frequency_test_bit)); save_item(NAME(m_cursor_enable)); save_pointer(NAME(m_crtc_regs), CRTC_VCER+1); - m_data_vram = auto_alloc_array_clear(machine(), u8, m_data_vram_size); - m_cursor_vram = auto_alloc_array_clear(machine(), u8, m_cursor_vram_size); + save_pointer(NAME(m_crtc_raw_horz), 2); + m_data_vram = make_unique_clear<u8[]>(m_data_vram_size); + m_cursor_vram = make_unique_clear<u8[]>(m_cursor_vram_size); save_pointer(NAME(m_data_vram), m_data_vram_size); save_pointer(NAME(m_cursor_vram), m_cursor_vram_size); save_pointer(NAME(m_stereo_image), m_sound_max_channels); @@ -174,8 +183,8 @@ void acorn_vidc10_device::device_start() // TODO: manual mentions a format difference between VIDC10 revisions for (int rawval = 0; rawval < 256; rawval++) { - uint8_t chord = rawval >> 5; - uint8_t point = (rawval & 0x1e) >> 1; + u8 chord = rawval >> 5; + u8 point = (rawval & 0x1e) >> 1; bool sign = rawval & 1; int16_t result = ((16+point)<<chord)-16; @@ -184,6 +193,8 @@ void acorn_vidc10_device::device_start() m_ulaw_lookup[rawval] = result*8; } + + // saved for debugging purposes save_pointer(NAME(m_ulaw_lookup), 256); } @@ -195,8 +206,6 @@ void acorn_vidc10_device::device_start() void acorn_vidc10_device::device_reset() { m_cursor_enable = false; - memset(m_data_vram, 0, m_data_vram_size); - memset(m_cursor_vram, 0, m_cursor_vram_size); memset(m_stereo_image, 4, m_sound_max_channels); for (int ch=0;ch<m_sound_max_channels;ch++) refresh_stereo_image(ch); @@ -232,9 +241,15 @@ inline void acorn_vidc10_device::screen_vblank_line_update() m_video_timer->adjust((vline > 2) ? screen().time_until_pos(vline) : attotime::never); } -void acorn_vidc10_device::screen_dynamic_res_change() +u32 acorn_vidc10_device::get_pixel_clock() { const int32_t pixel_rate[4] = { 8000000, 12000000, 16000000, 24000000}; + return pixel_rate[m_pixel_clock]; +} + +inline void acorn_vidc10_device::screen_dynamic_res_change() +{ + const u32 pixel_clock = get_pixel_clock(); // sanity checks if (m_crtc_regs[CRTC_HCR] <= 1 || m_crtc_regs[CRTC_VCR] <= 1) @@ -267,7 +282,7 @@ void acorn_vidc10_device::screen_dynamic_res_change() m_vidc_vblank_time); #endif - attoseconds_t const refresh = HZ_TO_ATTOSECONDS(pixel_rate[m_pixel_clock]) * m_crtc_regs[CRTC_HCR] * m_crtc_regs[CRTC_VCR]; + attoseconds_t const refresh = HZ_TO_ATTOSECONDS(pixel_clock) * m_crtc_regs[CRTC_HCR] * m_crtc_regs[CRTC_VCR]; screen().configure(m_crtc_regs[CRTC_HCR], m_crtc_regs[CRTC_VCR] * (m_crtc_interlace+1), visarea, refresh); } @@ -279,13 +294,13 @@ void acorn_vidc10_device::screen_dynamic_res_change() WRITE32_MEMBER( acorn_vidc10_device::write ) { // TODO: check against mem_mask not 32-bit wide - uint8_t reg = data >> 24; - uint32_t val = data & 0xffffff; - + u8 reg = data >> 24; + u32 val = data & 0xffffff; + this->space(AS_IO).write_dword(reg, val); } -inline void acorn_vidc10_device::update_4bpp_palette(uint16_t index, uint32_t paldata) +inline void acorn_vidc10_device::update_4bpp_palette(u16 index, u32 paldata) { int r,g,b; @@ -331,20 +346,34 @@ WRITE32_MEMBER( acorn_vidc10_device::control_w ) //m_test_mode = (data & 0xc100) != 0xc100; //todo: vga/svga modes sets 0x1000? + m_crtc_regs[CRTC_HDSR] = convert_crtc_hdisplay(0); + m_crtc_regs[CRTC_HDER] = convert_crtc_hdisplay(1); screen_vblank_line_update(); screen_dynamic_res_change(); } +inline u32 acorn_vidc10_device::convert_crtc_hdisplay(u8 index) +{ + const u8 x_step[4] = { 19, 11, 7, 5 }; + return (m_crtc_raw_horz[index]*2)+x_step[m_bpp_mode]; +} + WRITE32_MEMBER( acorn_vidc10_device::crtc_w ) { switch(offset) { - case CRTC_HCR: m_crtc_regs[CRTC_HCR] = ((data >> 14)<<1)+2; break; -// case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data >> 14)+1; break; - case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = ((data >> 14)<<1)+1; break; - case CRTC_HDSR: m_crtc_regs[CRTC_HDSR] = (data >> 14); break; - case CRTC_HDER: m_crtc_regs[CRTC_HDER] = (data >> 14); break; - case CRTC_HBER: m_crtc_regs[CRTC_HBER] = ((data >> 14)<<1)+1; break; + case CRTC_HCR: m_crtc_regs[CRTC_HCR] = ((data >> 14)<<1)+2; break; +// case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data >> 14)+1; break; + case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = ((data >> 14)<<1)+1; break; + case CRTC_HDSR: + m_crtc_raw_horz[0] = (data >> 14); + m_crtc_regs[CRTC_HDSR] = convert_crtc_hdisplay(0); + break; + case CRTC_HDER: + m_crtc_raw_horz[1] = (data >> 14); + m_crtc_regs[CRTC_HDER] = convert_crtc_hdisplay(1); + break; + case CRTC_HBER: m_crtc_regs[CRTC_HBER] = ((data >> 14)<<1)+1; break; case CRTC_HCSR: m_crtc_regs[CRTC_HCSR] = ((data >> 13) & 0x7ff) + 6; return; // case CRTC_HIR: // ... @@ -370,7 +399,7 @@ WRITE32_MEMBER( acorn_vidc10_device::crtc_w ) screen_dynamic_res_change(); } -inline void acorn_vidc10_device::refresh_stereo_image(uint8_t channel) +inline void acorn_vidc10_device::refresh_stereo_image(u8 channel) { /* -111 full right @@ -393,7 +422,7 @@ inline void acorn_vidc10_device::refresh_stereo_image(uint8_t channel) WRITE32_MEMBER( acorn_vidc10_device::stereo_image_w ) { - uint8_t channel = (offset + 7) & 0x7; + u8 channel = (offset + 7) & 0x7; m_stereo_image[channel] = data & 0x7; refresh_stereo_image(channel); } @@ -410,8 +439,8 @@ WRITE32_MEMBER( acorn_vidc10_device::sound_frequency_w ) // MEMC comms //************************************************************************** -void acorn_vidc10_device::write_dac(uint8_t channel, uint8_t data) -{ +void acorn_vidc10_device::write_dac(u8 channel, u8 data) +{ int16_t res; res = m_ulaw_lookup[data]; m_dac[channel & 7]->write(res); @@ -424,7 +453,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 /= 8.0; + sndhz /= m_sound_internal_divider; 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); } @@ -436,9 +465,9 @@ void acorn_vidc10_device::refresh_sound_frequency() // Screen Update / VBlank / HBlank //************************************************************************** -void acorn_vidc10_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, uint8_t bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor) +void acorn_vidc10_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, u8 bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor) { - const u16 pen_base = (bpp == 3 ? 0 : 0x100) + (is_cursor == true ? 0x10 : 0); + const u16 pen_base = (bpp == 3 ? 0 : m_pal_4bpp_base) + (is_cursor == true ? m_pal_cursor_base : 0); const u16 pen_masks[4] = { 1, 3, 0xf, 0xff }; const u16 pen_mask = pen_masks[bpp]; const u16 xchar_size = 1 << (3 - bpp); @@ -476,14 +505,13 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm int xstart,ystart,xend,yend; int xsize,ysize; int calc_dxs = 0,calc_dxe = 0; - const uint8_t x_step[4] = { 19, 11, 7, 5 }; /* border color */ - bitmap.fill(pen(0x110), cliprect); + bitmap.fill(pen(m_pal_border_base), cliprect); /* define X display area through BPP mode register */ - calc_dxs = (m_crtc_regs[CRTC_HDSR]*2)+x_step[m_bpp_mode & 3]; - calc_dxe = (m_crtc_regs[CRTC_HDER]*2)+x_step[m_bpp_mode & 3]; + calc_dxs = m_crtc_regs[CRTC_HDSR]; + calc_dxe = m_crtc_regs[CRTC_HDER]; /* now calculate display clip rectangle start/end areas */ xstart = (calc_dxs)-m_crtc_regs[CRTC_HBSR]; @@ -501,7 +529,7 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm if (xsize <= 0 || ysize <= 0) return 0; - draw(bitmap, cliprect, m_data_vram, m_bpp_mode, xstart, ystart, xsize, ysize, false); + draw(bitmap, cliprect, m_data_vram.get(), m_bpp_mode, xstart, ystart, xsize, ysize, false); if (m_cursor_enable == true) { xstart = m_crtc_regs[CRTC_HCSR] - m_crtc_regs[CRTC_HBSR]; @@ -509,7 +537,7 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm xsize = 32; ysize = m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR]; if (ysize > 0) - draw(bitmap, cliprect, m_cursor_vram, 1, xstart, ystart, xsize, ysize, true); + draw(bitmap, cliprect, m_cursor_vram.get(), 1, xstart, ystart, xsize, ysize, true); } return 0; @@ -518,6 +546,232 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm READ_LINE_MEMBER(acorn_vidc10_device::flyback_r ) { int vert_pos = screen().vpos(); - bool flyback = (vert_pos <= m_crtc_regs[CRTC_VDSR] || vert_pos >= m_crtc_regs[CRTC_VDER]); - return flyback; + if (vert_pos <= m_crtc_regs[CRTC_VDSR] * (m_crtc_interlace+1)) + return true; + + if (vert_pos >= m_crtc_regs[CRTC_VDER] * (m_crtc_interlace+1)) + return true; + + return false; +} + +// VIDC20 + +void arm_vidc20_device::regs_map(address_map &map) +{ + map(0x00, 0x0f).w(FUNC(arm_vidc20_device::vidc20_pal_data_display_w)); + 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(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)); + map(0xe0, 0xef).w(FUNC(arm_vidc20_device::vidc20_control_w)); +} + +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) +{ + 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; + m_pal_cursor_base = 0x100; + m_pal_border_base = 0x100; +} + + +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 } + +void arm_vidc20_device::device_config_complete() +{ + if (!has_screen()) + return; + + if (!screen().refresh_attoseconds()) + screen().set_raw(clock() * 2 / 3, 1024,0,735, 624/2,0,292); // RiscOS 3 default screen settings + + if (!screen().has_screen_update()) + screen().set_screen_update(*this, FUNC(arm_vidc20_device::screen_update)); +} + +u32 arm_vidc20_device::palette_entries() const +{ + return 0x100+4; // 8bpp + 2bpp for cursor +} + +void arm_vidc20_device::device_start() +{ + acorn_vidc10_device::device_start(); + + save_item(NAME(m_vco_r_modulo)); + save_item(NAME(m_vco_v_modulo)); + save_item(NAME(m_pal_data_index)); + save_item(NAME(m_dac_serial_mode)); + save_item(NAME(m_pixel_source)); + save_item(NAME(m_pixel_rate)); +} + +void arm_vidc20_device::device_reset() +{ + acorn_vidc10_device::device_reset(); + + // TODO: sensible defaults + m_vco_r_modulo = 1; + m_vco_v_modulo = 1; +} + +void arm_vidc20_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + acorn_vidc10_device::device_timer(timer, id, param, ptr); +} + +inline void arm_vidc20_device::update_8bpp_palette(u16 index, u32 paldata) +{ + int r,g,b; + + // TODO: ext hookup, supremacy plus other stuff according to the manual +// ext = (paldata & 0x0f000000) >> 24; + b = (paldata & 0x00ff0000) >> 16; + g = (paldata & 0x0000ff00) >> 8; + r = (paldata & 0x000000ff) >> 0; + + set_pen_color(index, r, g, b ); + screen().update_partial(screen().vpos()); +} + +WRITE32_MEMBER(arm_vidc20_device::vidc20_pal_data_display_w) +{ + u8 ext_data = offset & 0xf; + update_8bpp_palette(m_pal_data_index, (ext_data<<24) | data); + m_pal_data_index ++; + m_pal_data_index &= 0xff; +} + +WRITE32_MEMBER( arm_vidc20_device::vidc20_pal_data_index_w ) +{ + m_pal_data_index = data & 0xff; +} + +WRITE32_MEMBER( arm_vidc20_device::vidc20_pal_data_cursor_w ) +{ + u8 ext_data = offset & 0xf; + u8 cursor_pal_index = (offset >> 4) & 3; + update_8bpp_palette(m_pal_cursor_base + cursor_pal_index, (ext_data<<24) | data); +} + +u32 arm_vidc20_device::get_pixel_clock() +{ + // RCLK source: passes thru a r-modulus and a phase frequency (PCOMP), the full story is interesting if you're into maths. + // TODO: for now we just multiply source clock by 2, enough for ssfindo.cpp games. + //printf("%d %02x %02x %d %d\n",this->clock(), 1 << m_pixel_rate, m_pixel_source, m_vco_v_modulo, m_vco_r_modulo); + if (m_pixel_source == 2) // RCLK + return (this->clock() << 1) >> m_pixel_rate; + + // VCLK source is just an external connection + // TODO: get clock from outside world, understand how the modulos are really used, + // understand if SW do some VCO testing before setting CRTC params, + // if there isn't a monitor ID mechanism that copes with this + if (m_pixel_source == 0) // VCLK + return (25175000); + + throw emu_fatalerror("%s unhandled pixel source %02x selected",this->tag(), m_pixel_source); +} + +WRITE32_MEMBER(arm_vidc20_device::vidc20_crtc_w) +{ + if (offset & 0x8) + throw emu_fatalerror("%s accessing CRTC test register %02x, please call the ambulance",this->tag(),offset+0x80); + + const u8 crtc_offset = (offset & 0x7) | ((offset & 0x10) >> 1); + + switch(crtc_offset) + { + case CRTC_HCR: m_crtc_regs[CRTC_HCR] = (data&0x7ffc) + 8; break; + case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data&0x7ffe) + 8; break; + case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = (data&0x7ffe) + 12; break; + case CRTC_HDSR: m_crtc_regs[CRTC_HDSR] = (data&0x7ffe) + 18; break; + case CRTC_HDER: m_crtc_regs[CRTC_HDER] = (data&0x7ffe) + 18; break; + case CRTC_HBER: m_crtc_regs[CRTC_HBER] = (data&0x7ffe) + 12; break; + case CRTC_HCSR: m_crtc_regs[CRTC_HCSR] = (data&0x7fff) + 17; return; +// case CRTC_HIR: + case CRTC_VCR: m_crtc_regs[CRTC_VCR] = (data&0x3fff) + 2; break; + case CRTC_VSWR: m_crtc_regs[CRTC_VSWR] = (data&0x3fff) + 1; break; + case CRTC_VBSR: m_crtc_regs[CRTC_VBSR] = (data&0x3fff) + 1; break; + case CRTC_VDSR: m_crtc_regs[CRTC_VDSR] = (data&0x3fff) + 1; break; + case CRTC_VDER: + m_crtc_regs[CRTC_VDER] = (data&0x3fff) + 1; + screen_vblank_line_update(); + break; + case CRTC_VBER: m_crtc_regs[CRTC_VBER] = (data&0x3fff) + 1; break; + // TODO: bits 15-14 specific for duplex LCD mode + case CRTC_VCSR: + m_crtc_regs[CRTC_VCSR] = (data&0x3fff) + 1; + return; + case CRTC_VCER: m_crtc_regs[CRTC_VCER] = (data&0x3fff) + 1; return; + } + + screen_dynamic_res_change(); +} + +WRITE32_MEMBER( arm_vidc20_device::fsynreg_w ) +{ + m_vco_r_modulo = data & 0x3f; + m_vco_v_modulo = (data >> 8) & 0x3f; + // bits 15-14 and 7-6 are test bits + + screen_dynamic_res_change(); +} + +WRITE32_MEMBER( arm_vidc20_device::vidc20_control_w ) +{ + // ---- --00: VCLK + // ---- --01: HCLK + // ---- --10: RCLK ("recommended" 24 MHz) + // ---- --11: undefined, prolly same as RCLK + m_pixel_source = data & 3; + m_pixel_rate = (data & 0x1c) >> 2; + // (data & 0x700) >> 8 FIFO load + // BIT(data, 13) enables Duplex LCD mode + // BIT(data, 14) power down + // (data & 0xf0000) >> 16 test mode + m_bpp_mode = (data & 0xe0) >> 5; + m_crtc_interlace = BIT(data, 12); + + screen_vblank_line_update(); + screen_dynamic_res_change(); +} + +WRITE32_MEMBER( arm_vidc20_device::vidc20_sound_control_w ) +{ + // TODO: VIDC10 mode, ext clock bit 0 + m_dac_serial_mode = BIT(data, 1); +} + +WRITE32_MEMBER( arm_vidc20_device::vidc20_sound_frequency_w ) +{ + m_sound_frequency_latch = data & 0xff; + if (m_sound_mode == true) + refresh_sound_frequency(); +} + +void arm_vidc20_device::write_dac32(u8 channel, u16 data) +{ + m_dac[channel & 1]->write(data); +} + +bool arm_vidc20_device::get_dac_mode() +{ + return m_dac_serial_mode; +} + +u32 arm_vidc20_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + // TODO: support for true color modes + return acorn_vidc10_device::screen_update(screen, bitmap, cliprect); +} + + |