DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦14558304b⟧ TextFile

    Length: 45847 (0xb317)
    Types: TextFile
    Names: »msyp98.asm«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦71044c191⟧ »EurOpenD3/misc/kermit.ms-2.32.tar.Z« 
        └─⟦31f2d420d⟧ 
            └─⟦this⟧ »msyp98.asm« 

TextFile

;+ This is MSYPC98.ASM   VT100 emulation for NEC-PC9801          by.H.Fujii
;
; ESC sequence
; - General rule -
;   1) 2-byte sequence
;      a) ESC Fs terminated by 6/0 - 7/14
;      b) ESC Fp terminated by 3/0 - 3/15
;      c) ESC Fe terminated by 4/0 - 5/15
;   2) multibyte sequnce
;      a) ESC I...I Fp terminated by 3/0 - 3/15 (private sequence)
;      b) ESC I...I Ft terminated by 4/0 - 7/14 (standard sequence)
;      where I is 2/0 - 2/15
;   3) control sequnce
;      a) CSI P...P I...I Ft terminated by 4/0 - 6/15 (standard sequence)
;      b) CSI P...P I...I Fp terminated by 7/0 - 7/14 (private sequence)
;      where CSI is 9/11 or ESC 5/11 (one of ESC Fe sequnce)
;            P is 3/0 - 3/15,
;                 3/11 is separator
;                 3/15 is private parameter introducer
;            I is 2/0 - 2/15
;
; CRT display character
;
;   Character plane
;              F E D C B A 9 8   7 6 5 4 3 2 1 0
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;             |      0        | |    ANK code   |         ANK
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;             |0|   JIS 2nd   | |JIS 1st - '20'X|     Kanji Left half
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;             |1|   JIS 2nd   | |JIS 1st - '20'X|     Kanji Right half
;             +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
;
;
;   Attribute plane
;                                7 6 5 4 3 2 1 0
;                               +-+-+-+-+-+-+-+-+
;                               |G|R|B| | | | | |
;                               +-+-+-+-+-+-+-+-+
;                                ^ ^ ^ ^ ^ ^ ^ ^
;                                | | | | | | | |
;                                | | | | | | | secret (0)
;                                | | | | | | blink (1)
;                                | | | | | reverse (1)
;                                | | | | underline (1)
;                                | | | vertical line/graph pattern
;                                color
;
DOS             equ     021h            ; MS-DOS function
WRITE2          equ     40h             ; MS-DOS WRITE function (version2)

ESCAPE          equ     1Bh

BIOS            equ     018h            ; CRT BIOS
CHR_REV         equ     04h
CRT_TXT_SEG     equ     0A000h

PRIVP_FLG       equ     08000h

AUTOWRAP_BIT    equ     001h

        public  vt100,vt100_ini,vt100_save,vt100_restore
        public  vt100_modlin, vt100_dump, vt100_color

datas   segment public 'datas'

        extrn   curkey_mode:byte, keypad_mode:byte
        extrn   vt100_flags:byte
        extrn   kanji_rmode:byte

vt_init         db      0
vt_graph        db      0
vt_chrset       db      0
vt_chratr       db      0               ; current character attributes
vt_blkatr       db      0               ; blank area attributes

vt_kanji_code   db      2
vt_knjmode      db      0               ; Kanji mode if 1
vt_kanji1       db      0               ; Kanji 1st byte
vt_kanji2       db      0

vt_nrmatr       db      0E1h            ; normal character attributes
vt_hglatr       db      0A0h            ; highlight character attribute
vt_blnatr       db      002h            ; blink character attribute
vt_modatr       db      0C5h            ; mode line character attributes

esc_prv         db      0
esc_seq         db      0
esc_len         dw      0
esc_buf         db      128 dup (?)
esc_P_pnt       dw      0
esc_P_buf       dw      64 dup (?)

priv_param      dw      0

char_GL         dw      ?
char_GR         dw      ?

char_G0         db      0
char_G1         db      1
char_G2         db      0
char_G3         db      1

sng_char        db      1,0

vt_gset         db      0EAh,087h,009h,00Ch,00Dh,00Ah,0DFh,08Fh
                db      015h,00Bh,09Bh,099h,098h,09Ah,08Fh,094h
                db      094h,095h,081h,080h,093h,092h,090h,091h
                db      096h,01Dh,01Ch,01Eh,01Fh,0F1h,0A5h,020h

vram_line       label   word
                dw      0000h           ; 0-line
                dw      00a0h           ; 1
                dw      0140h           ; 2
                dw      01e0h           ; 3
                dw      0280h           ; 4
                dw      0320h           ; 5
                dw      03c0h           ; 6
                dw      0460h           ; 7
                dw      0500h           ; 8
                dw      05a0h           ; 9
                dw      0640h           ;10
                dw      06e0h           ;11
                dw      0780h           ;12
                dw      0820h           ;13
                dw      08c0h           ;14
                dw      0960h           ;15
                dw      0a00h           ;16
                dw      0aa0h           ;17
                dw      0b40h           ;18
                dw      0be0h           ;19
                dw      0c80h           ;20
                dw      0d20h           ;21
                dw      0dc0h           ;22
                dw      0e60h           ;23
vram_last_line  dw      0f00h           ;24
;
I_am_vt100      db      5
                db      ESCAPE,"[?6c"
I_am_vt220      db      16
                db      ESCAPE,"[?62;1;2;6;7;8c"

cur_col         db      0
cur_row         db      0
cur_save_col    db      0
cur_save_row    db      0

;
vt_top          db      0
vt_bottom       db      23

dump_pntr       dw      ?
dump_buffer     db      256     dup (?)

datas   ends

code    segment public  'code'
        assume  cs:code,ds:datas

        extrn   s2jis:near, jis2s:near
;
; VT100 terminal emulator
;

VT100_INI       PROC    NEAR
        cmp     vt_init,0
        je      vt100_ini_1
        jmp     vt100_ini_ex
vt100_ini_1:
        mov     vt_init,1
        mov     vt_graph,0
        mov     cur_col,0
        mov     cur_row,0
        mov     cur_save_col,0
        mov     cur_save_row,0
        mov     al,vt_nrmatr
        mov     vt_chratr,al
        mov     vt_blkatr,al
        mov     vt_top,0
        mov     vt_bottom,23
        mov     priv_param,0
;
        mov     char_G0,0
        mov     char_G1,1
        mov     char_G2,0
        mov     char_G3,1
;
        mov     char_GL,offset char_G0
        mov     char_GR,offset char_G1
;
; Erase entire screen
;
        push    es
        push    di
        mov     ax,CRT_TXT_SEG
        mov     es,ax
        mov     di,1000h                ; page 2
        mov     cx,0800h
        cld
        mov     ax,0020h
        rep     stosw
        mov     di,1000h
        add     di,02000h               ; text attributes
        mov     al,vt_blkatr
        xor     ah,ah
        mov     cx,0800h
        rep     stosw
;
        pop     di
        pop     es
;
vt100_ini_ex:
        ret
VT100_INI       ENDP

VT100_XCHG      PROC    NEAR
;
;       exchange page 1 and 2
;
        push    ax
        push    bx
        push    cx
        push    si
        push    di
        push    es
;
        mov     ax,CRT_TXT_SEG
        mov     es,ax
        mov     cx,800h
        mov     si,0
        mov     di,si
        add     di,1000h
;
vt100_xchg1:
        mov     ax,es:[si]
        mov     bx,es:[di]
        mov     es:[si],bx
        mov     es:[di],ax
        add     si,2
        add     di,2
        loop    vt100_xchg1
;
        mov     cx,800h
        mov     si,2000h
        mov     di,si
        add     si,1000h
;
vt100_xchg2:
        mov     ax,es:[si]
        mov     bx,es:[di]
        mov     es:[si],bx
        mov     es:[di],ax
        add     si,2
        add     di,2
        loop    vt100_xchg2

        pop     es
        pop     di
        pop     si
        pop     cx
        pop     bx
        pop     ax
        ret
VT100_XCHG      ENDP

;
; save VT100 screen (return to page 1)
;
VT100_SAVE      PROC    NEAR
        push    ax
        push    dx
;
        mov     ah,0Dh                  ; stop display
        int     BIOS
;
        call    vt100_xchg
;
;@@     mov     ah,0Eh
;@@     xor     dx,dx
;@@     int     BIOS

        mov     ah,0Ch                  ; start dispay
        int     BIOS
;
        pop     dx
        pop     ax
        ret
VT100_SAVE      ENDP

;
; restore VT100 screen (return to page 2)
;
VT100_RESTORE   PROC    NEAR
        push    ax
        push    dx
;
        mov     ah,0Dh                  ; stop display
        int     BIOS
;
        call    vt100_xchg
;
;@@     mov     ah,0Eh
;@@     mov     dx,vram_line
;@@     int     BIOS

        mov     ah,0Ch                  ; start display
        int     BIOS
        call    locate_cur
;
        pop     dx
        pop     ax
        ret
VT100_RESTORE   ENDP

VT100_MODLIN    PROC    NEAR
;
; Mode line display control
;
; Inputs:
;       dx      offset address of the mode line buffer;
;               The 1st byte of the mode line buffer must contain the
;               the number of characters in the buffer. If it is zero,
;               the mode line is cleared.
;
        push    es
        push    di
        push    si
;
        push    dx
        cld
        pop     si
        xor     ch,ch
        mov     cl,[si]
        inc     si
        dec     cx
;
        mov     ax,CRT_TXT_SEG
        mov     es,ax
        mov     di,vram_last_line
        mov     bx,cx
        mov     cx,80
        xor     ah,ah
        mov     al,' '
        rep     stosw
        mov     di,vram_last_line
        add     di,02000h
        mov     al,vt_modatr
        cmp     bx,0
        jg      vt100_modlin_01
        mov     al,vt_blkatr
vt100_modlin_01:
        mov     cx,80
        rep     stosw
;
        cmp     bx,0
        jle     vt100_modlin_ex
;
        xor     ax,ax
        mov     cx,bx
        mov     di,vram_last_line
vt100_modlin_1:
        movsb
        stosb
        loop    vt100_modlin_1
;
vt100_modlin_ex:
        call    locate_cur
;
        pop     si
        pop     di
        pop     es
        ret
VT100_MODLIN    ENDP

VT100_COLOR     PROC    NEAR
;
; Change color to the value specified in AX.
;       al      color index for normal character
;       ah      color index for highlighted character
;
        push    ax
        push    bx
        push    cx

        cmp     al,-1
        je      vt100_color1
        mov     bl,vt_nrmatr
        mov     bh,vt_chratr
        and     bl,1Fh                  ; mask other bit
        and     bh,1Fh
        mov     cl,5
        shl     al,cl
        or      bl,al
        or      bh,al
        mov     vt_nrmatr,bl
        mov     vt_chratr,bh
        mov     vt_blkatr,bh
vt100_color1:
        cmp     ah,-1
        je      vt100_color2
        mov     bl,vt_hglatr
        and     bl,1Fh
        mov     cl,5
        shl     ah,cl
        or      bl,ah
        mov     vt_hglatr,bl
vt100_color2:
        pop     cx
        pop     bx
        pop     ax
        ret
VT100_COLOR     ENDP

scrn_mode       proc    near
;
; set screen mode to normal(AL=0)/reverse(AL=1)
; [NOTE]
;       registers AX and BX are broken when return
;
        push    cx
        push    di
        push    es
;
        mov     bx,ax
        mov     ax,CRT_TXT_SEG
        mov     es,ax
        mov     di,vram_line
        add     di,2000h
        mov     cx,1920                 ; 1920 = 80 x 24
        cmp     bl,0
        je      scrn_mode2
scrn_mode1:
        or      BYTE PTR es:[di],CHR_REV
        add     di,2
        loop    scrn_mode1
        or      vt_nrmatr,CHR_REV
        or      vt_chratr,CHR_REV
        or      vt_blkatr,CHR_REV
        jmp     scrn_mode3
scrn_mode2:
        and     BYTE PTR es:[di],NOT CHR_REV
        add     di,2
        loop    scrn_mode2
        and     vt_nrmatr,NOT CHR_REV
        and     vt_chratr,NOT CHR_REV
        and     vt_blkatr,NOT CHR_REV
scrn_mode3:
        pop     es
        pop     di
        pop     cx
        ret
scrn_mode       endp


locate_cur      proc    near
;
; locate cursor at (cur_row,cur_col)
;
; [NOTE]
;       Registers ax, bx and dx are to be broken when return.
;

        mov     dh,cur_row
        mov     dl,cur_col
        call    vram_ofs
        shr     bx,1
        cli
locate_cur1:
        in      al,60h
        test    al,04h                  ; test GDC state
        jz      locate_cur1             ; z = not ready
        mov     al,49h
        out     62h,al
        mov     al,bl
        out     60h,al
        mov     al,bh
        out     60h,al
        sti

        ret
locate_cur      endp
;

disp_char       proc    near
;
; Display character in AX on the screen.
; Cursor moves to the next character position.
;
        mov     dh,cur_row
        mov     dl,cur_col
        call    vram_ofs
        mov     di,bx
        mov     dx,CRT_TXT_SEG
        push    es
        mov     es,dx
        mov     es:[di],ax
        xor     ah,ah
        mov     al,vt_chratr
        add     di,02000h
        stosw
        pop     es
        inc     cur_col
        mov     al,cur_col
        cmp     al,80
        jb      disp_char_loc
        test    vt100_flags,AUTOWRAP_BIT
        jnz     disp_char_wrap                  ; nz = AutoWrap
        mov     cur_col,79                      ; stay at right margin
        jmp     disp_char_ex
disp_char_wrap:
        mov     cur_col,0
        mov     bl,cur_row
        cmp     bl,vt_bottom
        jl      disp_char_wrap1
        je      disp_char_wrap2
        inc     cur_row
        cmp     cur_row,23
        jle     disp_char_loc
        mov     cur_row,23
        jmp     disp_char_loc
disp_char_wrap1:
        inc     cur_row
        jmp     disp_char_loc
disp_char_wrap2:
        mov     al,vt_top
        mov     ah,vt_bottom
        mov     cx,1
        call    scroll_up
disp_char_loc:
        call    locate_cur
disp_char_ex:
        ret
disp_char       endp

;---------------------------
VT100_DUMP      PROC    NEAR
;---------------------------
; Dump screen. This procedure dump the VT100 screen on the disk using
; MS-DOS function 40H (int 21H).
;
; Inputs
;   BX  file handle
;
; Outputs
;   None
;
        push    cx
        push    dx
        push    es
        push    si
        push    di

        mov     ax,CRT_TXT_SEG
        mov     es,ax
        mov     si,vram_line
        mov     cx,24
vt100_dump0:
        push    cx
        mov     di,offset dump_buffer
        mov     dump_pntr,di
        mov     cx,80
;
vt100_dump1:
        mov     ax,es:[si]
        cmp     ah,0                    ; Kanji ?
        je      vt100_dump3             ; e = no.
        add     ax,20h                  ; convert to jis
        and     ax,7F7Fh                ; mask 8th bit
        call    jis2s                   ; convert to shift jis
        mov     [di],al
        mov     [di+1],ah
        add     di,2
        add     si,4
        dec     cx
        mov     dump_pntr,di
        jmp     vt100_dump2
vt100_dump3:
        mov     [di],al                 ; remove Kanji flag etc in ah.
        inc     di
        add     si,2
        cmp     al,' '                  ; Is it blank ?
        je      vt100_dump2             ; e = yes.
        mov     dump_pntr,di
vt100_dump2:
        loop    vt100_dump1
;
        mov     di,dump_pntr
        mov     ax,0A0Dh                ; add CR/LF
        mov     [di],ax
        add     dump_pntr,2
        mov     cx,dump_pntr
        sub     cx,offset dump_buffer
        mov     dx,offset dump_buffer
        mov     ah,WRITE2               ; write function
        int     DOS
;
        pop     cx
        loop    vt100_dump0
;
        pop     di
        pop     si
        pop     es
        pop     dx
        pop     cx
        ret
VT100_DUMP      ENDP

;---------------------------
VT100           PROC    NEAR
;---------------------------
;
; Character display routine in VT-100 mode
;
vt_disp:
        cmp     al,20h
        jb      vt_disp_C0              ; C0 control characters
        jmp     vt_disp_D0
vt_disp_ex:
        mov     cx,0
        ret

; C0 control characters

vt_disp_C0:
        cmp     al,10h
        jl      vt_disp_C00
        jmp     vt_disp_C01
vt_disp_C00:
        jne     vt_disp_n00
        jmp     vt_disp_ex
vt_disp_n00:
vt_disp_n06:
        cmp     al,07h                  ; Bell ?
        jne     vt_disp_n07
        mov     al,06h
        out     37h,al
        mov     cx,0D000h
bell_loop:
        loop    bell_loop
        mov     al,07h
        out     37h,al
        jmp     vt_disp_ex
vt_disp_n07:
        cmp     al,08h                  ; BS ?
        jne     vt_disp_n08
        cmp     cur_col,0
        jle     vt_disp_ex
        dec     cur_col
        call    locate_cur
        jmp     vt_disp_ex
vt_disp_n08:
        cmp     al,09h                  ; HT ?
        jne     vt_disp_n09
        jmp     disp_TAB
vt_disp_n09:
        cmp     al,0Ah                  ; LF ?
        jne     vt_disp_n0A
        jmp     disp_LF
vt_disp_n0A:
        cmp     al,0Bh                  ; VT ?
        jne     vt_disp_n0B
        jmp     disp_LF
vt_disp_n0B:
        cmp     al,0Ch                  ; FF ?
        jne     vt_disp_n0C
        jmp     disp_LF
vt_disp_n0C:
        cmp     al,0Dh                  ; CR ?
        jne     vt_disp_n0D
        mov     cur_col,0
        call    locate_cur
        jmp     vt_disp_ex
vt_disp_n0D:
        cmp     al,0Eh
        jne     vt_disp_n0E             ; SO ?
        mov     char_GL,offset char_G1
        jmp     vt_disp_ex
vt_disp_n0E:
        cmp     al,0Fh                  ; SI ?
        jne     vt_disp_n0F
        mov     char_GL,offset char_G0
        jmp     vt_disp_ex
vt_disp_n0F:
        jmp     vt_disp_ex

vt_disp_C01:
        cmp     al,18h                  ; CAN ?
        jne     vt_disp_n18
        mov     esc_seq,0
        jmp     vt_disp_ex
vt_disp_n18:
        cmp     al,1Ah                  ; SUB ?
        jne     vt_disp_n1a
        mov     esc_seq,0
        jmp     vt_disp_ex
vt_disp_n1A:
        cmp     al,1Bh                  ; ESC ?
        jne     vt_disp_n1B
        jmp     vt_esc_0
vt_disp_n1B:
        jmp     vt_disp_ex
;
disp_lf:
        mov     bl,vt_bottom    ; get bottom margin
        cmp     cur_row,bl
        jl      disp_lf2        ; above boundary
        je      disp_lf1        ; on the boundary
        inc     cur_row
        cmp     cur_row,23      ; screen boundary
        jle     disp_lf3
        mov     cur_row,23
        jmp     disp_lf3
