ef9365: simplify busy timer, change msl pins to a devcb

This commit is contained in:
hap 2023-10-27 19:25:56 +02:00
parent d6a7f2906a
commit 5b297d7854
4 changed files with 69 additions and 64 deletions

View File

@ -2,7 +2,7 @@
// copyright-holders:Daniel Coulom,Sandro Ronco
/*********************************************************************
ef9345.c
ef9345.cpp
Thomson EF9345 video controller emulator code

View File

@ -3,7 +3,7 @@
/*********************************************************************
ef9365.c
ef9365.cpp
Thomson EF9365/EF9366/EF9367 video controller emulator code
@ -162,7 +162,8 @@ const tiny_rom_entry *ef9365_device::device_rom_region() const
// default address map
// Up to 512*512 per bitplane, 8 bitplanes max.
//-------------------------------------------------
void ef9365_device::ef9365(address_map &map)
void ef9365_device::ef9365_map(address_map &map)
{
if (!has_configured_map(0))
map(0x00000, ef9365_device::BITPLANE_MAX_SIZE * ef9365_device::MAX_BITPLANES - 1).ram();
@ -197,12 +198,15 @@ ef9365_device::ef9365_device(const machine_config &mconfig, const char *tag, dev
device_t(mconfig, EF9365, tag, owner, clock),
device_memory_interface(mconfig, *this),
device_video_interface(mconfig, *this),
m_space_config("videoram", ENDIANNESS_LITTLE, 8, 18, 0, address_map_constructor(FUNC(ef9365_device::ef9365), this)),
m_space_config("videoram", ENDIANNESS_LITTLE, 8, 18, 0, address_map_constructor(FUNC(ef9365_device::ef9365_map), this)),
m_charset(*this, "ef9365"),
m_palette(*this, finder_base::DUMMY_TAG),
m_irq_handler(*this)
m_irq_handler(*this),
m_write_msl(*this)
{
m_clock_freq = clock;
set_display_mode(DISPLAY_MODE_256x256);
set_nb_bitplanes(1);
set_color_filler(0);
}
//-------------------------------------------------
@ -270,11 +274,7 @@ void ef9365_device::set_display_mode(int display_mode)
break;
default:
logerror("Invalid EF9365 Display mode: %02x\n", display_mode);
m_bitplane_xres = 256;
m_bitplane_yres = 256;
m_vsync_scanline_pos = 250;
m_overflow_mask_x = 0xff00;
m_overflow_mask_y = 0xff00;
set_display_mode(DISPLAY_MODE_256x256);
break;
}
}
@ -315,7 +315,6 @@ void ef9365_device::device_start()
m_busy_timer = timer_alloc(FUNC(ef9365_device::clear_busy_flag), this);
m_videoram = &space(0);
m_current_color = 0x00;
m_irq_vb = 0;
m_irq_lb = 0;
@ -324,18 +323,20 @@ void ef9365_device::device_start()
m_screen_out.allocate(m_bitplane_xres, screen().height());
save_item(NAME(m_border));
save_item(NAME(m_registers));
save_item(NAME(m_bf));
save_item(NAME(m_state));
save_item(NAME(m_msl));
save_item(NAME(m_readback_latch_pix_offset));
save_item(NAME(m_irq_state));
save_item(NAME(m_irq_vb));
save_item(NAME(m_irq_lb));
save_item(NAME(m_irq_rdy));
save_item(NAME(m_current_color));
save_item(NAME(m_bf));
save_item(NAME(m_registers));
save_item(NAME(m_state));
save_item(NAME(m_border));
save_item(NAME(m_readback_latch));
save_item(NAME(m_readback_latch_pix_offset));
save_item(NAME(m_screen_out));
}
@ -345,17 +346,19 @@ void ef9365_device::device_start()
void ef9365_device::device_reset()
{
m_state = 0;
m_bf = 0;
m_irq_state = 0;
m_irq_vb = 0;
m_irq_lb = 0;
m_irq_rdy = 0;
m_bf = 0;
m_state = 0;
memset(m_registers, 0, sizeof(m_registers));
memset(m_border, 0, sizeof(m_border));
memset(m_readback_latch, 0, sizeof(m_readback_latch));
m_readback_latch_pix_offset = 0;
m_screen_out.fill(0);
set_video_mode();
@ -401,10 +404,10 @@ TIMER_CALLBACK_MEMBER(ef9365_device::clear_busy_flag)
// timer to clear it
//-------------------------------------------------
void ef9365_device::set_busy_flag(int period)
void ef9365_device::set_busy_flag(int cycles)
{
m_bf = 1;
m_busy_timer->adjust(attotime::from_usec(period));
m_busy_timer->adjust(attotime::from_ticks(cycles, clock()));
}
//-------------------------------------------------
@ -445,6 +448,16 @@ void ef9365_device::set_y_reg(uint16_t y)
m_registers[EF936X_REG_Y_LSB] = y & 0xff;
}
//-------------------------------------------------
// set_msl_pins: Set the MSL pins
//-------------------------------------------------
void ef9365_device::set_msl_pins(uint16_t x, uint16_t y)
{
y = (m_bitplane_yres == 512) ? (y & 1) : 1;
m_write_msl((x & 7) | y << 3);
}
//-------------------------------------------------
// set_video_mode: Set output screen format
//-------------------------------------------------
@ -506,8 +519,8 @@ void ef9365_device::plot(int x_pos, int y_pos)
if (m_registers[EF936X_REG_CTRL1] & 0x01)
{
y_pos = (m_bitplane_yres - 1) - y_pos;
m_msl = (x_pos & 7) | 8;
uint8_t mask = 0x80 >> (m_msl & 7);
set_msl_pins(x_pos, y_pos);
uint8_t mask = 0x80 >> (x_pos & 7);
if (m_registers[EF936X_REG_CTRL1] & 0x02)
{
@ -829,15 +842,6 @@ int ef9365_device::draw_character(uint8_t c, bool block, bool smallblock)
return compute_cycles;
}
//-------------------------------------------------
// cycles_to_us: Convert a number of clock cycles to us
//-------------------------------------------------
int ef9365_device::cycles_to_us(int cycles)
{
return (int)(cycles * (1000000.f / m_clock_freq));
}
//-------------------------------------------------
// dump_bitplanes_word: Latch the bitplane words
// pointed by the x & y registers
@ -873,8 +877,8 @@ void ef9365_device::screen_scanning(bool force_clear)
{
for (int x = 0; x < m_bitplane_xres; x++)
{
m_msl = (x & 7) | 8;
uint8_t mask = 0x80 >> (m_msl & 7);
set_msl_pins(x, y);
uint8_t mask = 0x80 >> (x & 7);
for (int p = 0; p < m_nb_of_bitplanes; p++)
{
@ -894,8 +898,8 @@ void ef9365_device::screen_scanning(bool force_clear)
{
for (int x = 0; x < m_bitplane_xres; x++)
{
m_msl = (x & 7) | 8;
uint8_t mask = 0x80 >> (m_msl & 7);
set_msl_pins(x, y);
uint8_t mask = 0x80 >> (x & 7);
for (int p = 0; p < m_nb_of_bitplanes; p++)
{
@ -987,7 +991,7 @@ void ef9365_device::ef9365_exec(uint8_t cmd)
if (busy_cycles)
{
set_busy_flag(cycles_to_us(busy_cycles));
set_busy_flag(busy_cycles);
}
}
else
@ -1041,7 +1045,7 @@ void ef9365_device::ef9365_exec(uint8_t cmd)
busy_cycles = draw_vector(get_x_reg(), get_y_reg(), -tmp_delta_x, 0);
break;
}
set_busy_flag(cycles_to_us(busy_cycles));
set_busy_flag(busy_cycles);
}
else
{
@ -1084,7 +1088,7 @@ void ef9365_device::ef9365_exec(uint8_t cmd)
break;
}
set_busy_flag(cycles_to_us(busy_cycles));
set_busy_flag(busy_cycles);
}
else
{
@ -1093,7 +1097,7 @@ void ef9365_device::ef9365_exec(uint8_t cmd)
LOG("EF9365 Command : [0x%.2X] %s\n", cmd, commands_names[0x12]);
int busy_cycles = draw_character(cmd - 0x20, false, false);
set_busy_flag(cycles_to_us(busy_cycles));
set_busy_flag(busy_cycles);
}
}
}

View File

@ -44,7 +44,8 @@ public:
template <typename T> void set_palette_tag(T &&tag) { m_palette.set_tag(std::forward<T>(tag)); }
void set_nb_bitplanes(int nb_bitplanes);
void set_display_mode(int display_mode);
auto irq_handler() { return m_irq_handler.bind(); }
auto irq_handler() { return m_irq_handler.bind(); } // IRQ pin
auto write_msl() { return m_write_msl.bind(); } // memory select during pixel write
// device interface
uint8_t data_r(offs_t offset);
@ -53,8 +54,6 @@ public:
void update_scanline(uint16_t scanline);
void set_color_filler(uint8_t color);
void set_color_entry(int index, uint8_t r, uint8_t g, uint8_t b);
uint8_t get_msl() { return m_msl; } // during pixel write
uint8_t get_last_readback_word(int bitplane_number, int *pixel_offset);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
@ -82,16 +81,16 @@ private:
uint16_t get_y_reg();
void set_x_reg(uint16_t x);
void set_y_reg(uint16_t y);
void set_msl_pins(uint16_t x, uint16_t y);
void screen_scanning(bool force_clear);
void set_busy_flag(int period);
void set_busy_flag(int cycles);
void set_video_mode();
void draw_border(uint16_t line);
void ef9365_exec(uint8_t cmd);
int cycles_to_us(int cycles);
void dump_bitplanes_word();
void update_interrupts();
void ef9365(address_map &map);
void ef9365_map(address_map &map);
// internal state
required_region_ptr<uint8_t> m_charset;
@ -106,7 +105,6 @@ private:
uint8_t m_registers[0x10]; // registers
uint8_t m_state; // status register
uint8_t m_border[80]; // border color
uint8_t m_msl; // memory select signal
int m_nb_of_bitplanes;
int m_nb_of_colors;
@ -119,7 +117,6 @@ private:
uint8_t m_readback_latch[MAX_BITPLANES]; // Last DRAM Readback buffer (Filled after a Direct Memory Access Request command)
int m_readback_latch_pix_offset;
uint32_t m_clock_freq;
bitmap_rgb32 m_screen_out;
// timers
@ -127,6 +124,7 @@ private:
required_device<palette_device> m_palette;
devcb_write_line m_irq_handler;
devcb_write8 m_write_msl;
};
// device type definition

View File

@ -80,6 +80,7 @@ private:
void vram_map(address_map &map);
void vram_w(offs_t offset, u8 data);
u8 vram_r(offs_t offset);
void msl_w(u8 data) { m_pixel_offset = data & 7; }
void porta_w(u8 data);
u8 porta_r();
@ -95,6 +96,7 @@ private:
u8 m_ccount = 0;
u8 m_command = 0;
u8 m_color = 0;
u8 m_pixel_offset = 0;
u8 m_vramdata = 0;
};
@ -117,6 +119,7 @@ void videoart_state::machine_start()
save_item(NAME(m_ccount));
save_item(NAME(m_command));
save_item(NAME(m_color));
save_item(NAME(m_pixel_offset));
save_item(NAME(m_vramdata));
}
@ -176,9 +179,8 @@ u32 videoart_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c
void videoart_state::vram_w(offs_t offset, u8 data)
{
u8 low = m_ef9367->get_msl() & 7;
data = BIT(data, low ^ 7);
offset = offset << 1 | BIT(low, 2);
data = BIT(data, ~m_pixel_offset & 7);
offset = offset << 1 | BIT(m_pixel_offset, 2);
if (data)
m_vram[offset] = m_color;
@ -188,9 +190,9 @@ void videoart_state::vram_w(offs_t offset, u8 data)
u8 videoart_state::vram_r(offs_t offset)
{
int low = 0;
m_ef9367->get_last_readback_word(0, &low);
offset = offset << 1 | BIT(low, 2);
int pixel_offset = 0;
m_ef9367->get_last_readback_word(0, &pixel_offset);
offset = offset << 1 | BIT(pixel_offset, 2);
if (!machine().side_effects_disabled())
m_vramdata = m_vram[offset];
@ -218,24 +220,24 @@ void videoart_state::porta_w(u8 data)
u8 videoart_state::porta_r()
{
u8 data = 0;
u8 data = 0xff;
// read EF9367 data
if (~m_portb & 1)
data |= m_efdata;
data &= m_efdata;
// read vram data
if (~m_portb & 4)
{
u8 shift = (m_ccount & 1) * 2;
data |= m_vramdata >> shift;
data &= m_vramdata >> shift | 0xfc;
}
// read cartridge data
if (~m_portb & 0x10)
{
u16 offset = m_romlatch << 8 | m_portc;
data |= m_cart->read_rom(offset);
data &= m_cart->read_rom(offset);
}
return data;
@ -357,6 +359,7 @@ void videoart_state::videoart(machine_config &config)
m_ef9367->set_nb_bitplanes(1);
m_ef9367->set_display_mode(ef9365_device::DISPLAY_MODE_512x256);
m_ef9367->irq_handler().set_inputline(m_maincpu, M6805_IRQ_LINE);
m_ef9367->write_msl().set(FUNC(videoart_state::msl_w));
TIMER(config, "scanline").configure_scanline(FUNC(videoart_state::scanline), "screen", 0, 1);