Support for VT100 dot stretching
This commit is contained in:
parent
37593a107d
commit
f7464dd182
7 changed files with 4890 additions and 4701 deletions
|
|
@ -34,11 +34,42 @@ See [DEC VT100 ROMs](/devices/pc8080/rom/vt100/) for more information about the
|
|||
(aka [phooky](https://github.com/phooky) aka Adam Mayer) further explains VT100 memory usage:
|
||||
|
||||
Start End Size Description
|
||||
0x0000 0x1fff 8K Basic ROM
|
||||
0x2000 0x2012 18B Blank lines for refresh (6 x 3B)
|
||||
0x2012 0x204f 61B Stack area (grows down from 0x204e)
|
||||
0x204f 0x22d0 641B Scratch Pad/Setup Area(?)
|
||||
0x22d0 0x2c00 2352B Screen RAM
|
||||
0x0000 0x1fff 8K Basic ROM
|
||||
0x2000 0x2012 18 Blank lines for refresh (6 x 3B)
|
||||
0x2012 0x204f 61 Stack area (grows down from 0x204e)
|
||||
0x204f 0x22d0 641 Scratch Pad/Setup Area(?)
|
||||
0x22d0 0x2c00 2352 Screen RAM
|
||||
|
||||
Note: 0x22bb through 0x22d0 appear to be unused
|
||||
|
||||
In his [Platform Notes](https://github.com/phooky/VT100-Hax/blob/master/Platform%20Notes.md), he further describes
|
||||
portions of the "Scratch Pad" area:
|
||||
|
||||
Start End Size Description
|
||||
0x2052 0x2054 2 0x2004 during init?
|
||||
0x2068 0x2069 1 Keys flag buffer
|
||||
0x206a 0x206e 3 New keys pressed buffer
|
||||
0x20f6 0x20f8 2 0x22d0 during init?
|
||||
0x2014 0x2015 1 0xff during init? [Typo or reference to a byte in the Stack area? -JP]
|
||||
|
||||
and the "Setup" area:
|
||||
|
||||
Start End Size Description
|
||||
0x217b 22 Answerback message (20chars+2delim)
|
||||
0x2191 17 Tabs (bit encoding) (first bit always set)
|
||||
0x21a2 1 80/132 col mode (00 = 80 col, 01 = 132 col)
|
||||
0x21a3 1 intensity (00 = brightest, 0x1f = dimmest)
|
||||
0x21a4 1 Mode byte for PUSART
|
||||
0x21a5 1 Online/local
|
||||
0x21a6 1 Switches 1
|
||||
0x21a7 1 Switches 2
|
||||
0x21a8 1 Switches 3
|
||||
0x21a9 1 Switches 4
|
||||
0x21aa 1 Switches 5
|
||||
0x21ab 1 TX baud rate
|
||||
0x21ac 1 RX baud rate
|
||||
0x21ad 1 parity
|
||||
0x21ae 1 nvr checksum
|
||||
|
||||
VT100 I/O Ports
|
||||
---------------
|
||||
|
|
@ -78,11 +109,11 @@ information about the Flags buffer (port 0x42):
|
|||
|
||||
Bit Active? Description
|
||||
7 H KBD Transmit Buffer Empty
|
||||
6 H LBA 7(?) (It's a pin on the backplane connector...) - used to clock NVR - line buffer address
|
||||
6 H NVR CLOCK, driven by LBA7 (line buffer address)
|
||||
5 H NVR DATA
|
||||
4 L EVEN FIELD (comes out of the video timing generator)
|
||||
3 H OPTION PRESENT (terminal output option???)
|
||||
2 L GRAPHICS FLAG (is VT52 graphics card present) [I think he meant VT125 -JP]
|
||||
2 L GRAPHICS FLAG (is VT125 graphics card present)
|
||||
1 L ADVANCED VIDEO (is AVO present)
|
||||
0 H XMIT FLAG
|
||||
|
||||
|
|
@ -127,6 +158,65 @@ measure 2.0mm x 3.35mm (in 132-column mode, they measure 1.3mm x 3.35mm), which
|
|||
roughly 160mm x 80mm, implying a screen aspect ratio of 2.0. However, after visually comparing the Technical Manual's SET-UP
|
||||
screenshots to our test screens, 1.67 appears to be closer to reality than 2.0. I'll revisit this issue at a later date.
|
||||
|
||||
VT100 Initialization Process
|
||||
----------------------------
|
||||
|
||||
From "Power-Up and Self-Test", section 4.2.8, p. 4-19, of the VT100 Technical Manual (July 1982):
|
||||
|
||||
When power is first applied to the terminal controller board, the reset circuit in the 8224 holds the microprocessor
|
||||
in a halt state. Within a second, after the voltages stabilize in the power supply, the RC network at the reset input
|
||||
allows tlhe input voltage to rise to the switching threshold of a Schmitt trigger. Then the reset is released with the
|
||||
8080 program counter set to 0. The low 64 bytes of program are reserved for the eight interrupt service routines which
|
||||
can be addressed by the restart instruction (see previous section). The low 8 start the power-up routine by disabling
|
||||
the interrupts, setting up the stack pointer, and then going immediately into the self-test routines.
|
||||
|
||||
Assuming there are no hard logic failures present on the board, the microprocessor attempts to perform a confidence
|
||||
check of the controller. Some failures are considered fatal and will stop the machine; other failures limit its operation
|
||||
but win not prevent its use. Fatal failures are indicated by the LEDs on the keyboard, while nonfatal errors are indicated
|
||||
as a single character on the screen.
|
||||
|
||||
The microprocessor first sends the number of the first ROM to the LEDs on the keyboard. Then it calculates a checksum
|
||||
of the contents of the first 2K of program. (Since firmware is treated as four 2K blocks of code, later VT100s with one
|
||||
8K X 8 ROM chip operate the same way but any block failure requires replacement of the one chip). At the time of ROM
|
||||
preparation, a special byte was included within each block to make the checksum equal zero if there are no errors. If
|
||||
there is an error, the microprocessor halts and the LEDs indicate the current ROM at the time of failure. Otherwise, the
|
||||
LEDs are incremented to show the next ROM number and the process continues.
|
||||
|
||||
The next part of the test is writing and reading the RAM. Every bit in the RAM is written with a 0 and a 1 and read each
|
||||
time. If the advanced video option is present (as indicated by the Option Present flag), its RAM is tested immediately
|
||||
after the main RAM. In the main RAM a failure halts the machine. Failure of a bit in the advanced video option RAM is
|
||||
indicated on the screen and the process continues. In another termnnal, the VT52, one bad bit in the screen RAM means there
|
||||
is one location that may not contain right character. This can be annoying to the user but does not affect the rest of the
|
||||
screen. If one bit is bad in a VT100 line address, the entire screen below the affected line can become garbled and unsuable.
|
||||
A bad bit in the scratch area could disable communication with the host. So this confidence check ensures that any RAM
|
||||
failure is detected immediately.
|
||||
|
||||
The next test checks the nonvola1tile RAM by reading it. A checksum is calculated and compared with the value stored the
|
||||
last time the NVR was written during a save. A bad NVR does not stop the VT100 because the SET-UP values can always be
|
||||
reestablished from the keyboard at power-up. The NVR test is also the normal time when the terminal gets its auto SET-UP
|
||||
readings from the NVR. Time is saved because reading the NVR is the most time-consuming part of both the self-test and the
|
||||
auto SET-UP. If the NVR fails, the bell sounds several times to inform the operator, and then default settings stored in
|
||||
the ROM allow the terminal to work. The operator must then manually reset any parameters that differ from the default values.
|
||||
|
||||
To test the keyboard, the microprocessor commands the keyboard to scan once, lights all the LEDs, for about a half second,
|
||||
and sounds the bell. It waits for the scan to finish and then looks for the last key address 7FH at the keyboard UART.
|
||||
If the test fails, the terminal remains on-line, making it a receive-only (RO) terminal.
|
||||
|
||||
This is the end of testing.
|
||||
|
||||
Once the NVR data is in the scratch area in RAM, the microprocessor uses that data to program the hardware. All operating
|
||||
parameters that were last saved (see NVR) are recalled and the terminal is set to match them. Finally the cursor appears
|
||||
at column 1, line 1, and the microprocessor enters its background routine, ready for operation.
|
||||
|
||||
Some additional observations:
|
||||
|
||||
- During the NVR test, a "WAIT" message is displayed in the top-left corner of the screen.
|
||||
- Following the NVR test, code at 0x00D2 loops for 0xFFF (4095) times with the CLICK bit (0x80) set in the keyboard STATUS
|
||||
port (0x82), generating a "bell" (beep), presumably because the NVR test failed. And one would expect the NVR checksum test
|
||||
to fail, since we initialize all NVR words with the freshly-erased value of 0x3fff. Also, at some point before arriving at the
|
||||
preceding loop, the "WAIT" message has been cleared.
|
||||
|
||||
|
||||
Additional VT100 Resources
|
||||
--------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -26,15 +26,18 @@ He then describes the memory map as follows:
|
|||
E52 H H L 0x0800
|
||||
E56 H L L 0x0000
|
||||
|
||||
The above PCB chip locations correspond to the following [DEC ROM](/devices/roms/dec/) dumps:
|
||||
The above PCB chip locations correspond to the following [DEC ROMs](/devices/roms/dec/):
|
||||
|
||||
* E56: [23-061E2.bin](https://web.archive.org/web/20140723115846/http://www.dunnington.u-net.com/public/DECROMs/23-061E2.bin)
|
||||
* E52: [23-032E2.bin](https://web.archive.org/web/20140723115846/http://www.dunnington.u-net.com/public/DECROMs/23-032E2.bin)
|
||||
* E45: [23-033E2.bin](https://web.archive.org/web/20140723115846/http://www.dunnington.u-net.com/public/DECROMs/23-033E2.bin)
|
||||
* E40: [23-034E2.bin](https://web.archive.org/web/20140723115846/http://www.dunnington.u-net.com/public/DECROMs/23-034E2.bin)
|
||||
|
||||
And sure enough, concatenating those four DEC ROM dumps produced a perfect match for Trammell Hudson's
|
||||
[VT100.bin](http://trmm.net/images/2/20/VT100.bin).
|
||||
And sure enough, concatenating those four DEC ROMs:
|
||||
|
||||
cat 23-061E2.bin 23-032E2.bin 23-033E2.bin 23-034E2.bin > VT100.bin
|
||||
|
||||
produces a perfect match for Trammell Hudson's [VT100.bin](http://trmm.net/images/2/20/VT100.bin).
|
||||
|
||||
### Character Generator (2Kb)
|
||||
|
||||
|
|
@ -46,7 +49,7 @@ The ROM contains 128 rows of character data, 16 bytes per character. More on th
|
|||
Following in the footsteps of [vt100romhax](http://vt100romhax.tumblr.com/post/90697428973/the-vt100-memory-map-and-8080-disassembly),
|
||||
I disassembled the ROM, using `dz80` from [D52](http://www.brouhaha.com/~eric/software/d52/) ([manual](http://www.bipom.com/documents/dis51/d52manual.html)):
|
||||
|
||||
dz80 -80 archive/VT100.bin
|
||||
dz80 -80 VT100.bin
|
||||
|
||||
This produced VT100.d80, which I renamed to [VT100.asm](VT100.asm). I fixed one `dz80` bug, replacing references to
|
||||
`X2000` with `2000h`, and then hand-merged most of the comments from [haxrom.d80](https://github.com/phooky/VT100-Hax/blob/master/ROMs/haxrom.d80).
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ X0000: di
|
|||
jmp X003b
|
||||
|
||||
org 8
|
||||
|
||||
;
|
||||
; Interrupt vector 0x1 for keyboard
|
||||
;
|
||||
X0008: call X00fd
|
||||
ei
|
||||
ret
|
||||
|
|
@ -160,6 +162,9 @@ X00c4: jz X00cb
|
|||
X00cb: mvi a,2fh
|
||||
sta X21c9
|
||||
out 62h
|
||||
;
|
||||
; Prepare to enter the "beep" loop
|
||||
;
|
||||
X00d2: lxi b,X0fff
|
||||
ei
|
||||
X00d6: mvi a,8
|
||||
|
|
@ -172,7 +177,10 @@ X00e0: out 82h
|
|||
mov a,b
|
||||
ora c
|
||||
jnz X00d6
|
||||
out 82h
|
||||
;
|
||||
; Done "beeping" now
|
||||
;
|
||||
X00e8: out 82h ; A = 0, so all LEDs off now
|
||||
lda X2068
|
||||
ora a
|
||||
jm X00f5
|
||||
|
|
@ -180,7 +188,28 @@ X00e0: out 82h
|
|||
ori 4
|
||||
mov d,a
|
||||
X00f5: push d
|
||||
|
||||
;
|
||||
; The next call issues the following:
|
||||
;
|
||||
; 03A2 CD8103 CALL 0381 ;stack=204A
|
||||
; 0B67 CDAD10 CALL 10AD ;stack=2048
|
||||
; chipset.outPort(0x00A2,DC012,0x00) at 10BD
|
||||
; chipset.outPort(0x00A2,DC012,0x04) at 10C1
|
||||
;
|
||||
; and then:
|
||||
;
|
||||
; 03A2 CD8103 CALL 0381 ;stack=204A
|
||||
; 0B67 CDAD10 CALL 10AD ;stack=2048
|
||||
; 10C9 CDAA0F CALL 0FAA ;stack=2046
|
||||
; 0FB6 CC8814 CALLZ 1488 ;stack=2040
|
||||
; 1488 CD9314 CALL 1493 ;stack=203E
|
||||
; chipset.inPort(0x0042,FLAGS.BUFFER): 0x60 at 1493
|
||||
;
|
||||
; Note that once we're inside 0FAA, that appears to be where we stay.
|
||||
;
|
||||
call X03a2
|
||||
|
||||
pop d
|
||||
jmp X0875
|
||||
;;
|
||||
|
|
@ -934,10 +963,10 @@ X06a7: mov a,d
|
|||
ora a
|
||||
ret
|
||||
|
||||
X06aa: lda X2068
|
||||
X06aa: lda X2068 ; A <- [Keys flag buffer]
|
||||
mov e,a
|
||||
ani 80h
|
||||
rz
|
||||
ani 80h ; bit 7 set?
|
||||
rz ; return if not
|
||||
lxi h,X0841
|
||||
push h
|
||||
mov a,e
|
||||
|
|
@ -2344,6 +2373,22 @@ X0f9e: ora m
|
|||
mov m,a
|
||||
ret
|
||||
|
||||
;
|
||||
; Main loop?
|
||||
;
|
||||
; Absent any interrupts, execution gravitates here:
|
||||
;
|
||||
; 0FAA:
|
||||
; ...
|
||||
; call 1488
|
||||
; call 1493 ; read port 0x42 (check flags buffer)
|
||||
; call 06aa ; check byte at [2068]
|
||||
; cli
|
||||
; call 0e3e ; fetch byte at [21A5], OR byte at [207B]
|
||||
; sti
|
||||
; ; return byte at [2172] in A
|
||||
; jmp 0FAE
|
||||
;
|
||||
X0faa: lxi h,X207f
|
||||
add m
|
||||
X0fae: cmp m
|
||||
|
|
@ -2356,6 +2401,9 @@ X0fb2: lda X207b
|
|||
pop psw
|
||||
pop h
|
||||
jmp X0fae
|
||||
;
|
||||
; End of main loop?
|
||||
;
|
||||
|
||||
X0fbe: lhld X204e
|
||||
mov a,h
|
||||
|
|
@ -4728,46 +4776,7 @@ X1fd4: ora a
|
|||
|
||||
; Last but not least, pad out to 8K (8192) bytes
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
org 1fffh
|
||||
nop
|
||||
|
||||
; Miscellaneous equates
|
||||
|
|
@ -4797,7 +4806,7 @@ X205b equ 205bh
|
|||
X205c equ 205ch
|
||||
X2065 equ 2065h
|
||||
X2067 equ 2067h
|
||||
X2068 equ 2068h
|
||||
X2068 equ 2068h ; Keys flag buffer
|
||||
X2069 equ 2069h
|
||||
X206a equ 206ah
|
||||
X206e equ 206eh
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -100,6 +100,12 @@ function ChipSet(parmsChipSet)
|
|||
|
||||
Component.subclass(ChipSet);
|
||||
|
||||
/*
|
||||
* NOTE: The STATUS1 port could have been handled entirely by the Keyboard component, but it was just as easy
|
||||
* to create a simple ChipSet interface, updateStatus1(), that the Keyboard calls whenever it wants to simulate a
|
||||
* button press or release. It's a six-of-one, half-a-dozen-of-another choice, since technically, Space Invaders
|
||||
* doesn't have a keyboard.
|
||||
*/
|
||||
ChipSet.SI1978 = {
|
||||
MODEL: 1978.1,
|
||||
STATUS0: { // NOTE: STATUS0 not used by the SI1978 ROMs; refer to STATUS1 instead
|
||||
|
|
@ -168,8 +174,33 @@ ChipSet.SI1978 = {
|
|||
*
|
||||
* <cpu id="cpu8080" model="8080" cycles="2764800"/>
|
||||
*
|
||||
* where 2764800 = 24883200 / 9. Beyond that, we don't really care about that particular 8224. I only mention it
|
||||
* because knowing the CPU frequency is helpful for simulating some of the other circuits below that we DO care about.
|
||||
* where 2764800 = 24883200 / 9. You need to know this because we rely on the CPU frequency for simulating some
|
||||
* of the other VT100 circuits.
|
||||
*
|
||||
* For reference, here is a list of all the VT100 I/O ports, from /devices/pc8080/machine/vt100/debugger/README.md,
|
||||
* which in turn comes from p. 4-17 of the VT100 Technical Manual (July 1982):
|
||||
*
|
||||
* READ OR WRITE
|
||||
* 00H PUSART data bus
|
||||
* 01H PUSART command port
|
||||
*
|
||||
* WRITE ONLY (Decoded with I/O WR L)
|
||||
* 02H Baud rate generator
|
||||
* 42H Brightness D/A latch
|
||||
* 62H NVR latch
|
||||
* 82H Keyboard UART data input [used to update the Keyboard Status Byte -JP]
|
||||
* A2H Video processor DC012
|
||||
* C2H Video processor DC011
|
||||
* E2H Graphics port
|
||||
*
|
||||
* READ ONLY (Decoded with I/O RD L)
|
||||
* 22H Modem buffer
|
||||
* 42H Flags buffer
|
||||
* 82H Keyboard UART data output
|
||||
*
|
||||
* Most of these are handled by the ChipSet component, since it exists as sort of a "catch-all" component,
|
||||
* but some are more appropriately handled by other components; eg, port 0x82 is handled by the Keyboard component,
|
||||
* so it's defined there instead of here.
|
||||
*/
|
||||
ChipSet.VT100 = {
|
||||
MODEL: 100.0,
|
||||
|
|
@ -202,13 +233,65 @@ ChipSet.VT100 = {
|
|||
STANDBY: 0x7
|
||||
},
|
||||
WORDMASK: 0x3fff // NVR words are 14-bit
|
||||
/*
|
||||
* The Technical Manual, p. 4-18, also notes that "Early VT100s can disable the receiver interrupt by
|
||||
* programming D4 in the NVR latch. However, this is never used by the VT100."
|
||||
*/
|
||||
},
|
||||
/*
|
||||
* DC012 is referred to as a Control Chip.
|
||||
*
|
||||
* As p. 4-67 (117) of the VT100 Technical Manual (July 1982) explains:
|
||||
*
|
||||
* The DCO12 performs three main functions.
|
||||
*
|
||||
* 1. Scan count generation. This involves two counters, a multiplexer to switch between the counters,
|
||||
* double-height logic, scroll and line attribute latches, and various logic controlling switching between
|
||||
* the two counters. This is the biggest part of the chip. It includes all scrolling, double-height logic,
|
||||
* and feeds into the underline and hold request circuits.
|
||||
*
|
||||
* 2. Generation of HOLD REQUEST. This uses information from the scan counters and the scrolling logic to
|
||||
* decide when to generate HOLD REQUEST.
|
||||
*
|
||||
* 3. Video modifications: dot stretching, blanking, addition of attributes to video outputs, and multiple
|
||||
* intensity levels.
|
||||
*
|
||||
* The input decoder accepts a 4-bit command from the microprocessor when VID WR 2 L is asserted. Table 4-6-2
|
||||
* lists the commands.
|
||||
*
|
||||
* D3 D2 D1 D0 Function
|
||||
* -- -- -- -- --------
|
||||
* 0 0 0 0 Load low order scroll latch = 00
|
||||
* 0 0 0 1 Load low order scroll latch = 01
|
||||
* 0 0 1 0 Load low order scroll latch = 10
|
||||
* 0 0 1 1 Load low order scroll latch = 11
|
||||
*
|
||||
* 0 1 0 0 Load high order scroll latch = 00
|
||||
* 0 1 0 1 Load high order scroll latch = 01
|
||||
* 0 1 1 0 Load high order scroll latch = 10
|
||||
* 0 1 1 1 Load high order scroll latch = 11 (not used)
|
||||
*
|
||||
* 1 0 0 0 Toggle blink flip-flop
|
||||
* 1 0 0 1 Clear vertical frequency interrupt
|
||||
*
|
||||
* 1 0 1 0 Set reverse field on
|
||||
* 1 0 1 1 Set reverse field off
|
||||
*
|
||||
* 1 1 0 0 Set basic attribute to underline*
|
||||
* 1 1 0 1 Set basic attribute to reverse video*
|
||||
* 1 1 1 0 Reserved for future specification*
|
||||
* 1 1 1 1 Reserved for future specification*
|
||||
*
|
||||
* *These functions also clear blink flip-flop.
|
||||
*/
|
||||
DC012: { // generates scan counts for the Video Processor
|
||||
PORT: 0xA2, // write-only
|
||||
INIT: 0x00 // for lack of a better guess
|
||||
},
|
||||
/*
|
||||
* As p. 4-55 (105) of the July 1982 Technical Manual explains:
|
||||
* DC011 is referred to as a Timing Chip.
|
||||
*
|
||||
* As p. 4-55 (105) of the VT100 Technical Manual (July 1982) explains:
|
||||
*
|
||||
* The DCO11 is a custom designed bipolar circuit that provides most of the timing signals required by the
|
||||
* video processor. Internal counters divide the output of a 24.0734 MHz oscillator (located elsewhere on the
|
||||
|
|
|
|||
|
|
@ -102,8 +102,7 @@ Keyboard.ASCII = {
|
|||
* keyCodes for most common ASCII keys can simply use the appropriate ASCII code above.
|
||||
*
|
||||
* Most of these represent non-ASCII keys (eg, the LEFT arrow key), yet for some reason, browsers defined
|
||||
* them using ASCII codes (eg, the LEFT arrow key uses the ASCII code for '%' or 37). This conflict is
|
||||
* discussed further in the definition of CLICKCODE below.
|
||||
* them using ASCII codes (eg, the LEFT arrow key uses the ASCII code for '%' or 37).
|
||||
*
|
||||
* @enum {number}
|
||||
*/
|
||||
|
|
@ -286,7 +285,18 @@ Keyboard.VT100 = {
|
|||
LED1: 0x08,
|
||||
LOCKED: 0x10,
|
||||
ONLINE: 0x20,
|
||||
LEDS: 0x3F, // all LEDs
|
||||
START: 0x40, // set to initiate a scan
|
||||
/*
|
||||
* From p. 4-38 of the VT100 Technical Manual (July 1982):
|
||||
*
|
||||
* A bit (CLICK) in the keyboard status word controls the bell.... When a single status word contains
|
||||
* the bell bit, flip-flop E3 toggles and turns on E1, generating a click. If the bell bit is set for
|
||||
* many words in succession, the UART latch holds the data output constant..., allowing the circuit to
|
||||
* produce an 800 hertz tone. Bell is generated by setting the bell bit for 0.25 seconds. Each cycle of
|
||||
* the tone is at a reduced amplitude compared with the single keyclick.... The overall effect of the
|
||||
* tone burst on the ear is that of a beep.
|
||||
*/
|
||||
CLICK: 0x80,
|
||||
INIT: 0x00
|
||||
}
|
||||
|
|
@ -573,7 +583,7 @@ Keyboard.prototype.save = function()
|
|||
case Keyboard.SI1978.MODEL:
|
||||
break;
|
||||
case Keyboard.VT100.MODEL:
|
||||
state.set(0, [this.bLEDs]);
|
||||
state.set(0, [this.bVT100Status]);
|
||||
break;
|
||||
}
|
||||
return state.data();
|
||||
|
|
@ -597,8 +607,8 @@ Keyboard.prototype.restore = function(data)
|
|||
return true;
|
||||
|
||||
case Keyboard.VT100.MODEL:
|
||||
this.bLEDs = a[0];
|
||||
this.updateLEDs();
|
||||
this.bVT100Status = a[0];
|
||||
this.updateLEDs(this.bVT100Status & Keyboard.VT100.STATUS.LEDS);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -621,20 +631,22 @@ Keyboard.prototype.setLED = function(control, f)
|
|||
};
|
||||
|
||||
/**
|
||||
* updateLEDs()
|
||||
* updateLEDs(bLEDs)
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {number} bLEDs
|
||||
*/
|
||||
Keyboard.prototype.updateLEDs = function()
|
||||
Keyboard.prototype.updateLEDs = function(bLEDs)
|
||||
{
|
||||
this.bLEDs = bLEDs;
|
||||
for (var sBinding in this.config.LEDCODES) {
|
||||
var id = "led-" + sBinding;
|
||||
var control = this.bindings[id];
|
||||
if (control) {
|
||||
var bitLED = this.config.LEDCODES[sBinding];
|
||||
var fOn = !!(this.bLEDs & bitLED);
|
||||
var fOn = !!(bLEDs & bitLED);
|
||||
if (bitLED & (bitLED-1)) {
|
||||
fOn = !(this.bLEDs & ~bitLED);
|
||||
fOn = !(bLEDs & ~bitLED);
|
||||
}
|
||||
this.setLED(control, fOn);
|
||||
}
|
||||
|
|
@ -783,8 +795,13 @@ Keyboard.prototype.checkSoftKeysToRelease = function()
|
|||
Keyboard.prototype.outVT100UARTStatus = function(port, b, addrFrom)
|
||||
{
|
||||
this.printMessageIO(port, b, addrFrom, "KBDUART.STATUS", null, true);
|
||||
this.bLEDs = b;
|
||||
this.updateLEDs();
|
||||
this.bVT100Status = b;
|
||||
this.updateLEDs(b & Keyboard.VT100.STATUS.LEDS);
|
||||
/*
|
||||
if (b & Keyboard.VT100.STATUS.START) {
|
||||
console.log("keyboard scan initiated");
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ function Video(parmsVideo, canvas, context, textarea, container)
|
|||
this.cxCellDefault = this.cxCell = parmsVideo['cellWidth'] || 1;
|
||||
this.cyCellDefault = this.cyCell = parmsVideo['cellHeight'] || 1;
|
||||
this.abFontData = null;
|
||||
this.fDotStretcher = false;
|
||||
|
||||
this.nBitsPerPixel = parmsVideo['bufferBits'] || 1;
|
||||
this.iBitFirstPixel = parmsVideo['bufferLeft'] || 0;
|
||||
|
|
@ -495,6 +496,7 @@ Video.prototype.createFonts = function(abFontData)
|
|||
* We retain abFontData in case we have to rebuild the fonts (eg, when we switch from 80 to 132 columns)
|
||||
*/
|
||||
this.abFontData = abFontData;
|
||||
this.fDotStretcher = (this.nFormat == Video.FORMAT.VT100);
|
||||
this.aFonts[Video.VT100.FONT.NORML] = [
|
||||
this.createFontVariation(this.cxCell, this.cyCell),
|
||||
this.createFontVariation(this.cxCell, this.cyCell, this.fUnderline)
|
||||
|
|
@ -561,6 +563,7 @@ Video.prototype.createFontVariation = function(cxCell, cyCell, fUnderline)
|
|||
var offFontData = iChar * nFontBytesPerChar + ((nFontByteOffset + y) & (nFontBytesPerChar - 1));
|
||||
var bits = (fUnderline && y == 8? 0xff : this.abFontData[offFontData]);
|
||||
for (var nRows = 0; nRows < (cyCell / this.cyCell); nRows++) {
|
||||
var bitPrev = 0;
|
||||
for (var x = 0, xDst = x; x < this.cxCell; x++) {
|
||||
/*
|
||||
* While x goes from 0 to cxCell-1, obviously we will run out of bits after x is 7;
|
||||
|
|
@ -568,12 +571,14 @@ Video.prototype.createFontVariation = function(cxCell, cyCell, fUnderline)
|
|||
* (so that line-drawing characters seamlessly connect), we ensure that the effective
|
||||
* shift count remains stuck at 7 once it reaches 7.
|
||||
*/
|
||||
var bit = bits & (0x80 >> (x > 7? 7 : x));
|
||||
var bitReal = bits & (0x80 >> (x > 7? 7 : x));
|
||||
var bit = (this.fDotStretcher && !bitReal && bitPrev)? bitPrev : bitReal;
|
||||
for (var nCols = 0; nCols < (cxCell / this.cxCell); nCols++) {
|
||||
if (fReverse) bit = !bit;
|
||||
this.setPixel(imageChar, xDst, yDst, bit? 1 : 0);
|
||||
xDst++;
|
||||
}
|
||||
bitPrev = bitReal;
|
||||
}
|
||||
yDst++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue