diff --git a/scripts/src/video.lua b/scripts/src/video.lua index a09ef123fca..fafc07e37f6 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -154,6 +154,18 @@ if (VIDEOS["EF9345"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/ef9364.h,VIDEOS["EF9364"] = true +-------------------------------------------------- + +if (VIDEOS["EF9364"]~=null) then + files { + MAME_DIR .. "src/devices/video/ef9364.cpp", + MAME_DIR .. "src/devices/video/ef9364.h", + } +end + -------------------------------------------------- -- --@src/devices/video/ef9365.h,VIDEOS["EF9365"] = true diff --git a/src/devices/video/ef9364.cpp b/src/devices/video/ef9364.cpp new file mode 100644 index 00000000000..b44909571e5 --- /dev/null +++ b/src/devices/video/ef9364.cpp @@ -0,0 +1,326 @@ +// license:BSD-3-Clause +// copyright-holders:Jean-Francois DEL NERO + +/********************************************************************* + + ef9364.cpp + + Thomson EF9364 / Sescosem SFF96364 video controller emulator code + + This circuit is a simple black and white 8x8 character generator. + It display 64 columns * 16 rows text page. + It is able to do automatic text scrolling, page erase. + The characters font is stored into an external 1KB EPROM. + + To see how to use this driver, have a look to the Goupil machine + driver (goupil.cpp). + If you have any question or remark, don't hesitate to contact me + at the email present on this website : http://hxc2001.free.fr/ + + 01/20/2016 + Jean-Francois DEL NERO +*********************************************************************/ + +#include "emu.h" +#include "ef9364.h" + +// devices +const device_type EF9364 = &device_creator; + +//------------------------------------------------- +// default address map +//------------------------------------------------- +static ADDRESS_MAP_START( ef9364, AS_0, 8, ef9364_device ) + AM_RANGE(0x00000, ( ( EF9364_TXTPLANE_MAX_SIZE * EF9364_MAX_TXTPLANES ) - 1 ) ) AM_RAM +ADDRESS_MAP_END + +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- + +const address_space_config *ef9364_device::memory_space_config(address_spacenum spacenum) const +{ + return (spacenum == AS_0) ? &m_space_config : NULL; +} + +//************************************************************************** +// INLINE HELPERS +//************************************************************************** + +//************************************************************************** +// live device +//************************************************************************** + +//------------------------------------------------- +// ef9364_device - constructor +//------------------------------------------------- + +ef9364_device::ef9364_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, EF9364, "EF9364", tag, owner, clock, "ef9364", __FILE__), + device_memory_interface(mconfig, *this), + device_video_interface(mconfig, *this), + m_space_config("textram", ENDIANNESS_LITTLE, 8, 12, 0, nullptr, *ADDRESS_MAP_NAME(ef9364)), + m_palette(*this) +{ + clock_freq = clock; +} + +//------------------------------------------------- +// static_set_palette_tag: Set the tag of the +// palette device +//------------------------------------------------- + +void ef9364_device::static_set_palette_tag(device_t &device, const char *tag) +{ + downcast(device).m_palette.set_tag(tag); +} + +//------------------------------------------------- +// static_set_nb_of_pages: Set the number of hardware pages +//------------------------------------------------- + +void ef9364_device::static_set_nb_of_pages(device_t &device, int nb_of_pages ) +{ + if( nb_of_pages > 0 && nb_of_pages <= 8 ) + { + downcast(device).nb_of_pages = nb_of_pages; + } +} + +//------------------------------------------------- +// set_color_entry: Set the color value +// into the palette +//------------------------------------------------- + +void ef9364_device::set_color_entry( int index, UINT8 r, UINT8 g, UINT8 b ) +{ + if( index < 2 ) + { + palette[index] = rgb_t(r, g, b); + } + else + { + logerror("Invalid EF9364 Palette entry : %02x\n", index); + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void ef9364_device::device_start() +{ + m_textram = &space(0); + m_charset = region(); + + bitplane_xres = EF9364_NB_OF_COLUMNS*8; + bitplane_yres = EF9364_NB_OF_ROWS*(8+4); + + vsync_scanline_pos = 250; + + // Default palette : Black and white + palette[0] = rgb_t(0, 0, 0); + palette[1] = rgb_t(255, 255, 255); + + m_screen_out.allocate( bitplane_xres, m_screen->height() ); + + save_item(NAME(m_border)); + + save_item(NAME(m_screen_out)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void ef9364_device::device_reset() +{ + int i; + + x_curs_pos = 0; + y_curs_pos = 0; + + char_latch = 0x00; + + for(i=0;iwrite_byte ( i , 0x7F ); + } + + memset(m_border, 0, sizeof(m_border)); + + m_screen_out.fill(0); + + set_video_mode(); +} + +//------------------------------------------------- +// set_video_mode: Set output screen format +//------------------------------------------------- + +void ef9364_device::set_video_mode(void) +{ + UINT16 new_width = bitplane_xres; + + if (m_screen->width() != new_width) + { + rectangle visarea = m_screen->visible_area(); + visarea.max_x = new_width - 1; + + m_screen->configure(new_width, m_screen->height(), visarea, m_screen->frame_period().attoseconds()); + } + + //border color + memset(m_border, 0, sizeof(m_border)); +} + +//------------------------------------------------- +// draw_border: Draw the left and right borders +// ( No border for the moment ;) ) +//------------------------------------------------- + +void ef9364_device::draw_border(UINT16 line) +{ +} + +//------------------------------------------------- +// screen_update: Framebuffer video ouput +//------------------------------------------------- + +UINT32 ef9364_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int x,y,r; + unsigned char c; + + for( r = 0 ; r < EF9364_NB_OF_ROWS ; r++ ) + { + for( y = 0 ; y < 8 ; y++ ) + { + for( x = 0 ; x < EF9364_NB_OF_COLUMNS * 8 ; x++ ) + { + c = m_textram->read_byte( ( r * EF9364_NB_OF_COLUMNS ) + ( x>>3 ) ); + + if( m_charset->u8(((c&0x7F)<<3) + y ) & (0x80>>(x&7)) ) + m_screen_out.pix32((r*12)+y, x) = palette[1]; + else + m_screen_out.pix32((r*12)+y, x) = palette[0]; + } + } + } + + copybitmap(bitmap, m_screen_out, 0, 0, 0, 0, cliprect); + return 0; +} + +//------------------------------------------------- +// update_scanline: Scanline callback +//------------------------------------------------- + +void ef9364_device::update_scanline(UINT16 scanline) +{ + if (scanline == vsync_scanline_pos) + { + // vsync + } + + if (scanline == 0) + { + draw_border(0); + } +} + +//------------------------------------------------- +// data_w: Registers write access callback +//------------------------------------------------- + +void ef9364_device::command_w(UINT8 cmd) +{ + int x,y,i,j; + + switch( cmd&7 ) + { + case 0x0: // Page Erase ² Cursor hiom + for( y=0 ; y < EF9364_NB_OF_ROWS ; y++ ) + { + for( x=0 ; x < EF9364_NB_OF_COLUMNS ; x++ ) + { + m_textram->write_byte ( y * EF9364_NB_OF_COLUMNS + x , 0x7F ); + } + } + x_curs_pos = 0; + y_curs_pos = 0; + break; + + case 0x1: // Erase to end of the line and return cursor + for( ; x_curs_pos < EF9364_NB_OF_COLUMNS ; x_curs_pos++ ) + { + m_textram->write_byte ( y_curs_pos * EF9364_NB_OF_COLUMNS + x_curs_pos , 0x7F ); + } + x_curs_pos = 0; + break; + + case 0x2: // Line feed + y_curs_pos++; + if( y_curs_pos >= EF9364_NB_OF_ROWS ) + { + // Scroll + for( j = 1 ; j < EF9364_NB_OF_ROWS ; j++ ) + { + for( i = 0 ; i < EF9364_NB_OF_COLUMNS ; i++ ) + { + m_textram->write_byte ( (j-1) * EF9364_NB_OF_COLUMNS + i , m_textram->read_byte ( j * EF9364_NB_OF_COLUMNS + i ) ); + } + } + // Erase last line + for( i = 0 ; i < EF9364_NB_OF_COLUMNS ; i++ ) + { + m_textram->write_byte ( ( EF9364_NB_OF_ROWS - 1 ) * EF9364_NB_OF_COLUMNS + i , 0x7F ); + } + + y_curs_pos = EF9364_NB_OF_ROWS - 1; + } + break; + + case 0x3: // Nop + + break; + + case 0x4: // Cursor left + if(x_curs_pos) + x_curs_pos--; + break; + + case 0x5: // Erasure of cursor Line. + for( x = 0 ; x < EF9364_NB_OF_COLUMNS ; x++ ) + { + m_textram->write_byte ( y_curs_pos * EF9364_NB_OF_COLUMNS + x , 0x7F ); + } + break; + + case 0x6: // Cursor up + if(y_curs_pos) + y_curs_pos--; + break; + + case 0x7: // Write char + if(cmd&0x8) + m_textram->write_byte ( y_curs_pos * EF9364_NB_OF_COLUMNS + x_curs_pos , char_latch ); + + x_curs_pos++; + if( x_curs_pos >= EF9364_NB_OF_COLUMNS ) + { + x_curs_pos=0; + y_curs_pos++; + if( y_curs_pos >= EF9364_NB_OF_ROWS ) + y_curs_pos = EF9364_NB_OF_ROWS - 1; + } + break; + + } +} + +void ef9364_device::char_latch_w(UINT8 data) +{ + char_latch = data; +} diff --git a/src/devices/video/ef9364.h b/src/devices/video/ef9364.h new file mode 100644 index 00000000000..7456c9ad9e6 --- /dev/null +++ b/src/devices/video/ef9364.h @@ -0,0 +1,102 @@ +// license:BSD-3-Clause +// copyright-holders:Jean-Francois DEL NERO +/********************************************************************* + + ef9364.h + + Thomson EF9364 video controller + +*********************************************************************/ + +#pragma once + +#ifndef __EF9364_H__ +#define __EF9364_H__ + +#define EF9364_NB_OF_COLUMNS 64 +#define EF9364_NB_OF_ROWS 16 + +#define EF9364_TXTPLANE_MAX_SIZE ( EF9364_NB_OF_COLUMNS * EF9364_NB_OF_ROWS ) +#define EF9364_MAX_TXTPLANES 2 + +#define MCFG_EF9364_PALETTE(_palette_tag) \ + ef9364_device::static_set_palette_tag(*device, "^" _palette_tag); + +#define MCFG_EF9364_PAGES_CNT(_pages_number) \ + ef9364_device::static_set_nb_of_pages(*device,_pages_number); + +#define MCFG_EF9364_IRQ_HANDLER(_devcb) \ + devcb = &ef9364_device::set_irq_handler(*device, DEVCB_##_devcb); + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> ef9364_device + +class ef9364_device : public device_t, + public device_memory_interface, + public device_video_interface +{ +public: + // construction/destruction + ef9364_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // static configuration + static void static_set_palette_tag(device_t &device, const char *tag); + static void static_set_nb_of_pages(device_t &device, int nb_bitplanes ); + + // device interface + + void update_scanline(UINT16 scanline); + void set_color_entry( int index, UINT8 r, UINT8 g, UINT8 b ); + + UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + void char_latch_w(UINT8 data); + void command_w(UINT8 cmd); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_config_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override; + + // address space configurations + const address_space_config m_space_config; + + // inline helper + +private: + void screen_scanning( int force_clear ); + void set_video_mode(void); + void draw_border(UINT16 line); + + // internal state + + memory_region *m_charset; + address_space *m_textram; + + UINT8 x_curs_pos; + UINT8 y_curs_pos; + UINT8 char_latch; + + UINT8 m_border[80]; //border color + + rgb_t palette[2]; + int nb_of_pages; + int bitplane_xres; + int bitplane_yres; + int vsync_scanline_pos; + + UINT32 clock_freq; + bitmap_rgb32 m_screen_out; + + required_device m_palette; +}; + +// device type definition +extern const device_type EF9364; + +#endif