;ASCII2, a tsr ASCII table, written by Doug Cox, May, 1988
;& assembled with A86

CODE SEGMENT
  JMP INSTALL
ALTA DW 01E00		;ALT-A to call ASCII table
  DB 'ASCII2(c)1988'
BUSY DB 0
MODE DB ?
OLDSCR DB 1452 DUP (?)
OLDCUR DW ?
TOPLEFT DW 16
TOPLINE DB ' ASCII:   h      (use ARROW KEYS to move cursor   ESC to exit) '
BLANK DB 0
ASCIINUM DB 0
ROW DB 0
COL DB 0
TEN DB 10
HUNDRED DB 100

INT9:
FLGCALL DW 09A9C        ;pushf & call far
INT9OFF DW ?
INT9SEG DW ?
  PUSH DS,BX
  MOV BX,040
  MOV DS,BX
  MOV BX,[01CH]         ;kbd buffer tail
  CMP BX,[01AH]         ;kbd buffer head
  JZ GETOUT             ;if no kbd buffer input
  DEC BX,2              ;back to last char entered
  CMP BX,01EH           ;beginning of kbd buffer
  IF C MOV BX,03CH      ;end of kbd buffer
  MOV BX,[BX]
  PUSH CS
  POP DS
  CMP BX,ALTA
  JNZ GETOUT		;if Alt-A not pressed
  CMP BUSY,0
  JZ CONTINUE		;if ASCII table not running
GETOUT:
  POP BX,DS
  IRET

CONTINUE:
  PUSH AX,CX,DX,DI,SI,BP,ES
  MOV BUSY,1            ;flag
  PUSH BX
  MOV AH,0F		;function to check screen mode
  INT 010
  POP BX
  MOV MODE,AL
  MOV DX,0B800
  CMP AL,7		;indicates monocrome mode
  IF Z MOV DX,0B000
  MOV ES,DX

  MOV BLANK,0
  MOV ASCIINUM,0
  MOV ROW,0
  MOV COL,0
  MOV AH,3		;function to get cursor position
  MOV BH,0
  INT 010
  MOV OLDCUR,DX
  MOV AH,2		;function to move cursor
  MOV DX,01900		;row 25 (off screen)
  INT 010

;save old screen
  MOV SI,TOPLEFT
  SUB SI,2
  MOV DI,OFFSET OLDSCR
  MOV AX,0B800		;screen segment addr
  CMP MODE,7
  IF Z MOV AX,0B000
  MOV DS,AX
  MOV AX,CS
  MOV ES,AX
  MOV BX,11
SAVELP:
  MOV CX,66
  REP MOVSW
  ADD SI,28
  DEC BX
  JNZ SAVELP
  MOV AX,DS
  MOV ES,AX
  MOV AX,CS
  MOV DS,AX

;put top line on screen
  MOV SI,OFFSET TOPLINE
  MOV DI,TOPLEFT
  ADD DI,160
  MOV AL,6              ;attribute
  CMP MODE,7
  IF Z MOV AL,7
  MOV CX,63
TOPLIN:
  MOVSB
  STOSB
  LOOP TOPLIN

;put ASCII chars on screen
  MOV AX,0300		;attribute & first ASCII char number
  CMP MODE,7
  IF Z MOV AH,7
  MOV DX,0720		;attribute & space char
  MOV DI,TOPLEFT
  ADD DI,320
  MOV BX,8		;line count
LOOPO:
  MOV CX,32		;chars/line
LOOPI:
  STOSW
  XCHG DX,AX
  STOSW 		;fill spaces between chars
  XCHG DX,AX
  INC AL
  LOOP LOOPI
  ADD DI,32
  DEC BX
  JNZ LOOPO

;put border on screen
  MOV AX,03C4		; & attribute
  CMP MODE,7
  IF Z MOV AH,7
  MOV DI,TOPLEFT
  MOV CX,63
  REP STOSW
  MOV DI,TOPLEFT
  ADD DI,1600
  MOV CX,63
  REP STOSW
  MOV AX,03B3		; & attribute
  CMP MODE,7
  IF Z MOV AH,7
  MOV DI,TOPLEFT
  ADD DI,158
  MOV CX,9		;rows
SIDELP:
  MOV ES:[DI],AX
  ADD DI,160
  LOOP SIDELP
  MOV DI,TOPLEFT
  ADD DI,286
  MOV CX,9
