LPC (Line Printer Control) Driver Disassembly

Page Customization

Description:

LPC is a small TSR (Terminate and Stay Resident) utility that installs a keyboard/display driver to handle line printer control characters. The loader at 7000H reserves 42 bytes of low memory, patches the DOS keyboard vector, and relocates the driver code into protected memory.

The driver intercepts character output and tracks control characters (CR, LF, FF). When a carriage return follows another control character, it routes through ROM's CR handler to prevent double line feeds and other printer output issues.

Program Entry: 7000H

Memory Used: 42 bytes (002AH) reserved below high memory

Variables:

AddressBytesPurpose
4026H2DOS high memory pointer (HIMEM)
4411H2DOS keyboard/display driver vector
7036H2Patch location: original vector stored here
7046H2Patch location: original vector stored here
704DH2Patch location: original vector stored here
7057H1Last character storage (pre-relocation address)

Technical Notes

Relocation: The driver code at 702EH-7057H is copied to low memory below the original keyboard vector address. The addresses 7036H, 7046H, 704DH reference locations within the driver that get patched with the original DOS keyboard vector before relocation. After relocation, these become relative offsets within the relocated code.

Vector Chain: The loader stores the original keyboard vector (from 4411H) into the driver at three JP instruction locations. This allows the driver to chain to the original handler for normal character output while intercepting specific control sequences.

Control Character Handling: The driver tracks CR (0DH), LF (0AH), and FF (0CH). When any of these control characters is followed by a CR, the driver routes through ROM address 042AH (the CR handler) instead of normal character output at 03C3H. This prevents double line feeds that can occur when CR+LF sequences are sent to line printers.

Disassembly:

7000H - Loader Entry Point

This routine verifies sufficient memory is available (high memory must be at 03C2H or above), saves the current keyboard vector, reserves 42 bytes of memory, patches the vector addresses into the driver, relocates the driver to protected memory, and updates the DOS keyboard vector to point to the new driver.

7000
LD HL,(4026H) 2A 26 40
Fetch DOS high memory pointer (HIMEM).
7003
LD BC,03C2H 01 C2 03
Load BC with 03C2H (minimum required HIMEM).
7006
XOR A AF
Clear A and CARRY flag for subtraction.
7007
SBC HL,BC ED 42
Subtract minimum from current HIMEM.
7009
If NZ FLAG (insufficient memory), JUMP to DOS READY.
700C
LD HL,(4411H) 2A 11 44
Fetch current DOS keyboard/display vector.
700F
LD (7036H),HL 22 36 70
Patch original vector into driver at offset 7036H.
7012
LD (7046H),HL 22 46 70
Patch original vector into driver at offset 7046H.
7015
LD (704DH),HL 22 4D 70
Patch original vector into driver at offset 704DH.
7018
LD BC,002AH 01 2A 00
Load BC with 002AH (42 bytes = driver size).
701B
OR A B7
Clear CARRY flag for subtraction.
701C
SBC HL,BC ED 42
Subtract driver size from original vector address.
701E
LD (4411H),HL 22 11 44
Store new keyboard vector (will point to relocated driver).
7021
INC HL 23
INCrement to get new HIMEM boundary.
7022
LD (4026H),HL 22 26 40
Update DOS high memory pointer.
7025
LD DE,702EH 11 2E 70
Point DE to driver source code at 702EH.
7028
EX DE,HL EB
Exchange: HL = 702EH (source), DE = destination.
7029
LDIR ED B0
Block copy 42 bytes of driver from 702EH to low memory.
702B
JUMP to DOS READY - installation complete.

702EH - Keyboard/Display Intercept Driver

This driver intercepts character output to handle line printer control sequences. It strips bit 7 from characters, tracks the last character output, and provides special handling when control characters (CR, LF, FF) follow each other. When a CR follows a control character, it routes to ROM's CR handler to prevent printer output issues. This code is relocated to low memory at runtime.

702E
LD A,C 79
Copy character from C to A.
702F
AND 7FH E6 7F
Mask off bit 7 (strip parity/high bit).
7031
LD C,A 4F
Store masked character back in C.
7032
If Z FLAG (null character), JUMP to ROM null handler.
7035
LD A,(7057H) 3A 57 70
Fetch last character from storage. (Patched at runtime)
7038
CP 0CH FE 0C
Compare last character against 0CH (Form Feed).
703A
If Z FLAG (last was FF), JUMP to 704BH for control handling.
703C
CP 0DH FE 0D
Compare last character against 0DH (Carriage Return).
703E
If Z FLAG (last was CR), JUMP to 704BH for control handling.
7040
CP 0AH FE 0A
Compare last character against 0AH (Line Feed).
7042
If Z FLAG (last was LF), JUMP to 704BH for control handling.

Last character was not a control character - normal output path.

7044
LD A,C 79
Copy current character to A.
7045
LD (7057H),A 32 57 70
Store as last character. (Patched at runtime)
7048
JUMP to ROM character output. (Patched to original vector)

Last character was a control character - check if current is CR for special handling.

704B
LD A,C 79
Copy current character to A.
704C
LD (7057H),A 32 57 70
Store as last character. (Patched at runtime)
704F
CP 0DH FE 0D
Compare current character against 0DH (Carriage Return).
7051
If Z FLAG (CR after control), JUMP to ROM CR handler. (Patched)
7054
JUMP to ROM character output. (Patched to original vector)

7057H - Last Character Storage

Single byte storage for tracking the last character output. Initialized to 0DH (CR).

7057
DEFB 0DH 0D
Last character storage (initialized to CR).