Rewritten Acorn VIDC10 into own device file [Angelo Salese] #5671

* Improved raster effects on games that dynamically change palette on active frame;
* Added stereo sound support;
This commit is contained in:
Angelo Salese 2019-09-20 15:38:24 +02:00 committed by GitHub
parent 8ef0656299
commit 3e6b9f9756
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 995 additions and 881 deletions

View File

@ -1638,9 +1638,9 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK but abuses of raster effects on menus, has trainer -->
<software name="jksquash" supported="no">
<description>Jahangir Khan Squash</description>
<!-- boot OK, raster effect bug on title screen, long loading screen with black afterwards?, entering player name has stuck keys, has trainer -->
<software name="jksquash" supported="partial">
<description>Jahangir Khan's World Championship Squash</description>
<year>1991</year>
<publisher>Krisalis</publisher>
<part name="flop1" interface="floppy_3_5">
@ -1821,7 +1821,7 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- Mouse cursor autocenters too much especially on A5000 class machine, raster effect is off on gameplay screen -->
<!-- Mouse cursor autocenters too much especially on A5000 class machine, raster effect bug on gameplay screen -->
<software name="lemmings2" supported="partial">
<description>Lemmings 2: The Tribes</description>
<year>1994</year>
@ -1853,7 +1853,7 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK, has raster effect bugs on gameplay -->
<!-- boot OK, has raster effect bugs on gameplay (2p is even worse), sometimes inputs forgets being hit -->
<software name="lotustc2" supported="partial">
<description>Lotus Turbo Challenge 2</description>
<year>1992</year>
@ -1952,7 +1952,7 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK, incorrectly trips raster effect on top of screen -->
<!-- boot OK, raster effect scroll & color bugs during gameplay, has CPU/RAM detection display after title screen -->
<software name="manchutd" supported="partial">
<description>Manchester United Europe</description>
<year>1991</year>
@ -2044,7 +2044,7 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK, has raster effect issues -->
<!-- boot OK, has raster effect bugs on title/gameplay -->
<software name="nebulus" supported="partial">
<description>Nebulus</description>
<year>1992</year>
@ -2443,7 +2443,7 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK but flickers like mad due of incorrect raster effects -->
<!-- boot OK but flickers like mad due of incorrect raster effects, also seems very slow with timing on gameplay even on A5000 class machine -->
<software name="rotoros3" cloneof="rotor" supported="no">
<description>Rotor (Patched RiscOS3)</description>
<year>1989</year>
@ -2565,7 +2565,7 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK, initial speech pitch sounds very low but it's likely a btanb -->
<!-- boot OK, initial speech pitch sounds very low (btanb) -->
<software name="small" supported="yes">
<description>Small</description>
<year>1993</year>
@ -2954,8 +2954,8 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK, has incorrectly emulated raster effect when dying with the fan -->
<software name="wimpgame" supported="partial">
<!-- boot OK, has ZX Spectrum like raster effect when dying with the fan -->
<software name="wimpgame" supported="yes">
<description>The Wimp Game</description>
<year>1990</year>
<publisher>Fourth Dimension</publisher>
@ -2967,8 +2967,8 @@ Zelanites: The Onslaught by Micro Power (RiscOS2)
</part>
</software>
<!-- boot OK, has incorrectly emulated raster effect when dying with the fan -->
<software name="wimpgamec" cloneof="wimpgame" supported="partial">
<!-- boot OK, has ZX Spectrum like raster effect when dying with the fan -->
<software name="wimpgamec" cloneof="wimpgame" supported="yes">
<description>The Wimp Game [cracked]</description>
<year>1990</year>
<publisher>Fourth Dimension</publisher>

View File

@ -4162,3 +4162,14 @@ if (MACHINES["VRENDER0"]~=null) then
}
end
--------------------------------------------------
--
--@src/devices/machine/acorn_vidc.h,MACHINES["ACORN_VIDC10"] = true
--------------------------------------------------
if (MACHINES["ACORN_VIDC10"]~=null) then
files {
MAME_DIR .. "src/devices/machine/acorn_vidc.cpp",
MAME_DIR .. "src/devices/machine/acorn_vidc.h",
}
end

View File

@ -982,7 +982,6 @@ files {
MAME_DIR .. "src/mame/drivers/aristmk5.cpp",
MAME_DIR .. "src/mame/machine/archimds.cpp",
MAME_DIR .. "src/mame/includes/archimds.h",
MAME_DIR .. "src/mame/video/archimds.cpp",
}
createMAMEProjects(_target, _subtarget, "adp")

View File