disp_lf1:
        mov     cur_row,bl
        mov     al,vt_top
        mov     ah,vt_bottom
        mov     cx,1
        call    scroll_up
        jmp     disp_lf3
disp_lf2:
        inc     cur_row
disp_lf3:
        call    locate_cur
        jmp     vt_disp_ex

disp_tab:
        mov     al,cur_col
        mov     cl,3
        shr     al,cl
        inc     al
        shl     al,cl
        cmp     al,79
        jle     disp_tab1
        mov     al,79
disp_tab1:
        mov     cur_col,al
        call    locate_cur
        jmp     vt_disp_ex

; non C0 characters

vt_disp_D0:
        cmp     al,7Fh                  ; DEL ?
        jne     vt_disp_n7f
        jmp     vt_disp_ex
vt_disp_n7f:
        cmp     esc_seq,0               ; In ESC sequence ?
        je      vt_disp_x               ; e = no, jump to normal sequence
        cmp     esc_seq,1               ; 1st character in ESC seq.?
        jne     vt_disp_1               ; ne = no, check the sequnce type
        jmp     vt_esc_1
vt_disp_1:
        cmp     esc_seq,2
        jne     vt_disp_2
        jmp     vt_esc_2
vt_disp_2:
        cmp     esc_seq,3
        jne     vt_disp_3
        jmp     vt_esc_3
vt_disp_3:
        cmp     esc_seq,4
        jne     vt_disp_x
        jmp     vt_esc_4
vt_disp_x:
        cmp     vt_knjmode,0
        je      try_KNJ0
        jmp     try_KNJ1
try_KNJ0:
        cmp     vt_kanji_code,0
        jne     try_KNJ1
        jmp     disp_out
try_KNJ1:
        test    vt_kanji_code,1         ; JIS Kanji code?
        jz      try_KNJ2
        jmp     KNJ_JIS
try_KNJ2:
        cmp     kanji_rmode,0           ; Kanji code?
        je      try_KNJ3
        jmp     KNJ_DEC
try_KNJ3:
        jmp     disp_out
;
KNJ_JIS:
        cmp     vt_knjmode,0
        je      KNJ_JIS1
        jmp     KNJ_DEC3
KNJ_JIS1:
        and     al,07Fh
        mov     vt_kanji1,al
        mov     vt_knjmode,1
        jmp     vt_disp_ex
;
KNJ_DEC:
        cmp     vt_knjmode,0
        jne     KNJ_DEC3
        and     al,07Fh
        mov     vt_kanji1,al
        mov     vt_knjmode,1
        jmp     vt_disp_ex
KNJ_DEC3:
        and     al,07Fh
        mov     ah,al
        mov     al,vt_kanji1
        sub     ax,020h
        push    ax
        call    disp_char
        pop     ax
        or      ax,8000h
        call    disp_char
        mov     vt_knjmode,0
        jmp     vt_disp_ex
;
disp_out:
        mov     bx,char_GL
        cmp     al,80h
        jb      disp_out0
        mov     bx,char_GR
disp_out0:
        mov     ah,[bx]
        mov     vt_graph,ah
        xor     ah,ah
        cmp     vt_graph,0
        je      disp_out1
        cmp     ax,060h
        jl      disp_out1
        cmp     ax,07Fh
        jg      disp_out1
        sub     ax,060h
        mov     bx,offset vt_gset
        add     bx,ax
        mov     al,[bx]
disp_out1:
        call    disp_char
        jmp     vt_disp_ex
;
; ESC sequence analysis
;
vt_esc_0:
        mov     esc_seq,1
        mov     esc_len,0
        mov     esc_P_pnt,0
        mov     bx,offset esc_P_buf
        mov     word ptr [bx],0
        jmp     vt_disp_ex
vt_esc_1:
        and     al,07Fh
        cmp     al,05Fh
        ja      vt_esc_do               ; char is in 6/0 - 7/15, i.e., single
        cmp     al,03Fh
        jbe     vt_esc_2
        jmp     vt_esc_c1               ; char is in 4/0 - 5/15, i.e, C1
vt_esc_2:
        cmp     al,02Fh
        ja      vt_esc_do
        cmp     al,01Fh
        jbe     vt_esc_done
        jmp     vt_esc_I                ; char is in 2/0 - 2/15, i.e., I
vt_esc_done:
        mov     esc_seq,0
        jmp     vt_disp_ex
vt_esc_do:
        cmp     al,'='
        jne     vt_esc_do10
        mov     keypad_mode,1
        jmp     vt_esc_done
vt_esc_do10:
        cmp     al,'>'
        jne     vt_esc_do20
        mov     keypad_mode,0
        jmp     vt_esc_done
vt_esc_do20:
        cmp     al,'<'                  ; VT52 -> ANSI mode ?
        jne     vt_esc_do30
        jmp     vt_esc_done
vt_esc_do30:
        cmp     al,'B'
        je      vt_esc_do32
        cmp     al,'A'                  ; use U.S for U.K
        jne     vt_esc_do40
        jmp     vt_esc_do34
vt_esc_do32:
        mov     bx,offset esc_P_buf
        mov     ah,[bx]
        cmp     ah,24h
        jne     vt_esc_do36
        or      vt_kanji_code,1
        jmp     vt_esc_done
vt_esc_do34:
        mov     bx,offset esc_P_buf
        mov     ah,[bx]
vt_esc_do36:
        sub     ah,28h
        and     ah,3
        mov     bx,offset char_G0
        add     bl,ah
        mov     byte ptr [bx],0
        jmp     vt_esc_done
vt_esc_do40:
        cmp     al,'H'
        je      vt_esc_do42
        cmp     al,'J'
        jne     vt_esc_do50
vt_esc_do42:
        mov     bx,offset esc_P_buf
        mov     ah,[bx]
        cmp     ah,28h
        jne     vt_esc_do44
        and     vt_kanji_code,0FEh
vt_esc_do44:
        jmp     vt_esc_done
vt_esc_do50:
        cmp     al,'0'
        jne     vt_esc_do60
        mov     bx,offset esc_P_buf
        mov     ah,[bx]
        sub     ah,28h
        and     ah,3
        mov     bx,offset char_G0
        add     bl,ah
        mov     byte ptr [bx],1
        jmp     vt_esc_done
vt_esc_do60:
vt_esc_do70:
        cmp     al,'7'
        jne     vt_esc_do80
        mov     al,cur_row
        mov     cur_save_row,al
        mov     al,cur_col
        mov     cur_save_col,al
        jmp     vt_esc_done