SIDELP2:
  MOV ES:[DI],AX
  ADD DI,160
  LOOP SIDELP2
  MOV DI,TOPLEFT
  SUB DI,2
  MOV W ES:[DI],03DA	;
  ADD DI,128
  MOV W ES:[DI],03BF	;
  ADD DI,1600
  MOV W ES:[DI],03D9	;
  SUB DI,128
  MOV W ES:[DI],03C0	;

  MOV BH,0F		;highlight attribute
  CMP MODE,7
  IF Z MOV BH,08F	;blinking intense
  MOV DI,TOPLEFT
  ADD DI,321		;to first ASCII char attribute

BIGLOOP:
;display ASCII char number in hex
  MOV AH,ASCIINUM
  MOV SI,TOPLEFT
  ADD SI,176
  MOV CH,2
HEXLP:
  MOV CL,4
  ROL AX,CL
  AND AL,0F
  ADD AL,030
  CMP AL,03A
  IF NC ADD AL,7
  MOV ES:[SI],AL
  INC SI,2
  DEC CH
  JNZ HEXLP

;display ASCII in decimal
  ADD SI,4
  MOV AL,ASCIINUM
  MOV AH,0
  DIV HUNDRED
  ADD AL,030
  CMP AL,'0'
  IF Z MOV AL,' '
  MOV ES:[SI],AL
  INC SI,2
  MOV AL,AH
  MOV AH,0
  DIV TEN
  ADD AL,030
  CMP AL,'0'
  JNZ NOTZ
  CMP B ES:[SI-2],' '
  IF Z MOV AL,' '
NOTZ:
  MOV ES:[SI],AL
  INC SI,2
  MOV AL,AH
  ADD AL,030
  MOV ES:[SI],AL

  CMP ASCIINUM,0
  JZ SPECIAL
  CMP ASCIINUM,32
  JZ SPECIAL
  CMP ASCIINUM,255
  JZ SPECIAL
DOATTRIB:
  MOV BL,ES:[DI]
  MOV ES:[DI],BH	;highlight attribute
READKBD:
  MOV AH,0		;function to read keyboard
  INT 016
  CMP AH,04D
  JZ RIGHT
  CMP AH,04B
  JZ LEFT
  CMP AH,048
  JZ UP
  CMP AH,050
  JZ DOWN
  CMP AL,01B		;ESC
  IF Z JMP EXIT
  JMP SHORT READKBD

SPECIAL:
  MOV B ES:[DI-1],0B2	;
  MOV BLANK,1
  JMP SHORT DOATTRIB

RIGHT:
  CMP COL,31
  JZ READKBD
  CMP BLANK,0
  IF NZ CALL ITSBLANK
  INC COL
  INC ASCIINUM
  MOV ES:[DI],BL
  ADD DI,4
  JMP SHORT BIGLOOP
LEFT:
  CMP COL,0
  JZ READKBD
  CMP BLANK,0
  IF NZ CALL ITSBLANK
  DEC COL
  DEC ASCIINUM
  MOV ES:[DI],BL
  SUB DI,4
  JMP SHORT BIGLOOP
UP:
  CMP ROW,0
  JZ READKBD
  CMP BLANK,0
  IF NZ CALL ITSBLANK
  DEC ROW
  SUB ASCIINUM,32
  MOV ES:[DI],BL
  SUB DI,160
  JMP SHORT BIGLOOP
DOWN:
  CMP ROW,7
  IF Z JMP READKBD
  CMP BLANK,0
  IF NZ CALL ITSBLANK
  INC ROW
  ADD ASCIINUM,32
  MOV ES:[DI],BL
  ADD DI,160
  JMP BIGLOOP

EXIT:
  MOV SI,OFFSET OLDSCR
  MOV DI,TOPLEFT
  SUB DI,2
  MOV BX,11
GETSCRNLP:
  MOV CX,66
  REP MOVSW
  ADD DI,28
  DEC BX
  JNZ GETSCRNLP
  MOV AH,2		;function to move cursor
  MOV BH,0
  MOV DX,OLDCUR
  INT 010
  MOV BUSY,0
  POP ES,BP,SI,DI,DX,CX,AX,BX,DS
  IRET

;****SUBROUTINE****
ITSBLANK:
  MOV B ES:[DI-1],0
  MOV BLANK,0
  RET
;*******************

INSTALL:
  MOV AX,03509
  INT 021
  MOV INT9OFF,BX
  MOV INT9SEG,ES
  MOV AX,02509
  MOV DX,OFFSET INT9
  INT 021
  LEA DX,MSG
  MOV AH,9
  INT 021
  MOV DX,OFFSET INSTALL
  INT 027

MSG DB "...is installed, press Alt-A to enter",0dh,0ah,'$'