@ -1347,7 +1347,6 @@ if (_subtarget=="mess") then
createMESSProjects(_target, _subtarget, "mameshared")
files {
MAME_DIR .. "src/mame/machine/archimds.cpp",
MAME_DIR .. "src/mame/video/archimds.cpp",
MAME_DIR .. "src/mame/machine/amiga.cpp",
MAME_DIR .. "src/mame/video/amiga.cpp",
MAME_DIR .. "src/mame/video/amigaaga.cpp",

View File

@ -0,0 +1,518 @@
// license:LGPL-2.1+
// copyright-holders:Angelo Salese, R. Belmont, Juergen Buchmueller
/**********************************************************************************************
Acorn VIDC10 (VIDeo Controller) device chip
based off legacy AA VIDC implementation by Angelo Salese, R. Belmont, Juergen Buchmueller
TODO:
- subclass screen_device, derive h/vsync signals out there;
- improve timings for raster effects:
* 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);
- Are CRTC values correct? VGA modes have a +1 in display line;
**********************************************************************************************/
#include "emu.h"
#include "acorn_vidc.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// 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")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// acorn_vidc10_device - constructor
//-------------------------------------------------
void acorn_vidc10_device::regs_map(address_map &map)
{
map(0x00, 0x3f).w(FUNC(acorn_vidc10_device::pal_data_display_w));
map(0x40, 0x4f).w(FUNC(acorn_vidc10_device::pal_data_cursor_w));
map(0x60, 0x7f).w(FUNC(acorn_vidc10_device::stereo_image_w));
map(0x80, 0xbf).w(FUNC(acorn_vidc10_device::crtc_w));
map(0xc0, 0xc3).w(FUNC(acorn_vidc10_device::sound_frequency_w));
map(0xe0, 0xe3).w(FUNC(acorn_vidc10_device::control_w));
}
acorn_vidc10_device::acorn_vidc10_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_memory_interface(mconfig, *this)
, device_video_interface(mconfig, *this)
, m_screen(*this, "screen")
, m_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_device::regs_map), this))
, m_palette(*this, "palette")
, m_lspeaker(*this, "lspeaker")
, m_rspeaker(*this, "rspeaker")
, m_dac(*this, "dac%u", 0)
, m_vblank_cb(*this)
, m_sound_drq_cb(*this)
{
}
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)
{
}
acorn_vidc10_lcd_device::acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: acorn_vidc10_device(mconfig, ACORN_VIDC10_LCD, tag, owner, clock)
{
}
device_memory_interface::space_config_vector acorn_vidc10_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_IO, &m_space_config)
};
}
//-------------------------------------------------
// device_add_mconfig - device-specific machine
// configuration addiitons
//-------------------------------------------------
void acorn_vidc10_device::device_add_mconfig(machine_config &config)
{
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(XTAL(16'000'000), 1024,0,735, 624/2,0,292); // RiscOS 3 default screen settings
m_screen->set_screen_update(FUNC(acorn_vidc10_device::screen_update));
// m_screen->screen_vblank().set(FUNC(acorn_vidc10_device::screen_vblank));
// 8bpp + 1/2/4bpp + 2bpp for cursor
PALETTE(config, m_palette, palette_device::BLACK).set_entries(0x100+0x10+4);
SPEAKER(config, m_lspeaker).front_left();
SPEAKER(config, m_rspeaker).front_right();
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
for (int i = 0; i < m_sound_max_channels; i++)
{
// custom DAC
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[i], 0).add_route(0, m_lspeaker, m_sound_input_gain).add_route(0, m_rspeaker, m_sound_input_gain);
vref.add_route(0, m_dac[i], 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, m_dac[i], -1.0, DAC_VREF_NEG_INPUT);
}
}
void acorn_vidc10_lcd_device::device_add_mconfig(machine_config &config)
{
acorn_vidc10_device::device_add_mconfig(config);
m_screen->set_type(SCREEN_TYPE_LCD);
// TODO: verify !Configure with automatic type detection, there must be an ID telling this is a LCD machine.
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void acorn_vidc10_device::device_start()
{
m_vblank_cb.resolve_safe();
m_sound_drq_cb.resolve_safe();
save_item(NAME(m_bpp_mode));
save_item(NAME(m_crtc_interlace));
save_item(NAME(m_pixel_clock));
save_item(NAME(m_sound_frequency_latch));
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_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);
m_video_timer = timer_alloc(TIMER_VIDEO);
m_sound_timer = timer_alloc(TIMER_SOUND);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
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);
m_video_timer->adjust(attotime::never);
m_sound_timer->adjust(attotime::never);
}
//-------------------------------------------------
// device_timer - device-specific timer
//-------------------------------------------------
void acorn_vidc10_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case TIMER_VIDEO:
m_vblank_cb(ASSERT_LINE);
screen_vblank_line_update();
break;
case TIMER_SOUND:
m_sound_drq_cb(ASSERT_LINE);
break;
}
}
//**************************************************************************
// CRTC section
//**************************************************************************
inline void acorn_vidc10_device::screen_vblank_line_update()
{
int vline = (m_crtc_regs[CRTC_VDER]) * (m_crtc_interlace + 1);
m_video_timer->adjust((vline > 2) ? m_screen->time_until_pos(vline) : attotime::never);
}
void acorn_vidc10_device::screen_dynamic_res_change()
{
const int32_t pixel_rate[4] = { 8000000, 12000000, 16000000, 24000000};
// sanity checks
if (m_crtc_regs[CRTC_HCR] <= 1 || m_crtc_regs[CRTC_VCR] <= 1)
return;
if (m_crtc_regs[CRTC_HBER] <= 1 || m_crtc_regs[CRTC_VBER] <= 1)
return;
// total cycles >= border end >= border start
if (m_crtc_regs[CRTC_HCR] < m_crtc_regs[CRTC_HBER])
return;
if (m_crtc_regs[CRTC_HBER] < m_crtc_regs[CRTC_HBSR])
return;
if (m_crtc_regs[CRTC_VBER] < m_crtc_regs[CRTC_VBSR])
return;
rectangle const visarea(
0, m_crtc_regs[CRTC_HBER] - m_crtc_regs[CRTC_HBSR] - 1,
0, (m_crtc_regs[CRTC_VBER] - m_crtc_regs[CRTC_VBSR]) * (m_crtc_interlace + 1));
#if 0
// TODO: move to debugger custom command
const int m_vidc_vblank_time = m_crtc_regs[CRTC_VDER] * (m_crtc_interlace+1);
printf("Configuring: htotal %d vtotal %d border %d x %d display origin %d x %d vblank = %d\n",
m_crtc_regs[CRTC_HCR], m_crtc_regs[CRTC_VCR],
visarea.right(), visarea.bottom(),
m_crtc_regs[CRTC_HDER]-m_crtc_regs[CRTC_HDSR],m_crtc_regs[CRTC_VDER]-m_crtc_regs[CRTC_VDSR]+1,
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];
m_screen->configure(m_crtc_regs[CRTC_HCR], m_crtc_regs[CRTC_VCR] * (m_crtc_interlace+1), visarea, refresh);
}
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
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;
this->space(AS_IO).write_dword(reg, val);
}
inline void acorn_vidc10_device::update_4bpp_palette(uint16_t index, uint32_t paldata)
{
int r,g,b;
// TODO: for TV Tuner we need to output this, also check if cursor mode actually sets this up for offset = 0
// i = (paldata & 0x1000) >> 12; //supremacy bit
b = (paldata & 0x0f00) >> 8;
g = (paldata & 0x00f0) >> 4;
r = (paldata & 0x000f) >> 0;
m_palette->set_pen_color(index, pal4bit(r), pal4bit(g), pal4bit(b) );
m_screen->update_partial(m_screen->vpos());
}
WRITE32_MEMBER( acorn_vidc10_device::pal_data_display_w )
{
update_4bpp_palette(offset+0x100, data);
//printf("%02x: %01x %01x %01x [%d]\n",offset,r,g,b,m_screen->vpos());
// 8bpp
for(int idx=0;idx<0x100;idx+=0x10)
{
int b = ((data & 0x700) >> 8) | ((idx & 0x80) >> 4);
int g = ((data & 0x030) >> 4) | ((idx & 0x60) >> 3);
int r = ((data & 0x007) >> 0) | ((idx & 0x10) >> 1);
m_palette->set_pen_color(offset + idx, pal4bit(r), pal4bit(g), pal4bit(b) );
}
}
WRITE32_MEMBER( acorn_vidc10_device::pal_data_cursor_w )
{
update_4bpp_palette(offset+0x110, data);
}
WRITE32_MEMBER( acorn_vidc10_device::control_w )
{
// TODO: not sure what the commented out bits do
m_pixel_clock = (data & 0x03);
m_bpp_mode = ((data & 0x0c) >> 2);
//m_dma_request_mode = ((data & 0x30) >> 4);
m_crtc_interlace = ((data & 0x40) >> 6);
//m_composite_sync = BIT(data, 7);
//m_test_mode = (data & 0xc100) != 0xc100;
//todo: vga/svga modes sets 0x1000?
screen_vblank_line_update();
screen_dynamic_res_change();
}
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_HCSR: m_crtc_regs[CRTC_HCSR] = ((data >> 13) & 0x7ff) + 6; return;
// case CRTC_HIR: // ...
case CRTC_VCR: m_crtc_regs[CRTC_VCR] = (data >> 14)+1; break;
case CRTC_VSWR: m_crtc_regs[CRTC_VSWR] = (data >> 14)+1; break;
case CRTC_VBSR:
m_crtc_regs[CRTC_VBSR] = (data >> 14)+1;
break;
case CRTC_VDSR:
m_crtc_regs[CRTC_VDSR] = (data >> 14)+1;
break;
case CRTC_VDER:
m_crtc_regs[CRTC_VDER] = (data >> 14)+1;
screen_vblank_line_update();
break;
case CRTC_VBER:
m_crtc_regs[CRTC_VBER] = (data >> 14)+1;
break;
case CRTC_VCSR: m_crtc_regs[CRTC_VCSR] = ((data >> 14) & 0x3ff) + 1; return;
case CRTC_VCER: m_crtc_regs[CRTC_VCER] = ((data >> 14) & 0x3ff) + 1; return;
}
screen_dynamic_res_change();
}
inline void acorn_vidc10_device::refresh_stereo_image(uint8_t channel)
{
/*
-111 full right
-110 83% right, 17% left
-101 67% right, 33% left
-100 center
-011 67% left, 33% right
-010 83% left, 17% right
-001 full left
-000 "undefined" TODO: verify what it actually means
*/
const float left_gain[8] = { 1.0, 2.0, 1.66, 1.34, 1.0, 0.66, 0.34, 0.0 };
const float right_gain[8] = { 1.0, 0.0, 0.34, 0.66, 1.0, 1.34, 1.66, 2.0 };
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_gain(channel),m_rspeaker->input_gain(channel));
}
WRITE32_MEMBER( acorn_vidc10_device::stereo_image_w )
{
uint8_t channel = (offset + 7) & 0x7;
m_stereo_image[channel] = data & 0x7;
refresh_stereo_image(channel);
}
WRITE32_MEMBER( acorn_vidc10_device::sound_frequency_w )
{
m_sound_frequency_test_bit = BIT(data, 8);
m_sound_frequency_latch = data & 0xff;
if (m_sound_mode == true)
refresh_sound_frequency();
}
//**************************************************************************
// MEMC comms
//**************************************************************************
void acorn_vidc10_device::write_dac(uint8_t channel, uint8_t data)
{
uint8_t ulaw_comp;
int16_t res;
const int16_t mulawTable[256] =
{
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
-11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
-1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
-876, -844, -812, -780, -748, -716, -684, -652,
-620, -588, -556, -524, -492, -460, -428, -396,
-372, -356, -340, -324, -308, -292, -276, -260,
-244, -228, -212, -196, -180, -164, -148, -132,
-120, -112, -104, -96, -88, -80, -72, -64,
-56, -48, -40, -32, -24, -16, -8, -1,
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
876, 844, 812, 780, 748, 716, 684, 652,
620, 588, 556, 524, 492, 460, 428, 396,
372, 356, 340, 324, 308, 292, 276, 260,
244, 228, 212, 196, 180, 164, 148, 132,
120, 112, 104, 96, 88, 80, 72, 64,
56, 48, 40, 32, 24, 16, 8, 0
};
uint8_t ulaw_temp = data ^ 0xff;
ulaw_comp = (ulaw_temp>>1) | ((ulaw_temp&1)<<7);
res = mulawTable[ulaw_comp];
m_dac[channel & 7]->write(res);
}
void acorn_vidc10_device::refresh_sound_frequency()
{
// TODO: check against test bit (reloads sound frequency if 0)
if (m_sound_mode == true)
{
// TODO: Range is between 3 and 256 usecs
double sndhz = 1e6 / ((m_sound_frequency_latch & 0xff) + 2);
sndhz /= 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);
}
else
m_sound_timer->adjust(attotime::never);
}
//**************************************************************************
// 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)
{
const u16 pen_base = (bpp == 3 ? 0 : 0x100) + (is_cursor == true ? 0x10 : 0);
const u16 pen_masks[4] = { 1, 3, 0xf, 0xff };
const u16 pen_mask = pen_masks[bpp];
const u16 xchar_size = 1 << (3 - bpp);
const u8 pen_byte_sizes[4] = { 1, 2, 4, 1 };
const u16 pen_byte_size = pen_byte_sizes[bpp];
const int raster_ystart = std::max(0, cliprect.min_y-ystart);
xsize >>= 3-bpp;
//printf("%d %d %d %d\n",ystart, ysize, cliprect.min_y, cliprect.max_y);
for (int srcy = raster_ystart; srcy<ysize; srcy++)
{
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++)
{
u16 dot = ((pen>>(xi*pen_byte_size)) & pen_mask);
if (is_cursor == true && dot == 0)
continue;
dot += pen_base;
bitmap.pix32(dsty, dstx+xi) = m_palette->pen(dot);
if (m_crtc_interlace)
bitmap.pix32(dsty+1, dstx+xi) = m_palette->pen(dot);
}
}
}
}
u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
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(m_palette->pen(0x110), 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];
/* now calculate display clip rectangle start/end areas */
xstart = (calc_dxs)-m_crtc_regs[CRTC_HBSR];
ystart = (m_crtc_regs[CRTC_VDSR]-m_crtc_regs[CRTC_VBSR]);
xend = (calc_dxe)+xstart;
yend = (m_crtc_regs[CRTC_VDER] * (m_crtc_interlace+1))+ystart;
/* disable the screen if display params are invalid */
if(xstart > xend || ystart > yend)
return 0;
xsize = calc_dxe-calc_dxs;
ysize = m_crtc_regs[CRTC_VDER]-m_crtc_regs[CRTC_VDSR];
if (xsize <= 0 || ysize <= 0)
return 0;
draw(bitmap, cliprect, m_data_vram, m_bpp_mode, xstart, ystart, xsize, ysize, false);
if (m_cursor_enable == true)
{
xstart = m_crtc_regs[CRTC_HCSR] - m_crtc_regs[CRTC_HBSR];
ystart = m_crtc_regs[CRTC_VCSR] - m_crtc_regs[CRTC_VBSR];
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);
}
return 0;
}
READ_LINE_MEMBER(acorn_vidc10_device::flyback_r )
{
int vert_pos = m_screen->vpos();
bool flyback = (vert_pos <= m_crtc_regs[CRTC_VDSR] || vert_pos >= m_crtc_regs[CRTC_VDER]);
return flyback;
}

View File

@ -0,0 +1,145 @@
// license:LGPL-2.1+
// copyright-holders:Angelo Salese, R. Belmont, Juergen Buchmueller
/***************************************************************************
Acorn VIDC10 (VIDeo Controller) device chip
***************************************************************************/
#ifndef MAME_MACHINE_ACORN_VIDC_H
#define MAME_MACHINE_ACORN_VIDC_H
#pragma once
#include "screen.h"
#include "speaker.h"
#include "emupal.h"
#include "sound/dac.h"
#include "sound/volt_reg.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> acorn_vidc10_device
class acorn_vidc10_device : public device_t,
public device_memory_interface,
public device_video_interface
{
public:
// construction/destruction
acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// I/O operations
DECLARE_WRITE32_MEMBER( write );
DECLARE_READ_LINE_MEMBER( flyback_r );
auto vblank() { return m_vblank_cb.bind(); }
auto sound_drq() { return m_sound_drq_cb.bind(); }
// MEMC comms
void write_vram(uint32_t offset, uint8_t data) { m_data_vram[offset & (m_data_vram_mask)] = data; }
void write_cram(uint32_t offset, uint8_t data) { m_cursor_vram[offset & (m_cursor_vram_mask)] = data; }
void write_dac(uint8_t channel, uint8_t data);
void clear_dac(uint8_t channel) { m_dac[channel & 7]->write(0); }
void update_sound_mode(bool state) { m_sound_mode = state; refresh_sound_frequency(); }
void set_cursor_enable(bool state) { m_cursor_enable = state; }
uint32_t get_cursor_size() { return (m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR]) * (32/4); }
protected:
acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
//virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual space_config_vector memory_space_config() const override;
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
required_device<screen_device> m_screen;
private:
const address_space_config m_space_config;
void regs_map(address_map &map);
required_device<palette_device> m_palette;
required_device<speaker_device> m_lspeaker;
required_device<speaker_device> m_rspeaker;
required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
devcb_write_line m_vblank_cb;
devcb_write_line m_sound_drq_cb;
DECLARE_WRITE32_MEMBER( pal_data_display_w );
DECLARE_WRITE32_MEMBER( pal_data_cursor_w );
DECLARE_WRITE32_MEMBER( stereo_image_w );
DECLARE_WRITE32_MEMBER( crtc_w );
DECLARE_WRITE32_MEMBER( sound_frequency_w );
DECLARE_WRITE32_MEMBER( control_w );
uint8_t m_pixel_clock, m_bpp_mode, m_crtc_interlace;
//bool m_flyback;
enum {
TIMER_VIDEO = 1,
TIMER_SOUND = 2
};
emu_timer *m_video_timer;
emu_timer *m_sound_timer;
inline void screen_vblank_line_update();
void screen_dynamic_res_change();
enum {
CRTC_HCR = 0, CRTC_HSWR, CRTC_HBSR, CRTC_HDSR, CRTC_HDER, CRTC_HBER, CRTC_HCSR, CRTC_HIR,
CRTC_VCR, CRTC_VSWR, CRTC_VBSR, CRTC_VDSR, CRTC_VDER, CRTC_VBER, CRTC_VCSR, CRTC_VCER
};
uint32_t m_crtc_regs[16];
u8 *m_data_vram;
u8 *m_cursor_vram;
// TODO: correct data vram size
const u32 m_data_vram_mask = 0x1fffff;
const u32 m_cursor_vram_mask = 0x7fff;
const u32 m_data_vram_size = m_data_vram_mask+1;
const u32 m_cursor_vram_size = m_cursor_vram_mask+1;
bool m_cursor_enable;
void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, uint8_t bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor);
inline void update_4bpp_palette(uint16_t index, uint32_t paldata);
u8 m_sound_frequency_latch;
bool m_sound_frequency_test_bit;
bool m_sound_mode;
u8 m_stereo_image[8];
const float m_sound_input_gain = 0.05;
const int m_sound_max_channels = 8;
void refresh_sound_frequency();
inline void refresh_stereo_image(uint8_t channel);
};
class acorn_vidc10_lcd_device : public acorn_vidc10_device
{
public:
// construction/destruction
acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual void device_add_mconfig(machine_config &config) override;
};
// device type definition
DECLARE_DEVICE_TYPE(ACORN_VIDC10, acorn_vidc10_device)
DECLARE_DEVICE_TYPE(ACORN_VIDC10_LCD, acorn_vidc10_lcd_device)
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
#endif // MAME_MACHINE_ACORN_VIDC10_H

View File

