ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/vt102/vt102
(Generate patch)

Comparing vt102/vt102 (file contents):
Revision 1.14 by root, Wed Dec 3 02:13:41 2014 UTC vs.
Revision 1.20 by root, Wed Dec 3 08:17:16 2014 UTC

21#use common::sense; 21#use common::sense;
22 22
23my $VT102 = 1; 23my $VT102 = 1;
24my $VT131 = 0; 24my $VT131 = 0;
25my $AVO = 1; 25my $AVO = 1;
26my $KBD = 1;
27 26
28shift, ($VT102 = 0), ($AVO = 0) if $ARGV[0] =~ /^-?-vt100$/; 27shift, ($VT102 = 0), ($AVO = 0) if $ARGV[0] =~ /^-?-vt100$/;
29shift, ($VT102 = 0) if $ARGV[0] =~ /^-?-vt100\+avo$/; 28shift, ($VT102 = 0) if $ARGV[0] =~ /^-?-vt100\+avo$/;
30shift if $ARGV[0] =~ /^-?-vt102$/; 29shift if $ARGV[0] =~ /^-?-vt102$/;
31shift, ($VT131 = 1) if $ARGV[0] =~ /^-?-vt131$/; 30shift, ($VT131 = 1) if $ARGV[0] =~ /^-?-vt131$/;
32 31
32# vt100 wps = word processing roms
33# vt101 = vt102 - avo, but custom rom? really?
34# vt103 = vt100 + tu58 tape drive
35# vt125 = vt100 + gpo graphics processor
36# vt132 = vt100 + avo, stp
37# vt180 = vt100 + z80 cp/m
38
33if ($ARGV[0] =~ /^-/) { 39if ($ARGV[0] =~ /^-/) {
34 die <<EOF; 40 die <<EOF;
35 41
36VT102, A VT100/101/102/131 SIMULATOR 42VT102, A VT100/102/131 SIMULATOR
37 43
38Usage: 44Usage:
39 45
40 $0 [option] [program [args]] 46 $0 [option] [program [args]]
41 47
72EOF 78EOF
73} 79}
74 80
75############################################################################# 81#############################################################################
76# ROM/hardware init 82# ROM/hardware init
83
84my $PTY; # the pty we allocated, if any
85my $KBD = 1;
77 86
78my $ROMS = do { 87my $ROMS = do {
79 binmode DATA; 88 binmode DATA;
80 local $/; 89 local $/;
81 <DATA> 90 <DATA>
95} 104}
96 105
97############################################################################# 106#############################################################################
98# 8085 CPU registers and I/O support 107# 8085 CPU registers and I/O support
99 108
100my $PTY; # the pty we allocated, if any
101
102# 8080/8085 registers 109# 8080/8085 registers
103# b, c, d, e, h, l, a
104my ($A, $B, $C, $D, $E, $H, $L, $A); 110my ($A, $B, $C, $D, $E, $H, $L);
105my ($PC, $SP, $IFF, $FA, $FZ, $FS, $FP, $FC); 111my ($PC, $SP, $IFF, $FA, $FZ, $FS, $FP, $FC);
106 112
107my $RST = 0; # 8080 pending interrupts 113my $RST = 0; # 8080 pending interrupts
108my $INTMASK = 7; # 8085 half interrupts 114my $INTMASK = 7; # 8085 half interrupts
109my $INTPEND = 0; # 8085 half interrupts 115my $INTPEND = 0; # 8085 half interrupts
110
111my $x; # dummy temp for instructions
112 116
113my $CLK; # rather inexact clock 117my $CLK; # rather inexact clock
114 118
115############################################################################# 119#############################################################################
116# the dreaded NVR1400 chip. not needed to get it going, but provided anyway 120# the dreaded NVR1400 chip. not needed to get it going, but provided anyway
130 sub { $NVR[$_[0]] = 0x3fff; }, # 5 erase 134 sub { $NVR[$_[0]] = 0x3fff; }, # 5 erase
131 sub { $NVRDATA = $NVR[$_[0]]; }, # 6 read 135 sub { $NVRDATA = $NVR[$_[0]]; }, # 6 read
132 sub { }, # 7 standby 136 sub { }, # 7 standby
133); 137);
134 138
135my @bitidx; 139my @NVR_BITIDX;
136$bitidx[1 << $_] = 9 - $_ for 0..9; 140$NVR_BITIDX[1 << $_] = 9 - $_ for 0..9;
137 141
138# the nvr1400 state machine. what a monster 142# the nvr1400 state machine. what a monster
139sub nvr() { 143sub nvr() {
140 my $a1 = $bitidx[(~$NVRADDR ) & 0x3ff]; 144 my $a1 = $NVR_BITIDX[(~$NVRADDR ) & 0x3ff];
141 my $a0 = $bitidx[(~$NVRADDR >> 10) & 0x3ff]; 145 my $a0 = $NVR_BITIDX[(~$NVRADDR >> 10) & 0x3ff];
142 146
143# printf "NVR %02x A %020b %d %d D %02x\n", $NVRLATCH, $NVRADDR & 0xfffff, $a1, $a0, $NVRDATA; 147# printf "NVR %02x A %020b %d %d D %02x\n", $NVRLATCH, $NVRADDR & 0xfffff, $a1, $a0, $NVRDATA;
144 148
145 $NVRCMD[($NVRLATCH >> 1) & 7]($a1 * 10 + $a0, $NVRLATCH & 1) 149 $NVRCMD[($NVRLATCH >> 1) & 7]($a1 * 10 + $a0, $NVRLATCH & 1)
146} 150}
293sub in_1b { 0xff } # vt102 unknown 297sub in_1b { 0xff } # vt102 unknown
294 298
295############################################################################# 299#############################################################################
296# 8085 cpu opcodes and flag handling 300# 8085 cpu opcodes and flag handling
297 301
302my $x; # dummy scratchpad for opcodes
303
298sub sf { # set flags (ZSC - AP not implemented) 304sub sf { # set flags (ZSC - AP not implemented)
299 $FS = $_[0] & 0x080; 305 $FS = $_[0] & 0x080;
300 $FZ = !($_[0] & 0x0ff); 306 $FZ = !($_[0] & 0x0ff);
301 $FC = $_[0] & 0x100; 307 $FC = $_[0] & 0x100;
302 308
400$op[0xb0 + $_] = 'sf8 $A |= ' . $reg[$_] for 0..7; # ora 406$op[0xb0 + $_] = 'sf8 $A |= ' . $reg[$_] for 0..7; # ora
401$op[0xb8 + $_] = 'sf $x = $A - ' . $reg[$_] for 0..7; # cmp 407$op[0xb8 + $_] = 'sf $x = $A - ' . $reg[$_] for 0..7; # cmp
402# possible todo: optimize ora a, maybe xra a 408# possible todo: optimize ora a, maybe xra a
403 409
404$op[0xc6] = 'sf $A += IMM8'; # adi 410$op[0xc6] = 'sf $A += IMM8'; # adi
405# ce ADI NYI 411# ce ACI NYI, apparently unused
406$op[0xd6] = 'sf $A -= IMM8'; # sui 412$op[0xd6] = 'sf $A -= IMM8'; # sui
407# de SBI NYI 413# de SBI NYI, apparently unused
408$op[0xe6] = 'sf8 $A &= IMM8'; # ani 414$op[0xe6] = 'sf8 $A &= IMM8'; # ani
409$op[0xee] = 'sf8 $A ^= IMM8'; # xri 415$op[0xee] = 'sf8 $A ^= IMM8'; # xri
410$op[0xf6] = 'sf8 $A |= IMM8'; # ori 416$op[0xf6] = 'sf8 $A |= IMM8'; # ori
411$op[0xfe] = 'sf $A - IMM8'; # cpi 417$op[0xfe] = 'sf $A - IMM8'; # cpi
412 418
430$op[0xc9] = 'JMP POP + POP * 256'; # ret 436$op[0xc9] = 'JMP POP + POP * 256'; # ret
431 437
432$op[0xc7 + $_ * 8] = "JMP $_ * 8" for 0..7; # rst 438$op[0xc7 + $_ * 8] = "JMP $_ * 8" for 0..7; # rst
433 439
434$op[0xe9] = 'JMP $H * 256 + $L'; # pchl 440$op[0xe9] = 'JMP $H * 256 + $L'; # pchl
435# f9 SPHL NYI 441# f9 SPHL NYI, apparently unused
436 442
437$op[0x37] = '$FC = 1 '; # stc 443$op[0x37] = '$FC = 1 '; # stc
438$op[0x3f] = '$FC = !$FC'; # cmc 444$op[0x3f] = '$FC = !$FC'; # cmc
439 445
440$op[0xd3] = 'OUT'; # out 446$op[0xd3] = 'OUT'; # out
441$op[0xdb] = 'IN'; # in 447$op[0xdb] = 'IN'; # in
442 448
443$op[0xeb] = '($D, $E, $H, $L) = ($H, $L, $D, $E)'; # xchg 449$op[0xeb] = '($D, $E, $H, $L) = ($H, $L, $D, $E)'; # xchg
444 450
445# e3 xthl NYI # @ 917b, hl <-> (sp) 451# e3 xthl NYI # @ 917b in e69, hl <-> (sp)
446 452
447$op[0x20] = '$A = $INTPEND * 16 + $INTMASK + ($IFF && 8)'; # rim (incomplete) 453$op[0x20] = '$A = $INTPEND * 16 + $INTMASK + ($IFF && 8)'; # rim (incomplete)
448$op[0x30] = '$INTMASK = $A & 7 if $A & 8'; # sim (incomplete) 454$op[0x30] = '$INTMASK = $A & 7 if $A & 8'; # sim (incomplete)
449 455
450$op[0xf3] = '$IFF = 0'; # DI 456$op[0xf3] = '$IFF = 0'; # DI
747 eval "use integer; sub { $insn }" or die "$insn: $@" 753 eval "use integer; sub { $insn }" or die "$insn: $@"
748 })->(); 754 })->();
749 755
750 ++$CLK; 756 ++$CLK;
751 757
752 # things we do from time too time only 758 # things we do from time to time only
753 unless ($CLK & 0xf) { 759 unless ($CLK & 0xf) {
754 # do I/O 760 # do I/O
755 761
756 unless ($CLK & 0xfff) { 762 unless ($CLK & 0xfff) {
757 763
759 unless ((@PUSARTRECV >= 128) || @KQUEUE || !$PTY) { 765 unless ((@PUSARTRECV >= 128) || @KQUEUE || !$PTY) {
760 my $rin = ""; (vec $rin, fileno $PTY, 1) = 1; 766 my $rin = ""; (vec $rin, fileno $PTY, 1) = 1;
761 767
762 if (select $rin, undef, undef, 0) { 768 if (select $rin, undef, undef, 0) {
763 sysread $PTY, my $buf, 256; 769 sysread $PTY, my $buf, 256;
770
771 # linux don't do cs7 and/or parity anymore, so we need to filter
772 # out xoff characters to avoid freezes.
764 push @PUSARTRECV, unpack "C*", $buf; 773 push @PUSARTRECV, grep { ($_ & 0x7f) != 0x13 } unpack "C*", $buf;
765 } 774 }
766 } 775 }
767 776
768 # keyboard input 777 # keyboard input
769 if ($KBD) { 778 if ($KBD) {
801 # 6.5 vt125 mb7 read ready (something modem?) 810 # 6.5 vt125 mb7 read ready (something modem?)
802 # 7.5 vt125 mb7 vblank h(?) 811 # 7.5 vt125 mb7 vblank h(?)
803 # trap vt125 mbi init h(?) 812 # trap vt125 mbi init h(?)
804 my $vec; 813 my $vec;
805 814
806 $x = $INTPEND & ~$INTMASK; 815 my $pend = $INTPEND & ~$INTMASK;
807 816
808 if ($x & 1) { $vec = 0x2c; $INTPEND &= ~1; 817 if ($pend & 1) { $vec = 0x2c; $INTPEND &= ~1;
809 } elsif ($x & 2) { $vec = 0x34; $INTPEND &= ~2; 818 } elsif ($pend & 2) { $vec = 0x34; $INTPEND &= ~2;
810 } elsif ($x & 4) { $vec = 0x3c; $INTPEND &= ~4; 819 } elsif ($pend & 4) { $vec = 0x3c; $INTPEND &= ~4;
811# } elsif ($RST ) { $vec = $RST * 8; $RST = 0; # the vt102 firmware doesn't like combined interrupts 820# } elsif ($RST ) { $vec = $RST * 8; $RST = 0; # the vt102 firmware doesn't like combined interrupts
812 } elsif ($RST & 1) { $vec = 0x08; $RST &= ~1; # separate is better for vt102 821 } elsif ($RST & 1) { $vec = 0x08; $RST &= ~1; # separate is better for vt102
813 } elsif ($RST & 2) { $vec = 0x10; $RST &= ~2; 822 } elsif ($RST & 2) { $vec = 0x10; $RST &= ~2;
814 } elsif ($RST & 4) { $vec = 0x20; $RST &= ~4; 823 } elsif ($RST & 4) { $vec = 0x20; $RST &= ~4;
815 } else { 824 } else {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines