mirror of
https://github.com/holub/mame
synced 2025-07-07 19:03:29 +03:00
zx spectrum drivers: Restore irq length == 32 / border timings. (#9711)
This commit is contained in:
parent
98b14fa8ae
commit
51a0b70208
@ -217,8 +217,8 @@ void pentagon_state::machine_reset()
|
||||
|
||||
void pentagon_state::video_start()
|
||||
{
|
||||
m_frame_invert_count = 16;
|
||||
m_screen_location = m_ram->pointer() + (5 << 14);
|
||||
spectrum_128_state::video_start();
|
||||
m_contention_pattern = {};
|
||||
}
|
||||
|
||||
static const gfx_layout spectrum_charlayout =
|
||||
|
@ -167,9 +167,9 @@ resulting mess can be seen in the F4 viewer display.
|
||||
|
||||
void spectrum_128_state::video_start()
|
||||
{
|
||||
m_frame_invert_count = 16;
|
||||
spectrum_state::video_start();
|
||||
m_screen_location = m_ram->pointer() + (5 << 14);
|
||||
m_contention_pattern = {6, 5, 4, 3, 2, 1, 0, 0};
|
||||
m_border4t_render_at = 6;
|
||||
}
|
||||
|
||||
uint8_t spectrum_128_state::spectrum_128_pre_opcode_fetch_r(offs_t offset)
|
||||
@ -230,8 +230,6 @@ void spectrum_128_state::spectrum_128_port_7ffd_w(offs_t offset, uint8_t data)
|
||||
/* disable paging? */
|
||||
if (m_port_7ffd_data & 0x20) return;
|
||||
|
||||
if ((m_port_7ffd_data ^ data) & 0x08) m_screen->update_now();
|
||||
|
||||
/* store new state */
|
||||
m_port_7ffd_data = data;
|
||||
|
||||
@ -293,6 +291,10 @@ void spectrum_128_state::spectrum_128_fetch(address_map &map)
|
||||
|
||||
void spectrum_128_state::machine_start()
|
||||
{
|
||||
spectrum_state::machine_start();
|
||||
|
||||
save_item(NAME(m_port_7ffd_data));
|
||||
|
||||
/* rom 0 is 128K rom, rom 1 is 48 BASIC */
|
||||
memory_region *rom = memregion("maincpu");
|
||||
m_bank_rom[0]->configure_entries(0, 2, rom->base() + 0x10000, 0x4000);
|
||||
@ -313,22 +315,19 @@ void spectrum_128_state::machine_reset()
|
||||
|
||||
/* set initial ram config */
|
||||
m_port_7ffd_data = 0;
|
||||
m_port_1ffd_data = -1;
|
||||
spectrum_128_update_memory();
|
||||
}
|
||||
|
||||
bool spectrum_128_state::is_vram_write(offs_t offset) {
|
||||
// TODO respect banks 2,5 mapped to 0xc000
|
||||
return (BIT(m_port_7ffd_data, 3))
|
||||
? offset >= 0x8000 && offset < 0x9b00
|
||||
return (BIT(m_port_7ffd_data, 3) && m_bank_ram[3]->entry() == 7)
|
||||
? offset >= 0xc000 && offset < 0xdb00
|
||||
: spectrum_state::is_vram_write(offset);
|
||||
}
|
||||
|
||||
bool spectrum_128_state::is_contended(offs_t offset) {
|
||||
// Memory banks 1,3,5 and 7 are contended
|
||||
u8 bank = m_bank_ram[3]->entry();
|
||||
return spectrum_state::is_contended(offset)
|
||||
|| ((offset >= 0xc000 && offset <= 0xffff) && (bank && 1));
|
||||
|| ((offset >= 0xc000 && offset <= 0xffff) && (bank && 1)); // Memory banks 1,3,5 and 7 are contended
|
||||
}
|
||||
|
||||
static const gfx_layout spectrum_charlayout =
|
||||
|
@ -266,8 +266,6 @@ void specpls3_state::port_7ffd_w(offs_t offset, uint8_t data)
|
||||
/* paging disabled? */
|
||||
if (m_port_7ffd_data & 0x20) return;
|
||||
|
||||
if ((m_port_7ffd_data ^ data) & 0x08) m_screen->update_now();
|
||||
|
||||
/* store new state */
|
||||
m_port_7ffd_data = data;
|
||||
|
||||
@ -342,6 +340,8 @@ void specpls3_state::machine_start()
|
||||
{
|
||||
spectrum_128_state::machine_start();
|
||||
|
||||
save_item(NAME(m_port_1ffd_data));
|
||||
|
||||
// reconfigure ROMs
|
||||
memory_region *rom = memregion("maincpu");
|
||||
m_bank_rom[0]->configure_entries(0, 4, rom->base() + 0x10000, 0x4000);
|
||||
@ -352,6 +352,7 @@ void specpls3_state::machine_start()
|
||||
void specpls3_state::machine_reset()
|
||||
{
|
||||
/* Initial configuration */
|
||||
m_port_fe_data = -1;
|
||||
m_port_7ffd_data = 0;
|
||||
m_port_1ffd_data = 0;
|
||||
plus3_update_memory();
|
||||
|
@ -727,10 +727,14 @@ void spectrum_state::init_spectrum()
|
||||
void spectrum_state::machine_start()
|
||||
{
|
||||
save_item(NAME(m_port_fe_data));
|
||||
save_item(NAME(m_int_at));
|
||||
}
|
||||
|
||||
void spectrum_state::machine_reset()
|
||||
{
|
||||
/* Initial value/behaviour of FE port is not confirmed. Startup of real devices produce 'random' border
|
||||
color which need to be investigated. */
|
||||
m_port_fe_data = -1;
|
||||
m_port_7ffd_data = -1;
|
||||
m_port_1ffd_data = -1;
|
||||
}
|
||||
@ -756,8 +760,10 @@ void spectrum_state::device_timer(emu_timer &timer, device_timer_id id, int para
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_IRQ_ON:
|
||||
m_maincpu->set_input_line(0, HOLD_LINE);
|
||||
timer_set(m_maincpu->clocks_to_attotime(32), TIMER_IRQ_OFF, 0);
|
||||
m_int_at = m_maincpu->total_cycles();
|
||||
m_int_at -= m_maincpu->attotime_to_cycles(m_maincpu->local_time() - machine().time());
|
||||
m_maincpu->set_input_line(0, ASSERT_LINE);
|
||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32));
|
||||
break;
|
||||
case TIMER_IRQ_OFF:
|
||||
m_maincpu->set_input_line(0, CLEAR_LINE);
|
||||
@ -767,13 +773,9 @@ void spectrum_state::device_timer(emu_timer &timer, device_timer_id id, int para
|
||||
}
|
||||
}
|
||||
|
||||
attotime spectrum_state::time_until_int() {
|
||||
return m_screen->time_until_pos(0, get_screen_area().left());
|
||||
};
|
||||
|
||||
INTERRUPT_GEN_MEMBER(spectrum_state::spec_interrupt)
|
||||
{
|
||||
timer_set(time_until_int(), TIMER_IRQ_ON, 0);
|
||||
timer_set(m_screen->time_until_pos(0, get_screen_area().left()), TIMER_IRQ_ON);
|
||||
}
|
||||
|
||||
void spectrum_state::spectrum_common(machine_config &config)
|
||||
|
@ -115,8 +115,13 @@ protected:
|
||||
|
||||
int m_ROMSelection = 0; // FIXME: this is used for various things in derived classes, but not by this base class, and should be removed
|
||||
std::vector<u8> m_contention_pattern;
|
||||
/* Pixel offset in 8px chunk (4T) when current chunk is rendered. */
|
||||
u8 m_border4t_render_at = 0;
|
||||
/* Defines offset in CPU cycles from screen left side. Early model (48/128/+2) typically use -1, later (+2A/+3) +1 */
|
||||
s8 m_contention_offset = -1;
|
||||
u64 m_int_at;
|
||||
|
||||
emu_timer *m_irq_off_timer;
|
||||
|
||||
uint8_t m_ram_disabled_by_beta;
|
||||
uint8_t pre_opcode_fetch_r(offs_t offset);
|
||||
@ -140,7 +145,6 @@ protected:
|
||||
void spectrum_palette(palette_device &palette) const;
|
||||
virtual u32 screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
INTERRUPT_GEN_MEMBER(spec_interrupt);
|
||||
virtual attotime time_until_int();
|
||||
|
||||
DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
|
||||
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
|
||||
|
@ -755,7 +755,7 @@ void tsconf_state::update_frame_timer()
|
||||
INTERRUPT_GEN_MEMBER(tsconf_state::tsconf_vblank_interrupt)
|
||||
{
|
||||
update_frame_timer();
|
||||
m_line_irq_timer->adjust(m_screen->time_until_pos(0));
|
||||
m_line_irq_timer->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
void tsconf_state::dma_ready(int line)
|
||||
@ -763,7 +763,7 @@ void tsconf_state::dma_ready(int line)
|
||||
if (BIT(m_regs[INT_MASK], 4))
|
||||
{
|
||||
m_maincpu->set_input_line_and_vector(line, ASSERT_LINE, 0xfb);
|
||||
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -776,7 +776,7 @@ void tsconf_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
||||
if (BIT(m_regs[INT_MASK], 0))
|
||||
{
|
||||
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff);
|
||||
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -788,12 +788,12 @@ void tsconf_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
||||
{
|
||||
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xfd);
|
||||
// Not quite precise. Scanline can't be skipped.
|
||||
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
||||
}
|
||||
if (BIT(m_regs[INT_MASK], 0) && OFFS_512(VS_INT_L) == screen_vpos && m_regs[HS_INT] == 0)
|
||||
{
|
||||
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff);
|
||||
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
||||
}
|
||||
|
||||
m_screen->update_now();
|
||||
|
@ -87,7 +87,7 @@ void agat7video_device::device_start()
|
||||
|
||||
void agat7video_device::device_reset()
|
||||
{
|
||||
// XXX to be confirmed
|
||||
// TODO to be confirmed
|
||||
m_video_mode = TEXT_LORES;
|
||||
m_start_address = 0x7800;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ void agat9video_device::device_start()
|
||||
|
||||
void agat9video_device::device_reset()
|
||||
{
|
||||
// XXX to be confirmed
|
||||
// TODO to be confirmed
|
||||
m_video_mode = TEXT_LORES;
|
||||
m_start_address = 0x7800;
|
||||
m_mode = palette_index = 0;
|
||||
@ -152,7 +152,7 @@ uint8_t agat9video_device::read(offs_t offset)
|
||||
{
|
||||
if(!machine().side_effects_disabled())
|
||||
do_io(offset);
|
||||
// XXX only 'Moscow' revision
|
||||
// FIXME only 'Moscow' revision
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,13 @@
|
||||
***************************************************************************/
|
||||
void spectrum_state::video_start()
|
||||
{
|
||||
m_irq_off_timer = timer_alloc(TIMER_IRQ_OFF);
|
||||
|
||||
m_frame_invert_count = 16;
|
||||
m_screen_location = m_video_ram;
|
||||
m_contention_pattern = {6, 5, 4, 3, 2, 1, 0, 0};
|
||||
m_contention_offset = -1;
|
||||
m_border4t_render_at = 2;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@ -116,14 +120,17 @@ u32 spectrum_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 &
|
||||
|
||||
void spectrum_state::spectrum_update_border(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &border)
|
||||
{
|
||||
u8 mod = m_contention_pattern.empty() ? 1 : m_contention_pattern.size();
|
||||
u8 mod = m_contention_pattern.empty() ? 1 : 8;
|
||||
u8 at = m_contention_pattern.empty() ? 0 : m_border4t_render_at;
|
||||
for (auto y = border.top(); y <= border.bottom(); y++)
|
||||
{
|
||||
u16 *pix = &(bitmap.pix(y, border.left()));
|
||||
for (auto x = border.left(); x <= border.right(); )
|
||||
{
|
||||
if (x % mod == 0)
|
||||
if (x % mod == at)
|
||||
{
|
||||
pix -= at;
|
||||
x -= at;
|
||||
for (auto m = 0; m < mod; m++, x++)
|
||||
*pix++ = get_border_color(y, x);
|
||||
}
|
||||
@ -136,6 +143,14 @@ void spectrum_state::spectrum_update_border(screen_device &screen, bitmap_ind16
|
||||
}
|
||||
}
|
||||
|
||||
/* ULA reads screen data in 16px (8T) chunks as following:
|
||||
T: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
px: | 0 | 1 | 2 | 3 |*4*| 5 | 6 | 7 |*0*| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
| << !right << | char1 | attr1 | char2 | attr2 | >> right >> |
|
||||
|
||||
TODO Curren implementation only tracks char switch position. In order to track both (char and attr) we need to share
|
||||
some state between screen->update() events.
|
||||
*/
|
||||
void spectrum_state::spectrum_update_screen(screen_device &screen_d, bitmap_ind16 &bitmap, const rectangle &screen)
|
||||
{
|
||||
u8 *attrs_location = m_screen_location + 0x1800;
|
||||
@ -144,17 +159,26 @@ void spectrum_state::spectrum_update_screen(screen_device &screen_d, bitmap_ind1
|
||||
{
|
||||
u16 hpos = screen.left();
|
||||
u16 x = hpos - get_screen_area().left();
|
||||
if (x % 8)
|
||||
bool chunk_right = x & 8;
|
||||
if (x % 8 <= (chunk_right ? 0 : 4))
|
||||
{
|
||||
u8 shift = x % 8;
|
||||
x -= shift;
|
||||
hpos -= shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 shift = 8 - (x % 8);
|
||||
x += shift;
|
||||
hpos += shift;
|
||||
chunk_right = !chunk_right;
|
||||
}
|
||||
u16 y = vpos - get_screen_area().top();
|
||||
u8 *scr = &m_screen_location[((y & 7) << 8) | ((y & 0x38) << 2) | ((y & 0xc0) << 5) | (x >> 3)];
|
||||
u8 *attr = &attrs_location[((y & 0xf8) << 2) | (x >> 3)];
|
||||
u16 *pix = &(bitmap.pix(vpos, hpos));
|
||||
while (hpos <= screen.right())
|
||||
|
||||
while ((hpos + (chunk_right ? 0 : 4)) <= screen.right())
|
||||
{
|
||||
u16 ink = ((*attr >> 3) & 0x08) | (*attr & 0x07);
|
||||
u16 pap = (*attr >> 3) & 0x0f;
|
||||
@ -164,6 +188,7 @@ void spectrum_state::spectrum_update_screen(screen_device &screen_d, bitmap_ind1
|
||||
*pix++ = (pix8 & b) ? ink : pap;
|
||||
scr++;
|
||||
attr++;
|
||||
chunk_right = !chunk_right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,7 +207,7 @@ void spectrum_state::content_early(s8 shift)
|
||||
if (m_contention_pattern.empty() || vpos < get_screen_area().top() || vpos > get_screen_area().bottom())
|
||||
return;
|
||||
|
||||
u64 now = m_maincpu->attotime_to_clocks(m_screen->frame_period() - time_until_int()) + shift;
|
||||
u64 now = m_maincpu->total_cycles() - m_int_at + shift;
|
||||
u64 cf = vpos * m_screen->width() * m_maincpu->clock() / m_screen->clock() + m_contention_offset;
|
||||
u64 ct = cf + get_screen_area().width() * m_maincpu->clock() / m_screen->clock();
|
||||
|
||||
@ -200,7 +225,7 @@ void spectrum_state::content_late()
|
||||
if (m_contention_pattern.empty() || vpos < get_screen_area().top() || vpos > get_screen_area().bottom())
|
||||
return;
|
||||
|
||||
u64 now = m_maincpu->attotime_to_clocks(m_screen->frame_period() - time_until_int()) + 1;
|
||||
u64 now = m_maincpu->total_cycles() - m_int_at + 1;
|
||||
u64 cf = vpos * m_screen->width() * m_maincpu->clock() / m_screen->clock() + m_contention_offset;
|
||||
u64 ct = cf + get_screen_area().width() * m_maincpu->clock() / m_screen->clock();
|
||||
for(auto i = 0x04; i; i >>= 1)
|
||||
|
@ -29,6 +29,8 @@ inline void tc2048_state::spectrum_plot_pixel(bitmap_ind16 &bitmap, int x, int y
|
||||
/* Update FLASH status for ts2068. Assumes flash update every 1/2s. */
|
||||
void ts2068_state::video_start()
|
||||
{
|
||||
m_irq_off_timer = timer_alloc(TIMER_IRQ_OFF);
|
||||
|
||||
m_frame_invert_count = 30;
|
||||
m_screen_location = m_video_ram;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user