@ -198,7 +198,7 @@ void aa310_state::aa310_mem(address_map &map)
map(0x00000000, 0x01ffffff).rw(FUNC(aa310_state::archimedes_memc_logical_r), FUNC(aa310_state::archimedes_memc_logical_w));
map(0x02000000, 0x02ffffff).ram().share("physicalram"); /* physical RAM - 16 MB for now, should be 512k for the A310 */
map(0x03000000, 0x033fffff).rw(FUNC(aa310_state::archimedes_ioc_r), FUNC(aa310_state::archimedes_ioc_w));
map(0x03400000, 0x035fffff).rom().region("extension", 0x000000).w(FUNC(aa310_state::archimedes_vidc_w));
map(0x03400000, 0x035fffff).rom().region("extension", 0x000000).w(m_vidc, FUNC(acorn_vidc10_device::write));
map(0x03600000, 0x037fffff).rom().region("extension", 0x200000).w(FUNC(aa310_state::archimedes_memc_w));
map(0x03800000, 0x03ffffff).rom().region("maincpu", 0).w(FUNC(aa310_state::archimedes_memc_page_w));
}
@ -428,12 +428,9 @@ void aa310_state::aa310(machine_config &config)
I2CMEM(config, "i2cmem", 0).set_data_size(0x100);
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(16_MHz_XTAL, 1024, 0, 735, 624/2, 0, 292); // RiscOS 3 default screen settings
m_screen->set_screen_update(FUNC(archimedes_state::screen_update));
PALETTE(config, m_palette).set_entries(32768);
ACORN_VIDC10(config, m_vidc, 0);
m_vidc->vblank().set(FUNC(aa310_state::vblank_irq));
m_vidc->sound_drq().set(FUNC(aa310_state::sound_drq));
RAM(config, m_ram).set_default_size("1M");
@ -448,21 +445,6 @@ void aa310_state::aa310(machine_config &config)
SOFTWARE_LIST(config, "flop_list").set_original("archimedes");
SPEAKER(config, "speaker").front_center();
for (int i = 0; i < 8; i++)
{
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[i], 0).add_route(0, "speaker", 0.1); // unknown DAC
}
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
vref.add_route(0, "dac0", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac0", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac1", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac1", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac2", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac2", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac3", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac3", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac4", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac4", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac5", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac5", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac6", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac6", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac7", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac7", -1.0, DAC_VREF_NEG_INPUT);
/* Expansion slots - 2-card backplane */
}
@ -546,7 +528,9 @@ void aa310_state::aa4(machine_config &config)
m_maincpu->set_clock(24_MHz_XTAL); // ARM3
/* video hardware */
m_screen->set_type(SCREEN_TYPE_LCD);
ACORN_VIDC10_LCD(config.replace(), m_vidc, 0);
m_vidc->vblank().set(FUNC(aa310_state::vblank_irq));
m_vidc->sound_drq().set(FUNC(aa310_state::sound_drq));
/* 765 FDC */
@ -619,7 +603,7 @@ ROM_START( aa305 )
ROMX_LOAD( "0276,148-01.ic26", 0x000002, 0x10000, CRC(1ab02f2d) SHA1(dd7d216967524e64d1a03076a6081461ec8528c3), ROM_BIOS(8) | ROM_SKIP(3) )
ROMX_LOAD( "0276,149-01.ic27", 0x000003, 0x10000, CRC(5fd6a406) SHA1(790af8a4c74d0f6714d528f7502443ce5898a618), ROM_BIOS(8) | ROM_SKIP(3) )
ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
ROM_REGION( 0x400000, "extension", ROMREGION_ERASE00 )
ROM_REGION( 0x100, "i2cmem", ROMREGION_ERASE00 )
@ -663,7 +647,7 @@ ROM_START( aa3000 )
ROM_SYSTEM_BIOS( 5, "319", "RISC OS 3.19 (09 Jun 1993)" ) // Parts 0296,241-01, 0296,242-01, 0296,243-01, 0296,244-01,
ROMX_LOAD( "riscos319.bin", 0x000000, 0x200000, CRC(00c7a3d3) SHA1(be7a8cba5d6c6c0e1c4838712524056cf4b8c8cb), ROM_BIOS(5) )
ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
ROM_REGION( 0x400000, "extension", ROMREGION_ERASE00 )
ROM_REGION( 0x100, "i2cmem", ROMREGION_ERASE00 )
@ -700,7 +684,7 @@ ROM_START( aa5000 )
ROM_SYSTEM_BIOS( 3, "319", "RISC OS 3.19 (09 Jun 1993)" ) // Parts 0296,241-01, 0296,242-01, 0296,243-01, 0296,244-01,
ROMX_LOAD( "riscos319.bin", 0x000000, 0x200000, CRC(00c7a3d3) SHA1(be7a8cba5d6c6c0e1c4838712524056cf4b8c8cb), ROM_BIOS(3) )
ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
ROM_REGION( 0x400000, "extension", ROMREGION_ERASE00 )
ROM_REGION( 0x100, "i2cmem", ROMREGION_ERASE00 )
@ -714,7 +698,7 @@ ROM_START( aa4 )
ROM_LOAD32_WORD( "0296,061-01.ic4", 0x000000, 0x100000, CRC(b77fe215) SHA1(57b19ea4b97a9b6a240aa61211c2c134cb295aa0) )
ROM_LOAD32_WORD( "0296,062-01.ic15", 0x000002, 0x100000, CRC(d42e196e) SHA1(64243d39d1bca38b10761f66a8042c883bde87a4) )
ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
ROM_REGION( 0x400000, "extension", ROMREGION_ERASE00 )
/* Power Management */
ROM_LOAD32_BYTE( "0296,063-01.ic38", 0x000003, 0x010000, CRC(9ca3a6be) SHA1(75905b031f49960605d55c3e7350d309559ed440) )
@ -728,7 +712,7 @@ ROM_START( aa3010 )
ROM_LOAD32_WORD( "0296,061-02.ic17", 0x000000, 0x100000, CRC(552fc3aa) SHA1(b2f1911e53d7377f2e69e1a870139745d3df494b) )
ROM_LOAD32_WORD( "0296,062-02.ic18", 0x000002, 0x100000, CRC(308d5a4a) SHA1(b309e1dd85670a06d77ec504dbbec6c42336329f) )
ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
ROM_REGION( 0x400000, "extension", ROMREGION_ERASE00 )
ROM_REGION( 0x100, "i2cmem", ROMREGION_ERASE00 )

File diff suppressed because it is too large Load Diff

View File