vt_esc_do80:
        cmp     al,'8'
        jne     vt_esc_doXX
        mov     al,cur_save_row
        mov     cur_row,al
        mov     al,cur_save_col
        mov     cur_col,al
        call    locate_cur
        jmp     vt_esc_done
vt_esc_doXX:
        jmp     vt_esc_done
vt_esc_I:
        mov     esc_seq,2
        xor     ah,ah
        mov     bx,offset esc_P_buf
        add     bx,esc_P_pnt
        mov     word ptr [bx],ax
        add     esc_P_pnt,2
        jmp     vt_disp_ex
;
vt_esc_c1:
        cmp     al,'['
        jne     vt_c1_try_IND
        jmp     vt_c1_CSI
vt_c1_try_IND:
        cmp     al,'D'
        jne     vt_c1_try_RI
        jmp     vt_c1_IND
vt_c1_try_RI:
        cmp     al,'M'
        jne     vt_c1_try_NEL
        jmp     vt_c1_RI
vt_c1_try_NEL:
        cmp     al,'E'
        jne     vt_c1_xxx
        jmp     vt_c1_NEL
vt_c1_xxx:
        jmp     vt_esc_done
vt_c1_CSI:
        mov     esc_seq,3
        mov     esc_len,0
        mov     esc_P_pnt,0
        mov     bx,offset esc_P_buf
        mov     word ptr [bx],0
        mov     priv_param,0
        jmp     vt_disp_ex
vt_esc_3:
        cmp     al,030h                 ; Parameter (3/0-3/15) ?
        jb      vt_esc_4
        cmp     al,03Fh
        jbe     vt_esc_P
vt_esc_4:
        cmp     al,020h                 ; Intermediate (2/0-2/15) ?
        jb      vt_esc_5
        cmp     al,02Fh
        jbe     vt_esc_CI
        cmp     al,040h                 ; Terminator (4/0-7/14) ?
        jb      vt_esc_5
        jmp     vt_esc_C1do
vt_esc_5:
        jmp     vt_esc_done
;
vt_esc_P:
        cmp     al,03ah
        jae     vt_esc_P1
        mov     bx,offset esc_P_buf
        add     bx,esc_P_pnt
        mov     cx,[bx]                 ; cx is previous value
        and     cx,7FFFh                ; mask private parameter flag
        mov     dx,cx
        shl     dx,1
        shl     dx,1
        add     dx,cx
        shl     dx,1                    ; dx is (previous value)*10
        xor     ah,ah
        sub     ax,030h
        add     ax,dx                   ; ax is (previous value)*10 + new
        or      ax,priv_param           ; set private parameter flag
        mov     [bx],ax
        jmp     vt_disp_ex
vt_esc_P1:
        cmp     al,'?'                  ; Private parameter ? (3/15)
        jne     vt_esc_P11
        mov     priv_param,PRIVP_FLG
        jmp     vt_disp_ex
vt_esc_P11:
        add     esc_P_pnt,2             ; separator
        mov     bx,offset esc_P_buf
        add     bx,esc_P_pnt
        mov     word ptr [bx],0         ; clear for next parameter
        jmp     vt_disp_ex
vt_esc_CI:
        mov     esc_seq,4
        jmp     vt_disp_ex

vt_esc_C1do:
        cmp     al,'K'
        jne     vt_esc_C1do_10
        jmp     vt_esc_K
vt_esc_C1do_10:
        cmp     al,'J'
        jne     vt_esc_C1do_20
        jmp     vt_esc_J
vt_esc_C1do_20:
        cmp     al,'H'
        jne     vt_esc_C1do_25
        jmp     vt_esc_H
vt_esc_C1do_25:
        cmp     al,'f'
        jne     vt_esc_C1do_30
        jmp     vt_esc_H
vt_esc_C1do_30:
        cmp     al,'A'
        jb      vt_esc_C1do_40
        cmp     al,'D'
        ja      vt_esc_C1do_40
        jmp     vt_esc_ABCD
vt_esc_C1do_40:
        cmp     al,'r'
        jne     vt_esc_C1do_50
        jmp     vt_esc_SCR
vt_esc_C1do_50:
        cmp     al,'L'
        jne     vt_esc_C1do_60
        jmp     vt_esc_L
vt_esc_C1do_60:
        cmp     al,'M'
        jne     vt_esc_C1do_70
        jmp     vt_esc_M
vt_esc_C1do_70:
        cmp     al,'m'
        jne     vt_esc_C1do_80
        jmp     vt_esc_CATR
vt_esc_C1do_80:
        cmp     al,'c'
        jne     vt_esc_C1do_90
        jmp     vt_esc_DA
vt_esc_C1do_90:
        cmp     al,'h'
        jne     vt_esc_C1do_100
        jmp     vt_esc_SET_M
vt_esc_C1do_100:
        cmp     al,'l'
        jne     vt_esc_C1do_110
        jmp     vt_esc_RESET_M
vt_esc_C1do_110:
vt_esc_C1do_ex:
        jmp     vt_esc_done
;
vt_esc_DA:
; Device attributes
        mov     si,offset I_am_vt100
        xor     cx,cx
        mov     cl,[si]
        inc     si
        mov     esc_seq,0
        ret
;
; Character attributes
;    0  All off
;    1  Bold (Highlight)
;    4  Underscored
;    5  Blinking
;    7  Reverse
;   22  Normal intensity
;   24  Not underlined
;   25  Not blinking
;   27  Positive image
;
vt_esc_CATR:
        push    cx
        push    si

        mov     si,offset esc_P_buf
        mov     cx,esc_P_pnt
        shr     cx,1
        inc     cx
vt_esc_CATR1:
        mov     bx,[si]
        cmp     bx,0
        jne     vt_esc_CATR2
        mov     al,vt_nrmatr
        mov     vt_chratr,al
        jmp     vt_esc_CATRX
vt_esc_CATR2:
        cmp     bx,1
        jne     vt_esc_CATR3
        mov     al,vt_chratr                    ; Bold
        and     al,01Fh
        or      al,vt_hglatr
        mov     vt_chratr,al
        jmp     vt_esc_CATRX
vt_esc_CATR3:
        cmp     bx,4
        jne     vt_esc_CATR5
        or      vt_chratr,8                     ; Underscored
        jmp     vt_esc_CATRX
vt_esc_CATR5:
        cmp     bx,5
        jne     vt_esc_CATR7
        or      vt_chratr,2                     ; Blinking
        jmp     vt_esc_CATRX
