summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/video/pc4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/video/pc4.c')
-rw-r--r--src/mess/video/pc4.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/mess/video/pc4.c b/src/mess/video/pc4.c
new file mode 100644
index 00000000000..1f2a5e0981f
--- /dev/null
+++ b/src/mess/video/pc4.c
@@ -0,0 +1,194 @@
+/***************************************************************************
+
+ VTech Laser PC4 LCD controller emulation
+
+***************************************************************************/
+
+#include "emu.h"
+#include "includes/pc4.h"
+
+void pc4_state::set_busy_flag(UINT16 usec)
+{
+ m_busy_flag = 1;
+ m_busy_timer->adjust( attotime::from_usec( usec ) );
+}
+
+UINT32 pc4_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(0, cliprect);
+
+ if (m_display_on)
+ for (int l=0; l<4; l++)
+ for (int i=0; i<40; i++)
+ {
+ UINT16 char_pos = l*40 + i;
+
+ for (int y=0; y<8; y++)
+ for (int x=0; x<5; x++)
+ if (m_ddram[char_pos] <= 0x10)
+ {
+ //draw CGRAM characters
+ bitmap.pix16(l*9 + y, i*6 + x) = BIT(m_cgram[(m_ddram[char_pos]&0x07)*8+y], 4-x);
+ }
+ else
+ {
+ //draw CGROM characters
+ bitmap.pix16(l*9 + y, i*6 + x) = BIT(machine().root_device().memregion("charset")->base()[m_ddram[char_pos]*8+y], 4-x);
+
+ }
+
+ // if is the correct position draw cursor and blink
+ if (char_pos == m_cursor_pos)
+ {
+ //draw the cursor
+ if (m_cursor_on)
+ for (int x=0; x<5; x++)
+ bitmap.pix16(l*9 + 7, i * 6 + x) = 1;
+
+ if (!m_blink && m_blink_on)
+ for (int y=0; y<7; y++)
+ for (int x=0; x<5; x++)
+ bitmap.pix16(l*9 + y, i * 6 + x) = 1;
+ }
+ }
+
+ return 0;
+
+}
+
+void pc4_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch(id)
+ {
+ case BUSY_TIMER:
+ m_busy_flag = 0;
+ break;
+
+ case BLINKING_TIMER:
+ m_blink = !m_blink;
+ break;
+ }
+}
+
+WRITE8_MEMBER(pc4_state::lcd_control_w)
+{
+ if (BIT(data, 7))
+ {
+ m_ac_mode = 0;
+ m_cursor_pos = m_ac = data & 0x7f;
+ set_busy_flag(37);
+ }
+ else if (BIT(data, 6))
+ {
+ m_ac_mode = 1;
+ m_ac = data & 0x3f;
+ set_busy_flag(37);
+ }
+ else if (BIT(data, 5))
+ {
+ m_cursor_on = BIT(data, 3);
+
+ set_busy_flag(37);
+ }
+ else if (BIT(data, 4))
+ {
+ UINT8 direct = (BIT(data, 2)) ? +1 : -1;
+
+ if (BIT(data, 3))
+ m_disp_shift += direct;
+ else
+ {
+ m_ac += direct;
+ m_cursor_pos += direct;
+ }
+
+ set_busy_flag(37);
+ }
+ else if (BIT(data, 3))
+ {
+ m_display_on = BIT(data, 2);
+ //m_cursor_on = BIT(data, 1);
+ m_blink_on = BIT(data, 0);
+
+ set_busy_flag(37);
+ }
+ else if (BIT(data, 2))
+ {
+ m_direction = (BIT(data, 1)) ? +1 : -1;
+ m_shift_on = BIT(data, 0);
+ set_busy_flag(37);
+ }
+ else if (BIT(data, 1))
+ {
+ m_ac = 0;
+ m_cursor_pos = 0;
+ m_ac_mode = 0;
+ m_direction = 1;
+ m_disp_shift = 0;
+ set_busy_flag(520);
+ }
+ else if (BIT(data, 0))
+ {
+ m_ac = 0;
+ m_cursor_pos = 0;
+ m_ac_mode = 0;
+ m_direction = 1;
+ m_disp_shift = 0;
+ memset(m_ddram, 0x20, sizeof(m_ddram));
+ set_busy_flag(520);
+ }
+}
+
+
+READ8_MEMBER(pc4_state::lcd_control_r)
+{
+ return m_busy_flag<<7 || m_ac&0x7f;
+}
+
+void pc4_state::update_ac(void)
+{
+ int new_ac = m_ac + m_direction;
+ m_ac = (new_ac < 0) ? 0 : ((new_ac >= 0xa0) ? 0xa0 : new_ac);
+
+ if (m_ac_mode == 0)
+ {
+ m_cursor_pos = m_ac;
+ // display is shifted only after a write
+ if (m_shift_on && m_data_bus_flag == 1) m_disp_shift += m_direction;
+ }
+
+ m_data_bus_flag = 0;
+}
+
+WRITE8_MEMBER( pc4_state::lcd_offset_w )
+{
+ m_cursor_pos = m_ac = (data%0xa0);
+}
+
+
+WRITE8_MEMBER(pc4_state::lcd_data_w)
+{
+ if (m_ac_mode == 0)
+ m_ddram[m_ac] = data;
+ else
+ m_cgram[m_ac] = data;
+
+ update_ac();
+ set_busy_flag(41);
+}
+
+READ8_MEMBER(pc4_state::lcd_data_r)
+{
+ UINT8 data;
+
+ if (m_ac_mode == 0)
+ data = m_ddram[m_ac];
+ else
+ data = m_cgram[m_ac];
+
+ m_data_bus_flag = 2;
+ update_ac();
+ set_busy_flag(41);
+
+ return data;
+}