@ -21,13 +21,12 @@
PCB has a single OSC at 24MHz
*******************************************************************************************/
#include "emu.h"
#include "includes/archimds.h"
#include "cpu/arm/arm.h"
#include "machine/aakart.h"
#include "machine/i2cmem.h"
#include "sound/volt_reg.h"
#include "speaker.h"
class ertictac_state : public archimedes_state
@ -73,8 +72,8 @@ void ertictac_state::ertictac_map(address_map &map)
map(0x03000000, 0x033fffff).rw(FUNC(ertictac_state::archimedes_ioc_r), FUNC(ertictac_state::archimedes_ioc_w));
map(0x03340000, 0x0334001f).r(FUNC(ertictac_state::ertictac_podule_r));
map(0x033c0000, 0x033c001f).r(FUNC(ertictac_state::ertictac_podule_r));
map(0x03400000, 0x035fffff).rw(FUNC(ertictac_state::archimedes_vidc_r), FUNC(ertictac_state::archimedes_vidc_w));
map(0x03600000, 0x037fffff).rw(FUNC(ertictac_state::archimedes_memc_r), FUNC(ertictac_state::archimedes_memc_w));
map(0x03400000, 0x035fffff).w(m_vidc, FUNC(acorn_vidc10_device::write));
map(0x03600000, 0x037fffff).w(FUNC(ertictac_state::archimedes_memc_w));
map(0x03800000, 0x03ffffff).rom().region("maincpu", 0).w(FUNC(ertictac_state::archimedes_memc_page_w));
}
@ -233,26 +232,9 @@ void ertictac_state::ertictac(machine_config &config)
// AAKART(config, m_kart, XTAL(24'000'000)/3); // TODO: frequency
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(XTAL(16'000'000), 1024,0,735, 624/2,0,292); // RiscOS 3 default screen settings
m_screen->set_screen_update(FUNC(archimedes_state::screen_update));
PALETTE(config, m_palette).set_entries(0x200);
SPEAKER(config, "speaker").front_center();
for (int i = 0; i < 8; i++)
{
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[i], 0).add_route(0, "speaker", 0.05); // unknown DAC
}
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
vref.add_route(0, "dac0", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac0", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac1", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac1", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac2", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac2", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac3", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac3", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac4", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac4", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac5", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac5", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac6", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac6", -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, "dac7", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "dac7", -1.0, DAC_VREF_NEG_INPUT);
ACORN_VIDC10(config, m_vidc, 0);
m_vidc->vblank().set(FUNC(ertictac_state::vblank_irq));
m_vidc->sound_drq().set(FUNC(ertictac_state::sound_drq));
}
ROM_START( ertictac )
@ -273,8 +255,6 @@ ROM_START( ertictac )
ROM_LOAD32_BYTE( "eroti_ver01_-14-", 0xc0001, 0x10000, CRC(3029567c) SHA1(6d49bea3a3f6f11f4182a602d37b53f1f896c154) )
ROM_LOAD32_BYTE( "eroti_ver01_-15-", 0xc0002, 0x10000, CRC(500997ab) SHA1(028c7b3ca03141e5b596ab1e2ab98d0ccd9bf93a) )
ROM_LOAD32_BYTE( "eroti_ver01_-16-", 0xc0003, 0x10000, CRC(70a8d136) SHA1(50b11f5701ed5b79a5d59c9a3c7d5b7528e66a4d) )
ROM_REGION(0x200000, "vram", ROMREGION_ERASE00)
ROM_END
@ -296,8 +276,6 @@ ROM_START( ertictaca ) /* PCB had sticker printed "092121 EROTICTAC" */
ROM_LOAD32_BYTE( "eroti_ver01_-14-", 0xc0001, 0x10000, CRC(3029567c) SHA1(6d49bea3a3f6f11f4182a602d37b53f1f896c154) )
ROM_LOAD32_BYTE( "eroti_ver01_-15-", 0xc0002, 0x10000, CRC(500997ab) SHA1(028c7b3ca03141e5b596ab1e2ab98d0ccd9bf93a) )
ROM_LOAD32_BYTE( "eroti_ver01_-16-", 0xc0003, 0x10000, CRC(70a8d136) SHA1(50b11f5701ed5b79a5d59c9a3c7d5b7528e66a4d) )
ROM_REGION(0x200000, "vram", ROMREGION_ERASE00)
ROM_END
ROM_START( ertictacb )
@ -318,8 +296,6 @@ ROM_START( ertictacb )
ROM_LOAD32_BYTE( "eroti_ver01_-14-", 0xc0001, 0x10000, CRC(3029567c) SHA1(6d49bea3a3f6f11f4182a602d37b53f1f896c154) )
ROM_LOAD32_BYTE( "eroti_ver01_-15-", 0xc0002, 0x10000, CRC(500997ab) SHA1(028c7b3ca03141e5b596ab1e2ab98d0ccd9bf93a) )
ROM_LOAD32_BYTE( "eroti_ver01_-16-", 0xc0003, 0x10000, CRC(70a8d136) SHA1(50b11f5701ed5b79a5d59c9a3c7d5b7528e66a4d) )
ROM_REGION(0x200000, "vram", ROMREGION_ERASE00)
ROM_END
@ -342,8 +318,6 @@ ROM_START( poizone )
ROM_LOAD32_BYTE( "p_son22.bin", 0x140001, 0x10000, CRC(16f0bb52) SHA1(893ab1e72b84de7a38f88f9d713769968ebd4553) )
ROM_LOAD32_BYTE( "p_son23.bin", 0x140002, 0x10000, CRC(e9c118b2) SHA1(110d9a204e701b9b54d89f027f8892c3f3a819c7) )
ROM_LOAD32_BYTE( "p_son24.bin", 0x140003, 0x10000, CRC(a09d7f55) SHA1(e0d562c655c16034b40db93de801b98b7948beb2) )
ROM_REGION(0x200000, "vram", ROMREGION_ERASE00)
ROM_END
GAME( 1990, ertictac, 0, ertictac, ertictac, ertictac_state, init_ertictac, ROT0, "Sisteme", "Erotictac/Tactic", MACHINE_IMPERFECT_SOUND)

View File