vt_esc_CATR7:
        cmp     bx,7
        jne     vt_esc_CATR22
        mov     al,CHR_REV                      ; Reverse
        xor     vt_chratr,al
        jmp     vt_esc_CATRX
vt_esc_CATR22:
        cmp     bx,22
        jne     vt_esc_CATR24
        jmp     vt_esc_CATRX
vt_esc_CATR24:
        cmp     bx,24
        jne     vt_esc_CATR25
        and     vt_chratr,0F7h                  ; not Underscored
        jmp     vt_esc_CATRX
vt_esc_CATR25:
        cmp     bx,25
        jne     vt_esc_CATR27
        and     vt_chratr,0FDh                  ; not blinking
        jmp     vt_esc_CATRX
vt_esc_CATR27:
        cmp     bx,27
        jne     vt_esc_CATRX
        and     vt_chratr,0FBh                  ; positive image

vt_esc_CATRX:
        add     si,2
        loop    vt_esc_CATR1
        pop     si
        pop     cx
        jmp     vt_esc_C1do_ex
;
; Set mode
;   2  Keyboard locked
;   4  Insert mode
;  12  Send-Receive off
;  20  LF is newline
;  ?1  Cursor Key is application
;  ?3  132 column
;  ?4  Smooth scroll
;  ?5  Reverse screen
;  ?6  Origin mode relative
;  ?7  Auto Wrap on
;  ?8  Auto repeate on
; ?18  Print form feed on
; ?19  Print extent is full screen
; ?25  Text cursor enable on
;
vt_esc_SET_M:
        push    cx
        push    si

        mov     si,offset esc_P_buf
        mov     cx,esc_P_pnt
        shr     cx,1
        inc     cx
vt_esc_SET_M1:
        mov     bx,[si]
        cmp     bx,1+PRIVP_FLG          ; ?1 = Cursor key application ?
        jne     vt_esc_SET_M2           ; ne = no
        mov     curkey_mode,1
        jmp     vt_esc_SET_MX
vt_esc_SET_M2:
vt_esc_SET_M3:
        cmp     bx,3+PRIVP_FLG          ; ?3 = 132 Column ?
        jne     vt_esc_SET_M4
        jmp     vt_esc_SET_MX
vt_esc_SET_M4:
vt_esc_SET_M5:
        cmp     bx,5+PRIVP_FLG          ; ?5 = reverse screen ?
        jne     vt_esc_SET_M6
        mov     ax,1
        call    scrn_mode
        jmp     vt_esc_SET_MX
vt_esc_SET_M6:
vt_esc_SET_M7:
        cmp     bx,7+PRIVP_FLG          ; ?7 = AutoWrap ?
        jne     vt_esc_SET_M8
        or      vt100_flags,AUTOWRAP_BIT
        jmp     vt_esc_SET_MX
vt_esc_SET_M8:
vt_esc_SET_MX:
        add     si,2
        loop    vt_esc_SET_M1
        pop     si
        pop     cx
        jmp     vt_esc_C1do_ex
;
; Reset mode
;   2  Keyboard Unlocked
;   4  Replace mode
;  12  Send-Receive on
;  20  LF is line feed
;  ?1  Normal cursor key
;  ?2  Enter VT52 mode
;  ?3  80 column
;  ?4  Jump scroll
;  ?5  Normal screen
;  ?6  Orgin mode is absolute
;  ?7  Auto wrap off
;  ?8  Auto repeat off
; ?18  Print form feed off
; ?19  Print extent is scroll region
; ?25  Text cursor enable off
;
vt_esc_RESET_M:
        push    cx
        push    si

        mov     si,offset esc_P_buf
        mov     cx,esc_P_pnt
        shr     cx,1
        inc     cx
vt_esc_RESET_M1:
        mov     bx,[si]
        cmp     bx,1+PRIVP_FLG          ; ?1 = Normal cursor key ?
        jne     vt_esc_RESET_M2
        mov     curkey_mode,0
        jmp     vt_esc_RESET_MX
vt_esc_RESET_M2:
vt_esc_RESET_M5:
        cmp     bx,5+PRIVP_FLG          ; ?5 = normal screen ?
        jne     vt_esc_RESET_M6
        mov     ax,0
        call    scrn_mode
        jmp     vt_esc_RESET_MX
vt_esc_RESET_M6:
vt_esc_RESET_M7:
        cmp     bx,7+PRIVP_FLG
        jne     vt_esc_RESET_M8
        and     vt100_flags,(not AUTOWRAP_BIT)
        jmp     vt_esc_RESET_MX
vt_esc_RESET_M8:
vt_esc_RESET_MX:
        add     si,2
        loop    vt_esc_RESET_M1
        pop     si
        pop     cx
        jmp     vt_esc_C1do_ex
;
vt_esc_ABCD:
        mov     bx,offset esc_P_buf
        mov     bx,[bx]
        cmp     bx,1
        jae     vt_esc_ABCD1
        mov     bx,1
vt_esc_ABCD1:
        cmp     al,'B'
        je      vt_esc_CUD
        cmp     al,'C'
        je      vt_esc_CUR
        cmp     al,'D'
        je      vt_esc_CUL
vt_esc_CUU:
        xor     ah,ah
        mov     al,cur_row
        sub     ax,bx
        xor     bh,bh
        mov     bl,vt_top
        cmp     ax,bx
        jge     vt_esc_CUU1
        mov     ax,bx
vt_esc_CUU1:
        mov     cur_row,al
        jmp     vt_esc_ABCD_ex
vt_esc_CUD:
        xor     ah,ah
        mov     al,cur_row
        add     ax,bx
        cmp     al,vt_bottom
        jle     vt_esc_CUD1
        mov     al,vt_bottom
vt_esc_CUD1:
        mov     cur_row,al
        jmp     vt_esc_ABCD_ex
vt_esc_CUR:
        xor     ah,ah
        mov     al,cur_col
        add     ax,bx
        cmp     ax,79
        jle     vt_esc_CUR1
        mov     ax,79
vt_esc_CUR1:
        mov     cur_col,al
        jmp     vt_esc_ABCD_ex
vt_esc_CUL:
        xor     ah,ah
        mov     al,cur_col
        sub     ax,bx
        cmp     ax,0
        jge     vt_esc_CUL1
        mov     ax,0
vt_esc_CUL1:
        mov     cur_col,al
vt_esc_ABCD_ex:
        call    locate_cur
        jmp     vt_esc_C1do_ex
