… | |
… | |
21 | # ./vt102 bash |
21 | # ./vt102 bash |
22 | # ./vt102 telnet towel.blinkenlights.nl |
22 | # ./vt102 telnet towel.blinkenlights.nl |
23 | # ./vt102 curl http://artscene.textfiles.com/vt100/trekvid.vt |
23 | # ./vt102 curl http://artscene.textfiles.com/vt100/trekvid.vt |
24 | # ./vt102 curl http://artscene.textfiles.com/vt100/surf.vt # in 3d! |
24 | # ./vt102 curl http://artscene.textfiles.com/vt100/surf.vt # in 3d! |
25 | |
25 | |
26 | # TODO: ctrl |
26 | use strict; |
27 | |
27 | use feature qw(state); |
28 | use common::sense; |
28 | #use common::sense; |
29 | |
29 | |
30 | $| = 1; |
30 | $| = 1; |
31 | |
31 | |
32 | my $VT102 = 1; |
32 | my $VT102 = 1; |
33 | my $AVO = $VT102 || 1; |
33 | my $AVO = $VT102 || 1; |
… | |
… | |
477 | |
477 | |
478 | line: |
478 | line: |
479 | for my $y (0 .. 25) { # ntsc, two vblank delay lines, up to 24 text lines |
479 | for my $y (0 .. 25) { # ntsc, two vblank delay lines, up to 24 text lines |
480 | my $prev_sgr; |
480 | my $prev_sgr; |
481 | |
481 | |
482 | $scr .= sprintf "%2d |", ++$y; |
482 | $scr .= sprintf "%2d \xe2\x94\x82", $y; |
483 | |
483 | |
484 | for (0..139) { |
484 | for (0..139) { |
485 | my $c = $M[$i]; |
485 | my $c = $M[$i]; |
486 | |
486 | |
487 | if ($c == 0x7f) { # also 0xff, but the firmware avoids that |
487 | if ($c == 0x7f) { # also 0xff, but the firmware avoids that |
488 | $scr .= "\e[m|\e[K\n"; |
488 | $scr .= "\e[m\xe2\x94\x82\e[K\n"; |
489 | |
489 | |
490 | my $a1 = $M[$i + 1]; |
490 | my $a1 = $M[$i + 1]; |
491 | my $a0 = $M[$i + 2]; |
491 | my $a0 = $M[$i + 2]; |
492 | |
492 | |
493 | $i = 0x2000 + (($a1 * 256 + $a0) & 0xfff); |
493 | $i = 0x2000 + (($a1 * 256 + $a0) & 0xfff); |
… | |
… | |
584 | 0x7b, -0x7b, # leave setup |
584 | 0x7b, -0x7b, # leave setup |
585 | ); |
585 | ); |
586 | |
586 | |
587 | ############################################################################# |
587 | ############################################################################# |
588 | |
588 | |
589 | # 0x80 shift, 0x100 ctrl, 0x200 toggle |
589 | # 0x080 shift, 0x100 ctrl |
590 | my %KEYMAP = ( |
590 | my %KEYMAP = ( |
|
|
591 | # these get overwritten by generic control codes, but both work, so i have no priority |
|
|
592 | # tid fix these. |
591 | "\t" => 0x3a, |
593 | "\t" => 0x3a, |
592 | "\r" => 0x64, |
594 | "\r" => 0x64, |
593 | "\n" => 0x44, |
595 | "\n" => 0x44, |
594 | |
596 | |
|
|
597 | "\x00" => 0x77 | 0x100, # CTRL-SPACE |
|
|
598 | "\x1c" => 0x45 | 0x100, # CTRL-\ |
|
|
599 | "\x1d" => 0x14 | 0x100, # CTRL-] |
|
|
600 | "\x1e" => 0x24 | 0x100, # CTRL-~ |
|
|
601 | "\x1f" => 0x75 | 0x100, # CTRL-? |
|
|
602 | |
595 | # hardcoded rxvt keys |
603 | # hardcoded rxvt keys |
596 | "\e" => 0x2a, # ESC |
604 | "\e" => 0x2a, # ESC |
597 | "\e[3~" => 0x03, # DC |
605 | "\e[3~" => 0x03, # DC |
598 | "\e[5~" => 0x7e, # CAPS LOCK (prior) |
606 | "\e[5~" => 0x7e, # CAPS LOCK (prior) |
599 | "\e[6~" => 0x6a, # NO SCROLL (next) |
607 | "\e[6~" => 0x6a, # NO SCROLL (next) |
600 | "\e[A" => 0x30, # UP |
608 | "\e[A" => 0x30, # UP |
601 | "\e[B" => 0x22, # DOWN |
609 | "\e[B" => 0x22, # DOWN |
602 | "\e[C" => 0x10, # RIGHT |
610 | "\e[C" => 0x10, # RIGHT |
603 | "\e[D" => 0x20, # LEFT |
611 | "\e[D" => 0x20, # LEFT |
604 | "\e[a" => 0x30 | 0x080, # UP |
612 | "\e[a" => 0x30 | 0x080, # UP |
605 | "\e[b" => 0x22 | 0x080, # DOWN |
613 | "\e[b" => 0x22 | 0x080, # DOWN |
606 | "\e[c" => 0x10 | 0x080, # RIGHT |
614 | "\e[c" => 0x10 | 0x080, # RIGHT |
607 | "\e[d" => 0x20 | 0x080, # LEFT |
615 | "\e[d" => 0x20 | 0x080, # LEFT |
608 | "\e[7~" => 0x7b, # SETUP (home) |
616 | "\e[7~" => 0x7b, # SETUP (home) |
609 | "\e[8~" => 0x23, # BREAK (end) |
617 | "\e[8~" => 0x23, # BREAK (end) |
610 | "\e[8\$" => 0x23 | 0x080, # SHIFT BREAK / DISCONNECT (shift-end) |
618 | "\e[8\$" => 0x23 | 0x080, # SHIFT BREAK / DISCONNECT (shift-end) |
611 | "\x7f" => 0x33, # BACKSPACE |
619 | "\x7f" => 0x33, # BACKSPACE |
612 | |
620 | |
613 | "\e[11~" => 0x32, # F1 |
621 | "\e[11~" => 0x32, # F1 |
614 | "\e[11~" => 0x42, # F2 |
622 | "\e[11~" => 0x42, # F2 |
615 | "\e[11~" => 0x31, # F3 |
623 | "\e[11~" => 0x31, # F3 |
616 | "\e[11~" => 0x41, # F4 |
624 | "\e[11~" => 0x41, # F4 |
617 | ); |
625 | ); |
618 | |
626 | |
619 | @KEYMAP{map chr, 0x20..0x40} = unpack "C*", pack "H*", |
627 | @KEYMAP{map chr, 0x20..0x40} = unpack "C*", pack "H*", |
620 | "779ad5a9a8b8a755a6b5b6b466256575" . "351a3929283837273626d656e634e5f5" . "b9"; |
628 | "779ad5a9a8b8a755a6b5b6b466256575" . "351a3929283837273626d656e634e5f5" . "b9"; |
621 | |
629 | |
622 | @KEYMAP{map chr, 0x5b .. 0x7e} = unpack "C*", pack "H*", |
630 | @KEYMAP{map chr, 0x5b .. 0x7e} = unpack "C*", pack "H*", |
623 | "154514b7a5" . "244a6879591949485816574746766706" . "050a185a0817780969077a95c594a4"; |
631 | "154514b7a5" . "244a6879591949485816574746766706" . "050a185a0817780969077a95c594a4"; |
624 | |
632 | |
625 | $KEYMAP{"\x3f" & $_} ||= $KEYMAP{$_} | 0x100 for "a" .. "z"; # ctrl |
633 | $KEYMAP{"\x1f" & $_} ||= $KEYMAP{$_} | 0x100 for "a" .. "z"; # ctrl |
626 | $KEYMAP{uc $_} ||= $KEYMAP{$_} | 0x080 for "a" .. "z"; # shift |
634 | $KEYMAP{uc $_} ||= $KEYMAP{$_} | 0x080 for "a" .. "z"; # shift |
627 | |
635 | |
628 | my $KEYMATCH = join "|", map quotemeta, reverse sort keys %KEYMAP; |
636 | my $KEYMATCH = join "|", map quotemeta, reverse sort keys %KEYMAP; |
629 | $KEYMATCH = qr{^($KEYMATCH)}s; |
637 | $KEYMATCH = qr{^($KEYMATCH)}s; |
630 | |
638 | |