… | |
… | |
21 | #use common::sense; |
21 | #use common::sense; |
22 | |
22 | |
23 | my $VT102 = 1; |
23 | my $VT102 = 1; |
24 | my $VT131 = 0; |
24 | my $VT131 = 0; |
25 | my $AVO = 1; |
25 | my $AVO = 1; |
26 | my $KBD = 1; |
|
|
27 | |
26 | |
28 | if ($ARGV[0] =~ /^-?-vt100$/) { |
27 | shift, ($VT102 = 0), ($AVO = 0) if $ARGV[0] =~ /^-?-vt100$/; |
29 | shift; $VT102 = 0; $AVO = 0; |
28 | shift, ($VT102 = 0) if $ARGV[0] =~ /^-?-vt100\+avo$/; |
30 | } |
29 | shift if $ARGV[0] =~ /^-?-vt102$/; |
31 | |
30 | shift, ($VT131 = 1) if $ARGV[0] =~ /^-?-vt131$/; |
32 | if ($ARGV[0] =~ /^-?-vt100\+avo$/) { |
|
|
33 | shift; $VT102 = 0; $AVO = 1; |
|
|
34 | } |
|
|
35 | |
|
|
36 | if ($ARGV[0] =~ /^-?-vt102$/) { |
|
|
37 | shift; # default |
|
|
38 | } |
|
|
39 | |
|
|
40 | if ($ARGV[0] =~ /^-?-vt131$/) { |
|
|
41 | shift; $VT131 = 1; |
|
|
42 | } |
|
|
43 | |
31 | |
44 | if ($ARGV[0] =~ /^-/) { |
32 | if ($ARGV[0] =~ /^-/) { |
45 | die <<EOF; |
33 | die <<EOF; |
46 | |
34 | |
47 | VT102, A VT100/101/102/131 SIMULATOR |
35 | VT102, A VT100/101/102/131 SIMULATOR |
… | |
… | |
84 | } |
72 | } |
85 | |
73 | |
86 | ############################################################################# |
74 | ############################################################################# |
87 | # ROM/hardware init |
75 | # ROM/hardware init |
88 | |
76 | |
|
|
77 | my $PTY; # the pty we allocated, if any |
|
|
78 | my $KBD = 1; |
|
|
79 | |
89 | my $ROMS = do { |
80 | my $ROMS = do { |
90 | binmode DATA; |
81 | binmode DATA; |
91 | local $/; |
82 | local $/; |
92 | <DATA> |
83 | <DATA> |
93 | }; |
84 | }; |
94 | |
85 | |
95 | 0x6801 == length $ROMS or die "corrupted rom image"; |
86 | 0x6801 == length $ROMS or die "corrupted rom image"; |
96 | |
|
|
97 | binmode STDOUT; |
|
|
98 | |
87 | |
99 | my @M = (0xff) x 65536; # main memory, = (0xff) x 65536; |
88 | my @M = (0xff) x 65536; # main memory, = (0xff) x 65536; |
100 | |
89 | |
101 | # populate mem with rom contents |
90 | # populate mem with rom contents |
102 | if ($VT102) { |
91 | if ($VT102) { |
… | |
… | |
108 | } |
97 | } |
109 | |
98 | |
110 | ############################################################################# |
99 | ############################################################################# |
111 | # 8085 CPU registers and I/O support |
100 | # 8085 CPU registers and I/O support |
112 | |
101 | |
113 | my $PTY; # the pty we allocated, if any |
|
|
114 | |
|
|
115 | # 8080/8085 registers |
102 | # 8080/8085 registers |
116 | # b, c, d, e, h, l, a |
|
|
117 | my ($A, $B, $C, $D, $E, $H, $L, $A); |
103 | my ($A, $B, $C, $D, $E, $H, $L); |
118 | my ($PC, $SP, $IFF, $FA, $FZ, $FS, $FP, $FC); |
104 | my ($PC, $SP, $IFF, $FA, $FZ, $FS, $FP, $FC); |
119 | |
105 | |
120 | my $RST = 0; # 8080 pending interrupts |
106 | my $RST = 0; # 8080 pending interrupts |
121 | my $INTMASK = 7; # 8085 half interrupts |
107 | my $INTMASK = 7; # 8085 half interrupts |
122 | my $INTPEND = 0; # 8085 half interrupts |
108 | my $INTPEND = 0; # 8085 half interrupts |
… | |
… | |
143 | sub { $NVR[$_[0]] = 0x3fff; }, # 5 erase |
129 | sub { $NVR[$_[0]] = 0x3fff; }, # 5 erase |
144 | sub { $NVRDATA = $NVR[$_[0]]; }, # 6 read |
130 | sub { $NVRDATA = $NVR[$_[0]]; }, # 6 read |
145 | sub { }, # 7 standby |
131 | sub { }, # 7 standby |
146 | ); |
132 | ); |
147 | |
133 | |
148 | my @bitidx; |
134 | my @NVR_BITIDX; |
149 | $bitidx[1 << $_] = 9 - $_ for 0..9; |
135 | $NVR_BITIDX[1 << $_] = 9 - $_ for 0..9; |
150 | |
136 | |
151 | # the nvr1400 state machine. what a monster |
137 | # the nvr1400 state machine. what a monster |
152 | sub nvr() { |
138 | sub nvr() { |
153 | my $a1 = $bitidx[(~$NVRADDR ) & 0x3ff]; |
139 | my $a1 = $NVR_BITIDX[(~$NVRADDR ) & 0x3ff]; |
154 | my $a0 = $bitidx[(~$NVRADDR >> 10) & 0x3ff]; |
140 | my $a0 = $NVR_BITIDX[(~$NVRADDR >> 10) & 0x3ff]; |
155 | |
141 | |
156 | # printf "NVR %02x A %020b %d %d D %02x\n", $NVRLATCH, $NVRADDR & 0xfffff, $a1, $a0, $NVRDATA; |
142 | # printf "NVR %02x A %020b %d %d D %02x\n", $NVRLATCH, $NVRADDR & 0xfffff, $a1, $a0, $NVRDATA; |
157 | |
143 | |
158 | $NVRCMD[($NVRLATCH >> 1) & 7]($a1 * 10 + $a0, $NVRLATCH & 1) |
144 | $NVRCMD[($NVRLATCH >> 1) & 7]($a1 * 10 + $a0, $NVRLATCH & 1) |
159 | } |
145 | } |
… | |
… | |
498 | $M[$PC], $op[$M[$PC]]; |
484 | $M[$PC], $op[$M[$PC]]; |
499 | } |
485 | } |
500 | |
486 | |
501 | ############################################################################# |
487 | ############################################################################# |
502 | # video emulation |
488 | # video emulation |
|
|
489 | |
|
|
490 | binmode STDOUT; |
503 | |
491 | |
504 | my @CHARMAP = ( |
492 | my @CHARMAP = ( |
505 | " " , "\x{29eb}", "\x{2592}", "\x{2409}", |
493 | " " , "\x{29eb}", "\x{2592}", "\x{2409}", |
506 | "\x{240c}", "\x{240d}", "\x{240a}", "\x{00b0}", |
494 | "\x{240c}", "\x{240d}", "\x{240a}", "\x{00b0}", |
507 | "\x{00b1}", "\x{2424}", "\x{240b}", "\x{2518}", |
495 | "\x{00b1}", "\x{2424}", "\x{240b}", "\x{2518}", |
… | |
… | |
750 | |
738 | |
751 | $insn .= "$op;\n"; |
739 | $insn .= "$op;\n"; |
752 | } |
740 | } |
753 | |
741 | |
754 | |
742 | |
755 | $insn .= "$pc"; |
743 | $insn .= $pc; |
756 | $insn =~ s/\x00.*$//s; |
744 | $insn =~ s/\x00.*$//s; |
757 | |
745 | |
758 | eval "use integer; sub { $insn }" or die "$insn: $@" |
746 | eval "use integer; sub { $insn }" or die "$insn: $@" |
759 | })->(); |
747 | })->(); |
760 | |
748 | |
… | |
… | |
841 | # vt100 @ 0x0000+0x0800 23-032E2 |
829 | # vt100 @ 0x0000+0x0800 23-032E2 |
842 | # vt100 @ 0x0800+0x0800 23-061E2 |
830 | # vt100 @ 0x0800+0x0800 23-061E2 |
843 | # vt100 @ 0x1000+0x0800 23-033E2 |
831 | # vt100 @ 0x1000+0x0800 23-033E2 |
844 | # vt100 @ 0x1800+0x0800 23-034E2 |
832 | # vt100 @ 0x1800+0x0800 23-034E2 |
845 | # |
833 | # |
846 | # vt102 @ 0x0000+0x8000 23-226E4 |
834 | # vt102 @ 0x0000+0x2000 23-226E4 |
847 | # vt102 @ 0x8000+0x8000 23-225E4 |
835 | # vt102 @ 0x8000+0x2000 23-225E4 |
848 | # |
836 | # |
849 | # vt131 @ 0xa000+0x0800 23-280E2 |
837 | # vt131 @ 0xa000+0x0800 23-280E2 |
850 | # |
838 | # |
851 | |
839 | |
852 | __DATA__ |
840 | __DATA__ |