;
vt_esc_K:
        mov     bx,offset esc_P_buf
        mov     ax,[bx]
        cmp     ax,0
        jne     vt_esc_K1
        mov     dh,cur_row
        mov     dl,cur_col
        call    vram_ofs
        mov     ax,bx
        mov     dh,cur_row
        mov     dl,79
        jmp     vt_esc_KX
vt_esc_K1:
        cmp     ax,1
        jne     vt_esc_K2
        mov     dh,cur_row
        mov     dl,0
        call    vram_ofs
        mov     ax,bx
        mov     dh,cur_row
        mov     dl,cur_col
        jmp     vt_esc_KX
vt_esc_K2:
        cmp     ax,2
        jne     vt_esc_K3
        mov     dh,cur_row
        mov     dl,0
        call    vram_ofs
        mov     ax,bx
        mov     dh,cur_row
        mov     dl,79
        jmp     vt_esc_KX
vt_esc_K3:
        jmp     vt_esc_C1do_ex
vt_esc_KX:
        call    vram_ofs
        call    vt_erase
        jmp     vt_esc_C1do_ex
;
vt_esc_L:
        mov     al,cur_row
        cmp     al,vt_top
        jge     vt_esc_L01
        jmp     vt_esc_C1do_ex
vt_esc_L01:
        cmp     al,vt_bottom
        jle     vt_esc_L02
        jmp     vt_esc_C1do_ex
vt_esc_L02:
        mov     bx,offset esc_P_buf
        mov     cx,[bx]
        cmp     cx,0
        jg      vt_esc_L1
        mov     cx,1
vt_esc_L1:
        mov     ah,vt_bottom
        call    scroll_down
        mov     cur_col,0
        call    locate_cur
        jmp     vt_esc_C1do_ex

vt_esc_M:
        mov     al,cur_row
        cmp     al,vt_top
        jge     vt_esc_M01
        jmp     vt_esc_C1do_ex
vt_esc_M01:
        cmp     al,vt_bottom
        jle     vt_esc_M02
        jmp     vt_esc_C1do_ex
vt_esc_M02:
        mov     bx,offset esc_P_buf
        mov     cx,[bx]
        cmp     cx,0
        jg      vt_esc_M1
        mov     cx,1
vt_esc_M1:
        mov     ah,vt_bottom
        call    scroll_up
        mov     cur_col,0
        call    locate_cur
        jmp     vt_esc_C1do_ex

vt_esc_J:
        mov     bx,offset esc_P_buf
        mov     ax,[bx]
        cmp     ax,0
        jg      vt_esc_J1
        mov     dh,cur_row
        mov     dl,cur_col
        call    vram_ofs
        mov     ax,bx
        mov     dh,23
        mov     dl,79
        call    vram_ofs
        jmp     vt_esc_JX
vt_esc_J1:
        cmp     ax,1
        jg      vt_esc_J2
        mov     dh,0
        mov     dl,0
        call    vram_ofs
        mov     ax,bx
        mov     dh,cur_row
        mov     dl,cur_col
        call    vram_ofs
        jmp     vt_esc_JX
vt_esc_J2:
        mov     dh,0
        mov     dl,0
        call    vram_ofs
        mov     ax,bx
        mov     dh,23
        mov     dl,79
        call    vram_ofs
vt_esc_JX:
        call    vt_erase
        jmp     vt_esc_C1do_ex
;
vt_esc_H:
        mov     bx,offset esc_P_buf
        mov     ax,[bx]
        cmp     ax,1
        jae     vt_esc_H1
        mov     ax,1
vt_esc_H1:
        cmp     ax,24
        jbe     vt_esc_H2
        mov     ax,24
vt_esc_H2:
        dec     ax
        mov     cur_row,al
        xor     ax,ax
        cmp     esc_P_pnt,2
        jb      vt_esc_H5
        mov     ax,[bx+2]
        cmp     ax,1
        jae     vt_esc_H3
        mov     ax,1
vt_esc_H3:
        cmp     ax,80
        jbe     vt_esc_H4
        mov     ax,80
vt_esc_H4:
        dec     ax
vt_esc_H5:
        mov     cur_col,al
        call    locate_cur
        jmp     vt_esc_C1do_ex