@ -14,9 +14,7 @@
#include "machine/aakart.h"
#include "machine/i2cmem.h"
#include "machine/wd_fdc.h"
#include "sound/dac.h"
#include "emupal.h"
#include "screen.h"
#include "machine/acorn_vidc.h"
// interrupt definitions. these are for the real Archimedes computer - arcade
// and gambling knockoffs likely are a bit different.
@ -53,15 +51,12 @@ public:
m_kart(*this, "kart"),
m_maincpu(*this, "maincpu"),
m_i2cmem(*this, "i2cmem"),
m_vidc(*this, "vidc"),
m_fdc(*this, "fdc"),
m_floppy0(*this, "fdc:0"),
m_floppy1(*this, "fdc:1"),
m_region_maincpu(*this, "maincpu"),
m_region_vram(*this, "vram"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_joy(*this, "joy_p%u",1),
m_dac(*this, { "dac0", "dac1", "dac2", "dac3", "dac4", "dac5", "dac6", "dac7" })
m_joy(*this, "joy_p%u",1)
{ }
optional_device<aakart_device> m_kart;
@ -79,24 +74,16 @@ public:
DECLARE_READ32_MEMBER(aristmk5_drame_memc_logical_r);
DECLARE_READ32_MEMBER(archimedes_memc_logical_r);
DECLARE_WRITE32_MEMBER(archimedes_memc_logical_w);
DECLARE_READ32_MEMBER(archimedes_memc_r);
DECLARE_WRITE32_MEMBER(archimedes_memc_w);
DECLARE_WRITE32_MEMBER(archimedes_memc_page_w);
DECLARE_READ32_MEMBER(archimedes_ioc_r);
DECLARE_WRITE32_MEMBER(archimedes_ioc_w);
DECLARE_READ32_MEMBER(archimedes_vidc_r);
DECLARE_WRITE32_MEMBER(archimedes_vidc_w);
DECLARE_WRITE_LINE_MEMBER( a310_kart_rx_w );
DECLARE_WRITE_LINE_MEMBER( a310_kart_tx_w );
uint8_t m_i2c_clk;
int16_t m_memc_pages[0x2000]; // the logical RAM area is 32 megs, and the smallest page size is 4k
uint32_t m_vidc_regs[256];
uint8_t m_cursor_vram[0x8000]; // size -> max(VCER) - min(VCSR) * 32 = 0x7fe0
uint8_t m_ioc_regs[0x80/4];
uint8_t m_vidc_bpp_mode;
uint8_t m_vidc_interlace;
uint16_t m_vidc_vblank_time;
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
@ -104,29 +91,25 @@ public:
protected:
required_device<arm_cpu_device> m_maincpu;
optional_device<i2cmem_device> m_i2cmem;
required_device<acorn_vidc10_device> m_vidc;
optional_device<wd1772_device> m_fdc;
optional_device<floppy_connector> m_floppy0;
optional_device<floppy_connector> m_floppy1;
required_memory_region m_region_maincpu;
required_memory_region m_region_vram;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
optional_ioport_array<2> m_joy;
required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
DECLARE_WRITE_LINE_MEMBER( vblank_irq );
DECLARE_WRITE_LINE_MEMBER( sound_drq );
private:
static const device_timer_id TIMER_VBLANK = 0;
static const device_timer_id TIMER_VIDEO = 1;
static const device_timer_id TIMER_AUDIO = 2;
static const device_timer_id TIMER_IOC = 3;
void vidc_vblank();
// void vidc_vblank();
void vidc_video_tick();
void vidc_audio_tick();
void ioc_timer(int param);
void vidc_dynamic_res_change();
void latch_timer_cnt(int tmr);
void a310_set_timer(int tmr);
DECLARE_READ32_MEMBER(ioc_ctrl_r);
@ -136,14 +119,11 @@ private:
uint32_t m_memc_pagesize;
int m_memc_latchrom;
uint32_t m_ioc_timercnt[4], m_ioc_timerout[4];
uint32_t m_vidc_vidstart, m_vidc_vidend, m_vidc_vidinit, m_vidc_vidcur,m_vidc_cinit;
uint32_t m_vidc_vidstart, m_vidc_vidend, m_vidc_vidinit, m_vidc_vidcur, m_vidc_cinit;
uint32_t m_vidc_sndstart, m_vidc_sndend, m_vidc_sndcur, m_vidc_sndendcur;
uint8_t m_video_dma_on,m_audio_dma_on;
uint8_t m_vidc_pixel_clk;
uint8_t m_vidc_stereo_reg[8];
bool m_cursor_enabled;
emu_timer *m_timer[4], *m_snd_timer, *m_vid_timer;
emu_timer *m_vbl_timer;
emu_timer *m_timer[4];
uint8_t m_floppy_select;
bool check_floppy_ready();
uint8_t m_joy_serial_data;
@ -185,22 +165,4 @@ private:
#define T3_GO 0x78/4
#define T3_LATCH 0x7c/4
#define VIDC_HCR 0x80
#define VIDC_HSWR 0x84
#define VIDC_HBSR 0x88
#define VIDC_HDSR 0x8c
#define VIDC_HDER 0x90
#define VIDC_HBER 0x94
#define VIDC_HCSR 0x98
#define VIDC_HIR 0x9c
#define VIDC_VCR 0xa0
#define VIDC_VSWR 0xa4
#define VIDC_VBSR 0xa8
#define VIDC_VDSR 0xac
#define VIDC_VDER 0xb0
#define VIDC_VBER 0xb4
#define VIDC_VCSR 0xb8
#define VIDC_VCER 0xbc
#endif // MAME_INCLUDES_ARCHIMEDES_H

View File

@ -34,7 +34,7 @@
#include "debugger.h"
static const int page_sizes[4] = { 4096, 8192, 16384, 32768 };
static const uint32_t pixel_rate[4] = { 8000000, 12000000, 16000000, 24000000};
//static const uint32_t pixel_rate[4] = { 8000000, 12000000, 16000000, 24000000};
#define IOC_LOG 0
#define CRTC_LOG 0
@ -97,30 +97,42 @@ void archimedes_state::device_timer(emu_timer &timer, device_timer_id id, int pa
{
switch (id)
{
case TIMER_VBLANK: vidc_vblank();break;
case TIMER_VIDEO: vidc_video_tick(); break;
case TIMER_AUDIO: vidc_audio_tick(); break;
//case TIMER_VBLANK: vidc_vblank();break;
//case TIMER_VIDEO: vidc_video_tick(); break;
//case TIMER_AUDIO: vidc_audio_tick(); break;
case TIMER_IOC: ioc_timer(param); break;
}
}
void archimedes_state::vidc_vblank()
WRITE_LINE_MEMBER( archimedes_state::vblank_irq )
{
archimedes_request_irq_a(ARCHIMEDES_IRQA_VBL);
if (state)
{
archimedes_request_irq_a(ARCHIMEDES_IRQA_VBL);
if (m_video_dma_on)
vidc_video_tick();
}
// set up for next vbl
m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time));
//m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time));
}
WRITE_LINE_MEMBER( archimedes_state::sound_drq )
{
if (state)
vidc_audio_tick();
}
/* video DMA */
/* TODO: what type of DMA this is, burst or cycle steal? Docs doesn't explain it (4 usec is the DRAM refresh). */
/* TODO: change m_region_vram into proper alloc array */
/* TODO: Erotictac and Poizone sets up vidinit register AFTER vidend, for double buffering? (fixes Poizone "Eterna" logo display on attract) */
// TODO: what type of DMA this is, burst or cycle steal? Docs doesn't explain it (4 usec is the DRAM refresh). */
// TODO: Erotictac and Poizone sets up vidinit register AFTER vidend, for double buffering? (fixes Poizone "Eterna" logo display on attract)
// TODO: understand how to make quazer to work (sets video DMA param in-flight)
void archimedes_state::vidc_video_tick()
{
address_space &space = m_maincpu->space(AS_PROGRAM);
static uint8_t *vram = m_region_vram->base();
uint32_t size;
uint32_t offset_ptr;
@ -134,7 +146,7 @@ void archimedes_state::vidc_video_tick()
for(m_vidc_vidcur = 0;m_vidc_vidcur < size;m_vidc_vidcur++)
{
vram[m_vidc_vidcur] = (space.read_byte(offset_ptr));
m_vidc->write_vram(m_vidc_vidcur, space.read_byte(offset_ptr));
offset_ptr++;
if(offset_ptr >= m_vidc_vidend+0x10) // TODO: correct?
offset_ptr = m_vidc_vidstart;
@ -142,73 +154,21 @@ void archimedes_state::vidc_video_tick()
if(m_cursor_enabled == true)
{
uint32_t ccur_size = (m_vidc_regs[VIDC_VCER] - m_vidc_regs[VIDC_VCSR]) * 32;
uint32_t ccur_size = m_vidc->get_cursor_size();
for(uint32_t ccur = 0; ccur < ccur_size; ccur++)
m_cursor_vram[ccur] = (space.read_byte(m_vidc_cinit+ccur));
m_vidc->write_cram(ccur, space.read_byte(m_vidc_cinit+ccur));
}
if(m_video_dma_on)
{
m_vid_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time+1));
}
else
m_vid_timer->adjust(attotime::never);
}
/* audio DMA */
void archimedes_state::vidc_audio_tick()
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint8_t ulaw_comp;
int16_t res;
uint8_t ch;
static const int16_t mulawTable[256] =
{
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
-11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
-1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
-876, -844, -812, -780, -748, -716, -684, -652,
-620, -588, -556, -524, -492, -460, -428, -396,
-372, -356, -340, -324, -308, -292, -276, -260,
-244, -228, -212, -196, -180, -164, -148, -132,
-120, -112, -104, -96, -88, -80, -72, -64,
-56, -48, -40, -32, -24, -16, -8, -1,
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
876, 844, 812, 780, 748, 716, 684, 652,
620, 588, 556, 524, 492, 460, 428, 396,
372, 356, 340, 324, 308, 292, 276, 260,
244, 228, 212, 196, 180, 164, 148, 132,
120, 112, 104, 96, 88, 80, 72, 64,
56, 48, 40, 32, 24, 16, 8, 0
};
for(ch=0; ch<8; ch++)
{
uint8_t ulaw_temp = (space.read_byte(m_vidc_sndcur + ch)) ^ 0xff;
ulaw_comp = (ulaw_temp>>1) | ((ulaw_temp&1)<<7);
res = mulawTable[ulaw_comp];
m_dac[ch & 7]->write(res);
}
m_vidc->write_dac(ch, (space.read_byte(m_vidc_sndcur + ch)));
m_vidc_sndcur+=8;
@ -216,13 +176,12 @@ void archimedes_state::vidc_audio_tick()
{
archimedes_request_irq_b(ARCHIMEDES_IRQB_SOUND_EMPTY);
// TODO: nuke this implementation detail, repeated below
m_vidc->update_sound_mode(m_audio_dma_on);
if(!m_audio_dma_on)
{
m_snd_timer->adjust(attotime::never);
for(ch=0; ch<8; ch++)
{
m_dac[ch & 7]->write(0);
}
m_vidc->clear_dac(ch);
}
else
{
@ -293,21 +252,12 @@ void archimedes_state::archimedes_reset()
m_ioc_regs[IRQ_STATUS_B] = 0x00; //set up IL[1] On
m_ioc_regs[FIQ_STATUS] = 0x80; //set up Force FIQ
m_ioc_regs[CONTROL] = 0xff;
m_vidc_vblank_time = 10000; // set a stupidly high time so it doesn't fire off
m_vbl_timer->adjust(attotime::never);
m_cursor_enabled = false;
memset(m_cursor_vram, 0, sizeof(m_cursor_vram));
}
void archimedes_state::archimedes_init()
{
m_memc_pagesize = 0;
m_vbl_timer = timer_alloc(TIMER_VBLANK);
m_vbl_timer->adjust(attotime::never);
m_timer[0] = timer_alloc(TIMER_IOC);
m_timer[1] = timer_alloc(TIMER_IOC);
m_timer[2] = timer_alloc(TIMER_IOC);
@ -316,10 +266,6 @@ void archimedes_state::archimedes_init()
m_timer[1]->adjust(attotime::never);
m_timer[2]->adjust(attotime::never);
m_timer[3]->adjust(attotime::never);
m_vid_timer = timer_alloc(TIMER_VIDEO);
m_snd_timer = timer_alloc(TIMER_AUDIO);
m_snd_timer->adjust(attotime::never);
}
READ32_MEMBER(archimedes_state::archimedes_memc_logical_r)
@ -520,13 +466,8 @@ READ32_MEMBER( archimedes_state::ioc_ctrl_r )
case CONTROL:
{
uint8_t i2c_data = 1;
uint8_t flyback; //internal name for vblank here
int vert_pos;
bool floppy_ready_state;
vert_pos = m_screen->vpos();
flyback = (vert_pos <= m_vidc_regs[VIDC_VDSR] || vert_pos >= m_vidc_regs[VIDC_VDER]) ? 0x80 : 0x00;
if ( m_i2cmem )
{
i2c_data = (m_i2cmem->read_sda() & 1);
@ -534,7 +475,7 @@ READ32_MEMBER( archimedes_state::ioc_ctrl_r )
floppy_ready_state = check_floppy_ready();
return (flyback) | (m_ioc_regs[CONTROL] & 0x78) | (floppy_ready_state<<2) | (m_i2c_clk<<1) | i2c_data;
return (m_vidc->flyback_r()<<7) | (m_ioc_regs[CONTROL] & 0x78) | (floppy_ready_state<<2) | (m_i2c_clk<<1) | i2c_data;
}
case KART: // keyboard read
@ -628,8 +569,8 @@ WRITE32_MEMBER( archimedes_state::ioc_ctrl_w )
/* bit 7 forces an IRQ trap */
archimedes_request_irq_a((data & 0x80) ? ARCHIMEDES_IRQA_FORCE : 0);
if(data & 0x08) //set up the VBLANK timer
m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time));
//if(data & 0x08) //set up the VBLANK timer
// m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time));
break;
@ -747,10 +688,11 @@ READ32_MEMBER(archimedes_state::archimedes_ioc_r)
}
case 2:
// RTFM joystick interface routes here
// TODO: slot interface for econet (reads registers 0 and 1 during boot)
switch(ioc_addr)
{
case 0x3a0000:
return 0xed; // ID? Status?
return 0xed; // ID for econet
case 0x3a0004:
return m_joy[0].read_safe(0xff);
case 0x3a0008:
@ -770,12 +712,13 @@ READ32_MEMBER(archimedes_state::archimedes_ioc_r)
case 5:
if (m_fdc)
{
// TODO: IOEB slot interface
switch(ioc_addr & 0xfffc)
{
case 0x18: return 0xff; // FDC latch B
case 0x40: return 0xff; // FDC latch A
case 0x50: return 0; //fdc type, new model returns 5 here
case 0x70: return 0x0f;
case 0x50: return 0; //fdc type, an 82c711 returns 5 here
case 0x70: return 0x0f; // monitor type, TBD
case 0x74: return 0xff; // unknown
case 0x78: // serial joystick?
case 0x7c:
@ -917,178 +860,6 @@ WRITE32_MEMBER(archimedes_state::archimedes_ioc_w)
logerror("(PC=%08x) I/O: W %x @ %x (mask %08x)\n", m_maincpu->pc(), data, (offset*4)+0x3000000, mem_mask);
}
READ32_MEMBER(archimedes_state::archimedes_vidc_r)
{
return 0;
}
void archimedes_state::vidc_dynamic_res_change()
{
/* sanity checks - first pass */
/*
total cycles + border end
*/
if(m_vidc_regs[VIDC_HCR] && m_vidc_regs[VIDC_HBER] &&
m_vidc_regs[VIDC_VCR] && m_vidc_regs[VIDC_VBER])
{
/* sanity checks - second pass */
/*
total cycles >= border end >= border start
*/
if((m_vidc_regs[VIDC_HCR] >= m_vidc_regs[VIDC_HBER]) &&
(m_vidc_regs[VIDC_HBER] >= m_vidc_regs[VIDC_HBSR]) &&
(m_vidc_regs[VIDC_VBER] >= m_vidc_regs[VIDC_VBSR]))
{
rectangle const visarea(
0, m_vidc_regs[VIDC_HBER] - m_vidc_regs[VIDC_HBSR] - 1,
0, (m_vidc_regs[VIDC_VBER] - m_vidc_regs[VIDC_VBSR]) * (m_vidc_interlace + 1));
m_vidc_vblank_time = m_vidc_regs[VIDC_VBER] * (m_vidc_interlace+1);
//logerror("Configuring: htotal %d vtotal %d border %d x %d display origin %d x %d vblank = %d\n",
// m_vidc_regs[VIDC_HCR], m_vidc_regs[VIDC_VCR],
// visarea.right(), visarea.bottom(),
// m_vidc_regs[VIDC_HDER]-m_vidc_regs[VIDC_HDSR],m_vidc_regs[VIDC_VDER]-m_vidc_regs[VIDC_VDSR]+1,
// m_vidc_vblank_time);
attoseconds_t const refresh = HZ_TO_ATTOSECONDS(pixel_rate[m_vidc_pixel_clk]) * m_vidc_regs[VIDC_HCR] * m_vidc_regs[VIDC_VCR];
m_screen->configure(m_vidc_regs[VIDC_HCR], m_vidc_regs[VIDC_VCR] * (m_vidc_interlace+1), visarea, refresh);
}
}
}
WRITE32_MEMBER(archimedes_state::archimedes_vidc_w)
{
uint32_t reg = data>>24;
uint32_t val = data & 0xffffff;
#if CRTC_LOG
static const char *const vrnames[] =
{
"horizontal total",
"horizontal sync width",
"horizontal border start",
"horizontal display start",
"horizontal display end",
"horizontal border end",
"horizontal cursor start",
"horizontal interlace",
"vertical total",
"vertical sync width",
"vertical border start",
"vertical display start",
"vertical display end",
"vertical border end",
"vertical cursor start",
"vertical cursor end",
};
#endif
// 0x00 - 0x3c Video Palette Logical Colors (16 colors)
// 0x40 Border Color
// 0x44 - 0x4c Cursor Palette Logical Colors
if (reg <= 0x4c)
{
int r,g,b;
//i = (val & 0x1000) >> 12; //supremacy bit
b = (val & 0x0f00) >> 8;
g = (val & 0x00f0) >> 4;
r = (val & 0x000f) >> 0;
//if(reg == 0x40 && val & 0xfff)
// logerror("WARNING: border color write here (PC=%08x)!\n",m_maincpu->pc());
m_palette->set_pen_color(reg >> 2, pal4bit(r), pal4bit(g), pal4bit(b) );
/* handle 8bpp colors here */
if(reg <= 0x3c)
{
int i;
for(i=0;i<0x100;i+=0x10)
{
b = ((val & 0x700) >> 8) | ((i & 0x80) >> 4);
g = ((val & 0x030) >> 4) | ((i & 0x60) >> 3);
r = ((val & 0x007) >> 0) | ((i & 0x10) >> 1);
m_palette->set_pen_color((reg >> 2) + 0x100 + i, pal4bit(r), pal4bit(g), pal4bit(b) );
}
}
// update partials
m_screen->update_partial(m_screen->vpos());
}
else if (reg >= 0x60 && reg <= 0x7c)
{
m_vidc_stereo_reg[(reg >> 2) & 7] = val & 0x07;
// popmessage("%02x %02x %02x %02x %02x %02x %02x %02x",vidc_stereo_reg[0],vidc_stereo_reg[1],vidc_stereo_reg[2],vidc_stereo_reg[3]
// ,vidc_stereo_reg[4],vidc_stereo_reg[5],vidc_stereo_reg[6],vidc_stereo_reg[7]);
}
else if (reg >= 0x80 && reg <= 0xbc)
{
switch(reg)
{
case VIDC_HCR: m_vidc_regs[VIDC_HCR] = ((val >> 14)<<1)+1; break;
// case VIDC_HSWR: m_vidc_regs[VIDC_HSWR] = (val >> 14)+1; break;
case VIDC_HBSR: m_vidc_regs[VIDC_HBSR] = ((val >> 14)<<1)+1; break;
case VIDC_HDSR: m_vidc_regs[VIDC_HDSR] = (val >> 14); break;
case VIDC_HDER: m_vidc_regs[VIDC_HDER] = (val >> 14); break;
case VIDC_HBER: m_vidc_regs[VIDC_HBER] = ((val >> 14)<<1)+1; break;
case VIDC_HCSR: m_vidc_regs[VIDC_HCSR] = ((val >> 13) & 0x7ff) + 6; break;
// #define VIDC_HIR 0x9c
case VIDC_VCR: m_vidc_regs[VIDC_VCR] = ((val >> 14))+1; break;
// #define VIDC_VSWR 0xa4
case VIDC_VBSR: m_vidc_regs[VIDC_VBSR] = (val >> 14)+1; break;
case VIDC_VDSR: m_vidc_regs[VIDC_VDSR] = (val >> 14)+1; break;
case VIDC_VDER: m_vidc_regs[VIDC_VDER] = (val >> 14)+1; break;
case VIDC_VBER: m_vidc_regs[VIDC_VBER] = (val >> 14)+1; break;
case VIDC_VCSR: m_vidc_regs[VIDC_VCSR] = ((val >> 14) & 0x3ff) + 1; break;
case VIDC_VCER: m_vidc_regs[VIDC_VCER] = ((val >> 14) & 0x3ff) + 1; break;
}
#if CRTC_LOG
if(reg != VIDC_VCSR && reg != VIDC_VCER && reg != VIDC_HCSR)
logerror("VIDC: %s = %d\n", vrnames[(reg-0x80)/4], m_vidc_regs[reg]);
#endif
vidc_dynamic_res_change();
}
else if (reg == 0xc0)
{
m_vidc_regs[reg] = val & 0xffff;
if (m_audio_dma_on)
{
double sndhz = 1e6 / ((m_vidc_regs[0xc0] & 0xff) + 2);
sndhz /= 8.0;
m_snd_timer->adjust(attotime::zero, 0, attotime::from_hz(sndhz));
//printf("VIDC: sound freq to %d, sndhz = %f\n", (val & 0xff)-2, sndhz);
}
}
else if (reg == 0xe0)
{
m_vidc_bpp_mode = ((val & 0x0c) >> 2);
m_vidc_interlace = ((val & 0x40) >> 6);
m_vidc_pixel_clk = (val & 0x03);
//todo: vga/svga modes sets 0x1000
vidc_dynamic_res_change();
}
else
{
logerror("VIDC: %x to register %x\n", val, reg);
m_vidc_regs[reg] = val&0xffff;
}
}
READ32_MEMBER(archimedes_state::archimedes_memc_r)
{
return 0;
}
WRITE32_MEMBER(archimedes_state::archimedes_memc_w)
{
// is it a register?
@ -1113,6 +884,7 @@ WRITE32_MEMBER(archimedes_state::archimedes_memc_w)
case 3: /* cursor init */
m_cursor_enabled = true;
m_vidc->set_cursor_enable(m_cursor_enabled);
m_vidc_cinit = 0x2000000 | (((data>>2)&0x7fff)*16);
//printf("MEMC: CURSOR INIT %08x\n",((data>>2)&0x7fff)*16);
break;
@ -1138,24 +910,25 @@ WRITE32_MEMBER(archimedes_state::archimedes_memc_w)
logerror("(PC = %08x) MEMC: %x to Control (page size %d, %s, %s)\n", m_maincpu->pc(), data & 0x1ffc, page_sizes[m_memc_pagesize], ((data>>10)&1) ? "Video DMA on" : "Video DMA off", ((data>>11)&1) ? "Sound DMA on" : "Sound DMA off");
m_video_dma_on = ((data>>10)&1);
m_audio_dma_on = ((data>>11)&1);
m_video_dma_on = BIT(data, 10);
m_audio_dma_on = BIT(data, 11);
if ((data>>10)&1)
if (m_video_dma_on)
{
m_vidc_vidcur = 0;
m_vid_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time+1));
// TODO: update internally
}
else
{
m_cursor_enabled = false;
m_vidc->set_cursor_enable(m_cursor_enabled);
}
if ((data>>11) & 1)
m_vidc->update_sound_mode(m_audio_dma_on);
if (m_audio_dma_on)
{
//printf("MEMC: Starting audio DMA at %d uSec, buffer from %x to %x\n", ((m_vidc_regs[0xc0]&0xff)-2)*8, m_vidc_sndstart, m_vidc_sndend);
double sndhz = 1e6 / ((m_vidc_regs[0xc0] & 0xff) + 2);
sndhz /= 8.0;
m_snd_timer->adjust(attotime::zero, 0, attotime::from_hz(sndhz));
//printf("MEMC: audio DMA start, sound freq %d, sndhz = %f\n", (m_vidc_regs[0xc0] & 0xff)-2, sndhz);
m_vidc_sndcur = m_vidc_sndstart;

View File

@ -1,229 +0,0 @@
// license:LGPL-2.1+
// copyright-holders:Angelo Salese, R. Belmont, Juergen Buchmueller
/***************************************************************************
Acorn Archimedes VIDC (VIDeo Controller) emulation
***************************************************************************/
#include "emu.h"
#include "includes/archimds.h"
uint32_t archimedes_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int xstart,ystart,xend,yend;
int res_x,res_y;
int xsize,ysize;
int calc_dxs = 0,calc_dxe = 0;
const uint8_t x_step[4] = { 19, 11, 7, 5 };
/* border color */
bitmap.fill(m_palette->pen(0x10), cliprect);
/* define X display area through BPP mode register */
calc_dxs = (m_vidc_regs[VIDC_HDSR]*2)+x_step[m_vidc_bpp_mode & 3];
calc_dxe = (m_vidc_regs[VIDC_HDER]*2)+x_step[m_vidc_bpp_mode & 3];
/* now calculate display clip rectangle start/end areas */
xstart = (calc_dxs)-m_vidc_regs[VIDC_HBSR];
ystart = (m_vidc_regs[VIDC_VDSR]-m_vidc_regs[VIDC_VBSR]);
xend = (calc_dxe)+xstart;
yend = (m_vidc_regs[VIDC_VDER] * (m_vidc_interlace+1))+ystart;
/* disable the screen if display params are invalid */
if(xstart > xend || ystart > yend)
return 0;
xsize = calc_dxe-calc_dxs;
ysize = m_vidc_regs[VIDC_VDER]-m_vidc_regs[VIDC_VDSR];
{
int count;
int x,y,xi;
uint8_t pen;
static uint8_t *vram = memregion("vram")->base();
count = (0);
switch(m_vidc_bpp_mode)
{
case 0: //1 bpp
{
for(y=0;y<ysize;y++)
{
for(x=0;x<xsize;x+=8)
{
pen = vram[count];
for(xi=0;xi<8;xi++)
{
res_x = x+xi+xstart;
res_y = (y+ystart)*(m_vidc_interlace+1);
if(m_vidc_interlace)
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen>>(xi))&0x1);
if (cliprect.contains(res_x, res_y+1) && (res_x) <= xend && (res_y+1) <= yend)
bitmap.pix32(res_y+1, res_x) = m_palette->pen((pen>>(xi))&0x1);
}
else
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen>>(xi))&0x1);
}
}
count++;
}
}
}
break;
case 1: //2 bpp
{
for(y=0;y<ysize;y++)
{
for(x=0;x<xsize;x+=4)
{
pen = vram[count];
for(xi=0;xi<4;xi++)
{
res_x = x+xi+xstart;
res_y = (y+ystart)*(m_vidc_interlace+1);
if(m_vidc_interlace)
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen>>(xi*2))&0x3);
if (cliprect.contains(res_x, res_y+1) && (res_x) <= xend && (res_y+1) <= yend)
bitmap.pix32(res_y+1, res_x) = m_palette->pen((pen>>(xi*2))&0x3);
}
else
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen>>(xi*2))&0x3);
}
}
count++;
}
}
}
break;
case 2: //4 bpp
{
for(y=0;y<ysize;y++)
{
for(x=0;x<xsize;x+=2)
{
pen = vram[count];
for(xi=0;xi<2;xi++)
{
res_x = x+xi+xstart;
res_y = (y+ystart)*(m_vidc_interlace+1);
if(m_vidc_interlace)
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen>>(xi*4))&0xf);
if (cliprect.contains(res_x, res_y+1) && (res_x) <= xend && (res_y+1) <= yend)
bitmap.pix32(res_y+1, res_x) = m_palette->pen((pen>>(xi*4))&0xf);
}
else
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen>>(xi*4))&0xf);
}
}
count++;
}
}
}
break;
case 3: //8 bpp
{
for(y=0;y<ysize;y++)
{
for(x=0;x<xsize;x++)
{
pen = vram[count];
res_x = x+xstart;
res_y = (y+ystart)*(m_vidc_interlace+1);
if(m_vidc_interlace)
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen&0xff)+0x100);
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y+1) <= yend)
bitmap.pix32(res_y+1, res_x) = m_palette->pen((pen&0xff)+0x100);
}
else
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen((pen&0xff)+0x100);
}
count++;
}
}
}
break;
default:
popmessage("Unemulated bpp mode %02x, contact MAME/MESSdev",m_vidc_bpp_mode);
break;
}
if(m_cursor_enabled == true)
{
count = 0;
int cursor_h = m_vidc_regs[VIDC_VCER] - m_vidc_regs[VIDC_VCSR];
if (cursor_h <= 0)
return 0;
for(y=0; y<cursor_h; y++)
{
for(x=0;x<32;x+=4)
{
for(xi=0;xi<4;xi++)
{
uint8_t cursor_dot;
pen = m_cursor_vram[count];
res_x = m_vidc_regs[VIDC_HCSR] - m_vidc_regs[VIDC_HBSR] + x + xi;
res_y = (m_vidc_regs[VIDC_VCSR] - m_vidc_regs[VIDC_VBSR] + y) * (m_vidc_interlace + 1);
cursor_dot = ((pen>>(xi*2))&0x3);
if(cursor_dot)
{
if(m_vidc_interlace)
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen(cursor_dot+0x10);
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y+1) <= yend)
bitmap.pix32(res_y+1, res_x) = m_palette->pen(cursor_dot+0x10);
}
else
{
if (cliprect.contains(res_x, res_y) && (res_x) <= xend && (res_y) <= yend)
bitmap.pix32(res_y, res_x) = m_palette->pen(cursor_dot+0x10);
}
}
}
count++;
}
}
}
}
return 0;
}