diff options
Diffstat (limited to 'src/mess/video/pc4.c')
-rw-r--r-- | src/mess/video/pc4.c | 194 |
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; +} |