;  Set scroll region.
;  It is NOT clear that this command affects the cursor position
;  or not.  In my experence, cursor moves to the left-top corner of the
;  entire screen (i.e., same as <ESC>[1;1H ).

vt_esc_SCR:
        mov     bx,offset esc_P_buf
        mov     ax,[bx]
        cmp     ax,1
        jae     vt_esc_SCR1
        mov     ax,1
vt_esc_SCR1:
        cmp     ax,24
        jbe     vt_esc_SCR2
        mov     ax,24
vt_esc_SCR2:
        dec     ax
        mov     vt_top,al
        mov     ax,24
        cmp     esc_P_pnt,2
        jb      vt_esc_SCR4
        mov     ax,[bx+2]
        cmp     ax,1
        jae     vt_esc_SCR3
        mov     ax,24
vt_esc_SCR3:
        cmp     ax,24
        jbe     vt_esc_SCR4
        mov     ax,24
vt_esc_SCR4:
        dec     ax
vt_esc_SCR5:
        mov     vt_bottom,al
        mov     cur_row,0
        mov     cur_col,0
        call    locate_cur
        jmp     vt_esc_C1do_ex
;
; Erase from VRAM address AX to BX
;
vt_erase:
        cld
        push    es
        mov     cx,bx
        sub     cx,ax
        shr     cx,1
        inc     cx
        mov     di,ax
        push    cx
        push    di
        mov     ax,CRT_TXT_SEG
        mov     es,ax
        mov     ax,0020h
        rep     stosw
        pop     di
        add     di,2000h
        pop     cx
        xor     ah,ah
        mov     al,vt_blkatr
        rep     stosw
        pop     es
        ret

;-------------
; Scroll-down
;-------------
; scroll down n-lines in the region [Pt,Pb].  The cursor does not move.
;
; Input paramters:
;       al: top row position Pt
;       ah: bottom row position Pb
;       cl: number of lines n (must be > 0)
; Registers:
;       ax, bx, cx, dx, si, di are broken

scroll_down:
        mov     bl,ah
        sub     bl,al
        cmp     cl,bl                   ; n <= bottom - top ?
        jle     scroll_down_2           ; yes, text remains.
        jmp     scroll_down_3           ; no text remains.
scroll_down_2:
        mov     dh,ah
        sub     dh,cl
        mov     dl,79
        call    vram_ofs
        mov     si,bx                   ; si is VRAM(bottom-n,79)
        mov     dh,al
        xor     dl,dl
        call    vram_ofs
        mov     cx,si
        sub     cx,bx
        shr     cx,1                    ; byte counts -> word counts
        inc     cx                      ; number of words to be moved
        mov     dh,ah
        mov     dl,79
        call    vram_ofs
        mov     di,bx                   ; di is VRAM(bottom,79)
        push    es
        push    ds
        mov     ax,CRT_TXT_SEG
        mov     bl,vt_blkatr            ; save attribute before ds cahnge
        mov     es,ax
        mov     ds,ax
        push    cx                      ; save word count
        push    di                      ; save destination address
        push    si                      ; save source address
        std
        rep     movsw                   ; move the text codes
        mov     cx,di
        sub     cx,si
        shr     cx,1
        mov     ax,0020h                ; fill blank
        rep     stosw
;
        pop     si
        pop     di
        pop     cx                      ; cx, si, di are restored
        add     di,2000h                ; attribute block
        add     si,2000h
        rep     movsw                   ; move the attributes
        mov     cx,di
        sub     cx,si
        shr     cx,1
        mov     al,bl                   ; fill attributes
        xor     ah,ah
        rep     stosw
;
        cld
        pop     ds
        pop     es
        jmp     scroll_down_ex
scroll_down_3:
        mov     dh,al
        xor     dl,dl
        call    vram_ofs
        mov     cx,bx
        mov     dh,ah
        mov     dl,79
        call    vram_ofs
        mov     ax,cx
        call    vt_erase
scroll_down_ex:
        ret
;
;-----------
; Scroll-up
;-----------
; scroll up n-lines in the region [Pt,Pb].  The cursor does not move.
;
; Input paramters:
;       al: top row position Pt
;       ah: bottom row position Pb (ah must be > al)
;       cl: number of lines n (must be > 0)
; Registers:
;       ax, bx, cx, dx, si, di are broken

scroll_up:
        mov     bl,ah
        sub     bl,al
        cmp     cl,bl                   ; n <= bottom - top ?
        jle     scroll_up_2             ; yes, text remains.
        jmp     scroll_up_3             ; no text remains.
scroll_up_2:
        mov     dh,al
        add     dh,cl
        xor     dl,dl
        call    vram_ofs
        mov     si,bx                   ; si is VRAM(top+n,0)
        mov     dh,ah
        xor     dl,79
        call    vram_ofs
        mov     cx,bx
        sub     cx,si
        shr     cx,1                    ; byte counts -> word counts
        inc     cx                      ; number of words to be moved
        mov     dh,al
        xor     dl,dl
        call    vram_ofs
        mov     di,bx                   ; di is VRAM(top,0)
        push    es
        push    ds
        mov     ax,CRT_TXT_SEG
        mov     bl,vt_blkatr            ; save attribute before ds cahnge
        mov     es,ax
        mov     ds,ax
        push    cx                      ; save word count
        push    di                      ; save destination address
        push    si                      ; save source address
        cld
        rep     movsw                   ; move the text codes
        mov     cx,si
        sub     cx,di
        shr     cx,1
        mov     ax,0020h                ; fill blank
        rep     stosw
;
        pop     si
        pop     di
        pop     cx                      ; cx, si, di are restored
        add     di,2000h                ; attribute block
        add     si,2000h
        rep     movsw                   ; move the attributes
        mov     cx,si
        sub     cx,di
        shr     cx,1
        mov     al,bl                   ; fill attributes
        xor     ah,ah
        rep     stosw
;
        cld
        pop     ds
        pop     es
        jmp     scroll_up_ex
scroll_up_3:
        mov     dh,al
        xor     dl,dl
        call    vram_ofs
        mov     cx,bx
        mov     dh,ah
        mov     dl,79
        call    vram_ofs
        mov     ax,cx
        call    vt_erase
scroll_up_ex:
        ret

;
; Calculate VRAM offset address from (col,row)
; Inputs:
;   dh: row (0-23)
;   dl: col (0-79)
; Output:
;   bx: VRAM offset address
;
; dx is broken when return

vram_ofs:
        xor     bx,bx
        mov     bl,dh
        shl     bx,1
        add     bx,offset vram_line
        mov     bx,[bx]
        xor     dh,dh
        shl     dl,1
        add     bx,dx
        ret

; C1 8-bit control character

;----------------------
; Index ( 8/4 ); ESC D
;----------------------
; Moves the cursor down one line in the same column.  If the cursor
; is at the bottom margin, the screen perform a scroll-up.

vt_c1_IND:
        mov     ah,cur_row
        cmp     ah,vt_bottom
        jl      vt_c1_IND_1
        je      vt_c1_IND_2
        jmp     vt_esc_done
vt_c1_IND_1:
        inc     ah
        mov     cur_row,ah
        call    locate_cur
        jmp     vt_esc_done
vt_c1_IND_2:
        mov     al,vt_top
        mov     cx,1
        call    scroll_up
        jmp     vt_esc_done

;-------------------------------
; Reverse index ( 8/13 ); ESC M
;-------------------------------
; Moves the cursor up one line in the same column.  If the cursor is
; at the top margin, the screen performs a scroll-down.

vt_c1_RI:
        mov     al,cur_row
        cmp     al,vt_top
        jg      vt_c1_RI_1
        jmp     vt_c1_RI_2
vt_c1_RI_1:
        dec     al
        jmp     vt_c1_RI_3
vt_c1_RI_2:
        mov     al,vt_top
        mov     ah,vt_bottom
        mov     cx,1
        call    scroll_down
        mov     al,vt_top
vt_c1_RI_3:
        mov     cur_row,al
        call    locate_cur
        jmp     vt_esc_done

;--------------------------
; Next line ( 8/5 ); ESC E
;--------------------------
; Moves the cursor to the first position on the next line.
; If the cursor is at the bottom margin, the screen performs a
; scroll-up.

vt_c1_NEL:
        mov     ah,cur_row
        cmp     ah,vt_bottom
        jl      vt_c1_NEL_1
        je      vt_c1_NEL_2
        jmp     vt_esc_done
vt_c1_NEL_1:
        inc     ah
        mov     cur_row,ah
        mov     cur_col,0
        call    locate_cur
        jmp     vt_esc_done
vt_c1_NEL_2:
        mov     al,vt_top
        mov     cx,1
        call    scroll_up
        mov     cur_col,0
        call    locate_cur
        jmp     vt_esc_done

;
VT100   ENDP

code    ends
        end