1 // license:GPL-2.0+
2 // copyright-holders:Raphael Nabet
3 /*
4 TI 911 VDT core. To be operated with the TI 990 line of computers (can be connected to
5 any model, as communication uses the CRU bus).
6
7 Raphael Nabet 2002
8
9 TODO:
10 * add more flexibility, so that we can create multiple-terminal configurations.
11 * support test mode???
12 */
13
14
15 #include "emu.h"
16 #include "911_vdt.h"
17 #include "911_chr.h"
18 #include "911_key.h"
19
20 #include "speaker.h"
21
22
23 #define MAX_VDT 1
24
25 static const gfx_layout fontlayout_7bit =
26 {
27 7, 10, /* 7*10 characters */
28 128, /* 128 characters */
29 1, /* 1 bit per pixel */
30 { 0 },
31 { 1, 2, 3, 4, 5, 6, 7 }, /* straightforward layout */
32 { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8 },
33 10*8 /* every char takes 10 consecutive bytes */
34 };
35
36 static const gfx_layout fontlayout_8bit =
37 {
38 7, 10, /* 7*10 characters */
39 128, /* 128 characters */
40 1, /* 1 bit per pixel */
41 { 0 },
42 { 1, 2, 3, 4, 5, 6, 7 }, /* straightforward layout */
43 { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8 },
44 10*8 /* every char takes 10 consecutive bytes */
45 };
46
47 static GFXDECODE_START( gfx_vdt911 )
48 // Caution: Array must use same order as vdt911_model_t
49 // US
50 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::US_chr_offset, fontlayout_7bit, 0, 4 )
51
52 // UK
53 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::UK_chr_offset, fontlayout_7bit, 0, 4 )
54
55 // French (without accented characters)
56 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::US_chr_offset, fontlayout_7bit, 0, 4 )
57
58 // German
59 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::german_chr_offset, fontlayout_7bit, 0, 4 )
60
61 // Swedish
62 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::swedish_chr_offset, fontlayout_7bit, 0, 4 )
63
64 // Norwegian
65 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::norwegian_chr_offset, fontlayout_7bit, 0, 4 )
66
67 // Japanese
68 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::japanese_chr_offset, fontlayout_8bit, 0, 4 )
69
70 // Arabic
71 // GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::arabic_chr_offset, fontlayout_8bit, 0, 4 )
72
73 // FrenchWP (contains accented characters)
74 GFXDECODE_ENTRY( vdt911_chr_region, vdt911_device::frenchWP_chr_offset, fontlayout_7bit, 0, 4 )
75 GFXDECODE_END
76
77 static constexpr rgb_t vdt911_colors[] =
78 {
79 { 0x00, 0x00, 0x00 }, // black
80 { 0xc0, 0xc0, 0xc0 }, // low intensity
81 { 0xff, 0xff, 0xff } // high intensity
82 };
83
84 static const unsigned short vdt911_pens[] =
85 {
86 0, 2, // high intensity
87 0, 1, // low intensity
88 2, 0, // high intensity, reverse
89 2, 1 // low intensity, reverse
90 };
91
92 /*
93 Macros for model features
94 */
95 /* TRUE for Japanese and Arabic terminals, which use 8-bit charcodes and keyboard shift modes */
96 #define USES_8BIT_CHARCODES() ((m_model == model::Japanese) /*|| (m_model == model::Arabic)*/)
97 /* TRUE for keyboards which have this extra key (on the left of TAB/SKIP)
98 (Most localized keyboards have it) */
99 #define HAS_EXTRA_KEY_67() (! ((m_model == model::US) || (m_model == model::UK) || (m_model == model::French)))
100 /* TRUE for keyboards which have this extra key (on the right of space),
101 AND do not use it as a modifier */
102 #define HAS_EXTRA_KEY_91() ((m_model == model::German) || (m_model == model::Swedish) || (m_model == model::Norwegian))
103
104 /*
105 Initialize vdt911 palette
106 */
vdt911_palette(palette_device & palette) const107 void vdt911_device::vdt911_palette(palette_device &palette) const
108 {
109 for (int i = 0; i < ARRAY_LENGTH(vdt911_colors); i++)
110 palette.set_indirect_color(i, vdt911_colors[i]);
111
112 for (int i = 0; i < ARRAY_LENGTH(vdt911_pens); i++)
113 palette.set_pen_indirect(i, vdt911_pens[i]);
114 }
115
116 /*
117 Copy a character bitmap array to another location in memory
118 */
copy_character_matrix_array(const uint8_t char_array[128][10],uint8_t * dest)119 static void copy_character_matrix_array(const uint8_t char_array[128][10], uint8_t *dest)
120 {
121 int i, j;
122
123 for (i=0; i<128; i++)
124 for (j=0; j<10; j++)
125 *(dest++) = char_array[i][j];
126 }
127
128 /*
129 Patch a character bitmap array according to an array of char_override_t
130 */
apply_char_overrides(int nb_char_overrides,const char_override_t char_overrides[],uint8_t * dest)131 static void apply_char_overrides(int nb_char_overrides, const char_override_t char_overrides[], uint8_t *dest)
132 {
133 int i, j;
134
135 for (i=0; i<nb_char_overrides; i++)
136 {
137 for (j=0; j<10; j++)
138 dest[char_overrides[i].char_index*10+j] = char_defs[char_overrides[i].symbol_index][j];
139 }
140 }
141
142 DEFINE_DEVICE_TYPE(VDT911, vdt911_device, "vdt911", "911 VDT")
143
vdt911_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)144 vdt911_device::vdt911_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
145 : device_t(mconfig, VDT911, tag, owner, clock)
146 , device_gfx_interface(mconfig, *this, gfx_vdt911, "palette")
147 , m_beeper(*this, "beeper")
148 , m_screen(*this, "screen")
149 , m_keys(*this, "KEY%u", 0U)
150 , m_keyint_line(*this)
151 , m_lineint_line(*this)
152 {
153 }
154
155 enum
156 {
157 BLINK_TIMER,
158 BEEP_TIMER,
159 LINE_TIMER
160 };
161
162 //-------------------------------------------------
163 // device_start - device-specific startup
164 //-------------------------------------------------
165
device_start()166 void vdt911_device::device_start()
167 {
168 m_last_key_pressed = 0x80;
169
170 m_keyboard_data_ready = false;
171 m_display_enable = false;
172 m_blink_state = false;
173
174 m_keyint_line.resolve();
175 m_lineint_line.resolve();
176
177 /* set up cursor blink clock. 2Hz frequency -> .25s half-period. */
178 /*m_blink_clock =*/
179
180 m_blink_timer = timer_alloc(BLINK_TIMER);
181 m_beep_timer = timer_alloc(BEEP_TIMER);
182 m_line_timer = timer_alloc(LINE_TIMER);
183
184 m_blink_timer->adjust(attotime::from_msec(0), 0, attotime::from_msec(250));
185
186 uint8_t *base;
187 uint8_t *chr = machine().root_device().memregion(vdt911_chr_region)->base();
188
189 /* set up US character definitions */
190 base = chr+US_chr_offset;
191 copy_character_matrix_array(char_defs+char_defs_US_base, base);
192
193 /* set up UK character definitions */
194 base = chr+UK_chr_offset;
195 copy_character_matrix_array(char_defs+char_defs_US_base, base);
196 apply_char_overrides(sizeof(UK_overrides)/sizeof(char_override_t), UK_overrides, base);
197
198 /* French character set is identical to US character set */
199
200 /* set up German character definitions */
201 base = chr+german_chr_offset;
202 copy_character_matrix_array(char_defs+char_defs_US_base, base);
203 apply_char_overrides(sizeof(german_overrides)/sizeof(char_override_t), german_overrides, base);
204
205 /* set up Swedish/Finnish character definitions */
206 base = chr+swedish_chr_offset;
207 copy_character_matrix_array(char_defs+char_defs_US_base, base);
208 apply_char_overrides(sizeof(swedish_overrides)/sizeof(char_override_t), swedish_overrides, base);
209
210 /* set up Norwegian/Danish character definitions */
211 base = chr+norwegian_chr_offset;
212 copy_character_matrix_array(char_defs+char_defs_US_base, base);
213 apply_char_overrides(sizeof(norwegian_overrides)/sizeof(char_override_t), norwegian_overrides, base);
214
215 /* set up French word processing character definitions */
216 base = chr+frenchWP_chr_offset;
217 copy_character_matrix_array(char_defs+char_defs_US_base, base);
218 apply_char_overrides(sizeof(frenchWP_overrides)/sizeof(char_override_t), frenchWP_overrides, base);
219
220 /* set up Katakana Japanese character definitions */
221 base = chr+japanese_chr_offset;
222 copy_character_matrix_array(char_defs+char_defs_US_base, base);
223 apply_char_overrides(sizeof(japanese_overrides)/sizeof(char_override_t), japanese_overrides, base);
224 base = chr+japanese_chr_offset+128*single_char_len;
225 copy_character_matrix_array(char_defs+char_defs_katakana_base, base);
226
227 #if 0
228 /* set up Arabic character definitions */
229 base = chr+arabic_chr_offset;
230 copy_character_matrix_array(char_defs+char_defs_US_base, base);
231 apply_char_overrides(sizeof(arabic_overrides)/sizeof(char_override_t), arabic_overrides, base);
232 base = chr+arabic_chr_offset+128*single_char_len;
233 copy_character_matrix_array(char_defs+char_defs_arabic_base, base);
234 #endif
235 }
236
237
device_reset()238 void vdt911_device::device_reset()
239 {
240 m_model = model(ioport("LOCALE")->read());
241 m_screen_size = screen_size(ioport("SCREEN")->read());
242
243 if (m_screen_size == screen_size::char_960)
244 m_cursor_address_mask = 0x3ff; /* 1kb of RAM */
245 else
246 m_cursor_address_mask = 0x7ff; /* 2 kb of RAM */
247
248 // European models have 50 Hz
249 int lines = (m_model == model::US) || (m_model == model::Japanese) ? 262 : 314;
250 attotime refresh = attotime::from_hz(11.004_MHz_XTAL / 700 / lines);
251 m_screen->configure(700, lines, m_screen->visible_area(), refresh.as_attoseconds());
252 m_line_timer->adjust(attotime::from_msec(0), 0, refresh);
253 }
254
255 /*
256 Timer callbacks
257 */
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)258 void vdt911_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
259 {
260 switch (id)
261 {
262 case BLINK_TIMER:
263 m_blink_state = !m_blink_state;
264 break;
265 case BEEP_TIMER:
266 m_beeper->set_state(0);
267 break;
268 case LINE_TIMER:
269 check_keyboard();
270 m_lineint_line(ASSERT_LINE);
271 m_lineint_line(CLEAR_LINE);
272 break;
273 }
274 }
275
276 /*
277 CRU interface read
278 */
cru_r(offs_t offset)279 uint8_t vdt911_device::cru_r(offs_t offset)
280 {
281 int reply=0;
282
283 offset &= 0xf;
284
285 if (!m_word_select)
286 { /* select word 0 */
287 switch (offset >> 3)
288 {
289 case 0:
290 reply = m_display_RAM[m_cursor_address];
291 break;
292
293 case 1:
294 reply = m_keyboard_data & 0x7f;
295 if (m_keyboard_data_ready)
296 reply |= 0x80;
297 break;
298 }
299 }
300 else
301 { /* select word 1 */
302 switch (offset >> 3)
303 {
304 case 0:
305 reply = m_cursor_address & 0xff;
306 break;
307
308 case 1:
309 reply = (m_cursor_address >> 8) & 0x07;
310 if (m_keyboard_data & 0x80)
311 reply |= 0x08;
312 /*if (!m_terminal_ready)
313 reply |= 0x10;*/
314 if (m_previous_word_select)
315 reply |= 0x20;
316 /*if (m_keyboard_parity_error)
317 reply |= 0x40;*/
318 if (m_keyboard_data_ready)
319 reply |= 0x80;
320 break;
321 }
322 }
323
324 return BIT(reply, offset & 3);
325 }
326
327 /*
328 CRU interface write
329 */
cru_w(offs_t offset,uint8_t data)330 void vdt911_device::cru_w(offs_t offset, uint8_t data)
331 {
332 offset &= 0xf;
333
334 if (!m_word_select)
335 { /* select word 0 */
336 switch (offset)
337 {
338 case 0x0:
339 case 0x1:
340 case 0x2:
341 case 0x3:
342 case 0x4:
343 case 0x5:
344 case 0x6:
345 case 0x7:
346 /* display memory write data */
347 if (data)
348 m_data_reg |= (1 << offset);
349 else
350 m_data_reg &= ~ (1 << offset);
351 break;
352
353 case 0x8:
354 /* write data strobe */
355 m_display_RAM[m_cursor_address] = m_data_reg;
356 break;
357
358 case 0x9:
359 /* test mode */
360 /* ... */
361 break;
362
363 case 0xa:
364 /* cursor move */
365 if (data)
366 m_cursor_address--;
367 else
368 m_cursor_address++;
369 m_cursor_address &= m_cursor_address_mask;
370 break;
371
372 case 0xb:
373 /* blinking cursor enable */
374 m_blinking_cursor_enable = data;
375 break;
376
377 case 0xc:
378 /* keyboard interrupt enable */
379 m_keyboard_interrupt_enable = data;
380 m_keyint_line(m_keyboard_interrupt_enable && m_keyboard_data_ready);
381 break;
382
383 case 0xd:
384 /* dual intensity enable */
385 m_dual_intensity_enable = data;
386 break;
387
388 case 0xe:
389 /* display enable */
390 m_display_enable = data;
391 break;
392
393 case 0xf:
394 /* select word */
395 m_previous_word_select = m_word_select;
396 m_word_select = data;
397 break;
398 }
399 }
400 else
401 { /* select word 1 */
402 switch (offset)
403 {
404 case 0x0:
405 case 0x1:
406 case 0x2:
407 case 0x3:
408 case 0x4:
409 case 0x5:
410 case 0x6:
411 case 0x7:
412 case 0x8:
413 case 0x9:
414 case 0xa:
415 /* cursor address */
416 if (data)
417 m_cursor_address |= (1 << offset);
418 else
419 m_cursor_address &= ~ (1 << offset);
420 m_cursor_address &= m_cursor_address_mask;
421 break;
422
423 case 0xb:
424 /* not used */
425 break;
426
427 case 0xc:
428 /* display cursor */
429 m_display_cursor = data;
430 break;
431
432 case 0xd:
433 /* keyboard acknowledge */
434 if (m_keyboard_data_ready)
435 {
436 m_keyboard_data_ready = 0;
437 if (m_keyboard_interrupt_enable)
438 m_keyint_line(CLEAR_LINE);
439 }
440 /*m_keyboard_parity_error = 0;*/
441 break;
442
443 case 0xe:
444 /* beep enable strobe - not tested */
445 m_beeper->set_state(1);
446 m_beep_timer->adjust(attotime::from_usec(300));
447 break;
448
449 case 0xf:
450 /* select word */
451 m_previous_word_select = m_word_select;
452 m_word_select = data;
453 break;
454 }
455 }
456 }
457
458 /*
459 Video refresh
460 */
refresh(bitmap_ind16 & bitmap,const rectangle & cliprect,int x,int y)461 void vdt911_device::refresh(bitmap_ind16 &bitmap, const rectangle &cliprect, int x, int y)
462 {
463 gfx_element *gfx = this->gfx(unsigned(m_model));
464 int height = (m_screen_size == screen_size::char_960) ? 12 : 24;
465
466 int use_8bit_charcodes = USES_8BIT_CHARCODES();
467 int address = 0;
468 int i, j;
469 int cur_char;
470 int color;
471
472 /*if (use_8bit_charcodes)
473 color = vdt->dual_intensity_enable ? 1 : 0;*/
474
475 if (!m_display_enable)
476 {
477 rectangle my_rect(x, x + 80*7 - 1, y, y + height*10 - 1);
478
479 bitmap.fill(0, my_rect);
480 }
481 else
482 {
483 for (i=0; i<height; i++)
484 {
485 for (j=0; j<80; j++)
486 {
487 cur_char = m_display_RAM[address];
488 /* does dual intensity work with 8-bit character set? */
489 color = (m_dual_intensity_enable && (cur_char & 0x80)) ? 1 : 0;
490 if (!use_8bit_charcodes)
491 cur_char &= 0x7f;
492
493 /* display cursor in reverse video */
494 if ((address == m_cursor_address) && m_display_cursor
495 && ((!m_blinking_cursor_enable) || m_blink_state))
496 color += 2;
497
498 address++;
499
500 gfx->opaque(bitmap, cliprect, cur_char, color, 0, 0,
501 x+j*7, y+i*10);
502 }
503 }
504 }
505 }
506
507 static const unsigned char (*const key_translate[])[91] =
508 { /* array must use same order as vdt911_model_t!!! */
509 /* US */
510 US_key_translate,
511 /* UK */
512 US_key_translate,
513 /* French */
514 French_key_translate,
515 /* German */
516 German_key_translate,
517 /* Swedish */
518 Swedish_key_translate,
519 /* Norwegian */
520 Norwegian_key_translate,
521 /* Japanese */
522 Japanese_key_translate,
523 /* Arabic */
524 /*Arabic_key_translate,*/
525 /* FrenchWP */
526 FrenchWP_key_translate
527 };
528
529 /*
530 keyboard handler: should be called regularly by machine code, for instance
531 every Video Blank Interrupt.
532 */
check_keyboard()533 void vdt911_device::check_keyboard()
534 {
535 enum modifier_state_t
536 {
537 /* states for Western keyboards and katakana/Arabic keyboards in romaji/Latin mode */
538 lower_case = 0, upper_case, shift, control,
539 /* states for katakana/Arabic keyboards in katakana/Arabic mode */
540 foreign, foreign_shift,
541 /* special value to stop repeat if the modifier state changes */
542 special_debounce = -1
543 };
544
545 static unsigned char repeat_timer;
546 enum { repeat_delay = 5 /* approx. 1/10s */ };
547
548 uint16_t key_buf[6];
549 int i, j;
550 modifier_state_t modifier_state;
551 int repeat_mode;
552
553 /* read current key state */
554 for (i = 0; i < 6; i++)
555 {
556 key_buf[i] = m_keys[i]->read();
557 }
558
559 /* parse modifier keys */
560 if ((USES_8BIT_CHARCODES())
561 && ((key_buf[5] & 0x0400) || ((!(key_buf[5] & 0x0100)) && m_foreign_mode)))
562 { /* we are in katakana/Arabic mode */
563 m_foreign_mode = true;
564
565 if ((key_buf[4] & 0x0400) || (key_buf[5] & 0x0020))
566 modifier_state = foreign_shift;
567 else
568 modifier_state = foreign;
569 }
570 else
571 { /* we are using a Western keyboard, or a katakana/Arabic keyboard in
572 romaji/Latin mode */
573 m_foreign_mode = false;
574
575 if (key_buf[3] & 0x0040)
576 modifier_state = control;
577 else if ((key_buf[4] & 0x0400) || (key_buf[5] & 0x0020))
578 modifier_state = shift;
579 else if ((key_buf[0] & 0x2000))
580 modifier_state = upper_case;
581 else
582 modifier_state = lower_case;
583 }
584
585
586 /* test repeat key */
587 repeat_mode = key_buf[2] & 0x0002;
588
589
590 /* remove modifier keys */
591 key_buf[0] &= ~0x2000;
592 key_buf[2] &= ~0x0002;
593 key_buf[3] &= ~0x0040;
594 key_buf[4] &= ~0x0400;
595 key_buf[5] &= ~0x0120;
596
597 /* remove unused keys */
598 if (! HAS_EXTRA_KEY_91())
599 key_buf[5] &= ~0x0400;
600
601 if (! HAS_EXTRA_KEY_67())
602 key_buf[4] &= ~0x0004;
603
604
605 if (! repeat_mode)
606 /* reset REPEAT timer if the REPEAT key is not pressed */
607 repeat_timer = 0;
608
609 if (!(m_last_key_pressed & 0x80) && (key_buf[m_last_key_pressed >> 4] & (1 << (m_last_key_pressed & 0xf))))
610 {
611 /* last key has not been released */
612 if (modifier_state == m_last_modifier_state)
613 {
614 /* handle REPEAT mode if applicable */
615 if ((repeat_mode) && (++repeat_timer == repeat_delay))
616 {
617 if (m_keyboard_data_ready)
618 { /* keyboard buffer full */
619 repeat_timer--;
620 }
621 else
622 { /* repeat current key */
623 m_keyboard_data_ready = 1;
624 repeat_timer = 0;
625 }
626 }
627 }
628 else
629 {
630 repeat_timer = 0;
631 m_last_modifier_state = special_debounce;
632 }
633 }
634 else
635 {
636 m_last_key_pressed = 0x80;
637
638 if (m_keyboard_data_ready)
639 { /* keyboard buffer full */
640 /* do nothing */
641 }
642 else
643 {
644 for (i=0; i<6; i++)
645 {
646 for (j=0; j<16; j++)
647 {
648 if (key_buf[i] & (1 << j))
649 {
650 m_last_key_pressed = (i << 4) | j;
651 m_last_modifier_state = modifier_state;
652
653 m_keyboard_data = (int)key_translate[unsigned(m_model)][modifier_state][m_last_key_pressed];
654 m_keyboard_data_ready = 1;
655 if (m_keyboard_interrupt_enable)
656 m_keyint_line(ASSERT_LINE);
657 return;
658 }
659 }
660 }
661 }
662 }
663 }
664
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)665 uint32_t vdt911_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
666 {
667 refresh(bitmap, cliprect, 0, 0);
668 return 0;
669 }
670
671 INPUT_PORTS_START( vdt911 )
672 PORT_START( "LOCALE" )
673 PORT_CONFNAME( 0x0f, 0x00, "Terminal language" )
ioport_value(vdt911_device::model::US)674 PORT_CONFSETTING( ioport_value(vdt911_device::model::US), "English US" )
675 PORT_CONFSETTING( ioport_value(vdt911_device::model::UK), "English UK" )
676 PORT_CONFSETTING( ioport_value(vdt911_device::model::French), "French" )
677 PORT_CONFSETTING( ioport_value(vdt911_device::model::German), "German" )
678 PORT_CONFSETTING( ioport_value(vdt911_device::model::Swedish), "Swedish" )
679 PORT_CONFSETTING( ioport_value(vdt911_device::model::Norwegian), "Norwegian" )
680 PORT_CONFSETTING( ioport_value(vdt911_device::model::Japanese), "Japanese" )
681 // PORT_CONFSETTING( ioport_value(vdt911_device::model::Arabic), "Arabic" )
682 PORT_CONFSETTING( ioport_value(vdt911_device::model::FrenchWP), "French Word Processing" )
683
684 PORT_START( "SCREEN" )
685 PORT_CONFNAME( 0x01, ioport_value(vdt911_device::screen_size::char_960), "Terminal screen size" )
686 PORT_CONFSETTING( ioport_value(vdt911_device::screen_size::char_960), "960 chars (12 lines)")
687 PORT_CONFSETTING( ioport_value(vdt911_device::screen_size::char_1920), "1920 chars (24 lines)")
688
689 PORT_START("KEY0") /* keys 1-16 */ \
690 PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) \
691 PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) \
692 PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) \
693 PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) \
694 PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) \
695 PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) \
696 PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) \
697 PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) \
698 PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("CMD") PORT_CODE(KEYCODE_F9) \
699 PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(red)") PORT_CODE(KEYCODE_F10) \
700 PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ERASE FIELD") PORT_CODE(KEYCODE_END) \
701 PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ERASE INPUT") PORT_CODE(KEYCODE_PGDN) \
702 PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(grey)") PORT_CODE(KEYCODE_F11) \
703 PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("UPPER CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE\
704 PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) \
705 PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) \
706 \
707 PORT_START("KEY1") /* keys 17-32 */ \
708 PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) \
709 PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) \
710 PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) \
711 PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) \
712 PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) \
713 PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) \
714 PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) \
715 PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) \
716 PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("+ [") PORT_CODE(KEYCODE_MINUS) \
717 PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("- ]") PORT_CODE(KEYCODE_EQUALS) \
718 PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("_ =") PORT_CODE(KEYCODE_BACKSPACE) \
719 PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) \
720 PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7 (numpad)") PORT_CODE(KEYCODE_7_PAD) \
721 PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8 (numpad)") PORT_CODE(KEYCODE_8_PAD) \
722 PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9 (numpad)") PORT_CODE(KEYCODE_9_PAD) \
723 PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PRINT") PORT_CODE(KEYCODE_PRTSCR) \
724 \
725 PORT_START("KEY2") /* keys 33-48 */ \
726 PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(up)") PORT_CODE(KEYCODE_UP) \
727 PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("REPEAT") PORT_CODE(KEYCODE_LALT) \
728 PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER_PAD) \
729 PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) \
730 PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) \
731 PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) \
732 PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) \
733 PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) \
734 PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) \
735 PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) \
736 PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) \
737 PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) \
738 PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) \
739 PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("CHAR (left/right)") PORT_CODE(KEYCODE_OPENBRACE) \
740 PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("FIELD (left/right)") PORT_CODE(KEYCODE_CLOSEBRACE) \
741 PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) \
742 \
743 PORT_START("KEY3") /* keys 49-64 */ \
744 PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4 (numpad)") PORT_CODE(KEYCODE_4_PAD) \
745 PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5 (numpad)") PORT_CODE(KEYCODE_5_PAD) \
746 PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6 (numpad)") PORT_CODE(KEYCODE_6_PAD) \
747 PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(left)") PORT_CODE(KEYCODE_LEFT) \
748 PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("HOME") PORT_CODE(KEYCODE_HOME) \
749 PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(right)") PORT_CODE(KEYCODE_RIGHT) \
750 PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("CONTROL") PORT_CODE(KEYCODE_LCONTROL) \
751 PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) \
752 PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) \
753 PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) \
754 PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) \
755 PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) \
756 PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) \
757 PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) \
758 PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) \
759 PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) \
760 \
761 PORT_START("KEY4") /* keys 65-80 */ \
762 PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) \
763 PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) \
764 PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(not on US keyboard)") PORT_CODE(KEYCODE_BACKSLASH) \
765 PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SKIP TAB") PORT_CODE(KEYCODE_TAB) \
766 PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1 (numpad)") PORT_CODE(KEYCODE_1_PAD) \
767 PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2 (numpad)") PORT_CODE(KEYCODE_2_PAD) \
768 PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3 (numpad)") PORT_CODE(KEYCODE_3_PAD) \
769 PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("INS CHAR") PORT_CODE(KEYCODE_INSERT) \
770 PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(down)") PORT_CODE(KEYCODE_DOWN) \
771 PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DEL CHAR") PORT_CODE(KEYCODE_DEL) \
772 PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) \
773 PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) \
774 PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) \
775 PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) \
776 PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) \
777 PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) \
778 \
779 PORT_START("KEY5") /* keys 81-91 */ \
780 PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) \
781 PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) \
782 PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) \
783 PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) \
784 PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) \
785 PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_RSHIFT) \
786 PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0 (numpad)") PORT_CODE(KEYCODE_0_PAD) \
787 PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(". (numpad)") PORT_CODE(KEYCODE_DEL_PAD) \
788 PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(not on US keyboard)") PORT_CODE(KEYCODE_MINUS_PAD) \
789 PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) \
790 PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(not on US keyboard)") PORT_CODE(KEYCODE_PLUS_PAD)
791 INPUT_PORTS_END
792
793 //-------------------------------------------------
794 // device_add_mconfig - add device configuration
795 //-------------------------------------------------
796
797 void vdt911_device::device_add_mconfig(machine_config &config)
798 {
799 SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
800 m_screen->set_raw(11.004_MHz_XTAL, 700, 0, 560, 262, 0, 240);
801 m_screen->set_screen_update(FUNC(vdt911_device::screen_update));
802 m_screen->set_palette("palette");
803
804 SPEAKER(config, "speaker").front_center();
805 BEEP(config, m_beeper, 3250).add_route(ALL_OUTPUTS, "speaker", 0.50);
806
807 PALETTE(config, "palette", FUNC(vdt911_device::vdt911_palette), ARRAY_LENGTH(vdt911_pens), ARRAY_LENGTH(vdt911_colors));
808 }
809
device_input_ports() const810 ioport_constructor vdt911_device::device_input_ports() const
811 {
812 return INPUT_PORTS_NAME( vdt911 );
813 }
814