Metropoli BBS
VIEWER: comdebug.asm MODE: TEXT (CP437)
                        title  COMDEBUG.ASM
                        page   55, 132


COMMENT!

Written by Peter Shier at TADIRAN Givat Shmuel January 1987

This program is a RAM resident serial communications status monitor. It is
installed by typing

        COMDEBUG

at the dos prompt. To activate press ALT + Scroll Lock. The state of modem
status, line status and modem control registers is displayed. The DTR line is
highlighted in reverse video and this is considered to be the "cursor"
position. The following keys are now active:

1/0                                     Raise/lower the line highlighted by the cursor

D                                       Display registers

Left/right arrows   Move cursor between DTR and RTS

C                   Change com port no.

Esc                 Exit


Com ports 1 to 10 are supported. COM1 and COM2 are at their usual addresses.
(i.e. COM1 at 3F8H and COM2 at 2F8H). COM3 - COM10 start at BASE_ADDRESS and
have a distance between them of PORT_DISPLACEMENT.

!




push_all        macro

                        push    ax
                        push    bx
                        push    cx
                        push    dx
                        push    di
                        push    si
                        push    bp
                        push    ds
                        push    es
                        pushf
                        endm

pop_all         macro

                        popf
                        pop             es
                        pop             ds
                        pop             bp
                        pop             si
                        pop             di
                        pop             dx
                        pop             cx
                        pop             bx
                        pop             ax
                        endm




TRUE  equ 1
FALSE equ 0

ESCP                    equ     1
D                       equ     32
C                       equ     46
ONE                     equ     2
NUM_ONE         equ     79
ZERO            equ     11
NUM_ZERO        equ     82
LEFT            equ     75
RIGHT           equ     77

ALT_SHIFT               equ 08h
SCROLL_SHIFT    equ     10h

KB_DATA equ 60h
KB_CTL  equ     61h


ON      equ     1
OFF equ 0

REV_VIDEO       EQU     70H         ; video attributes for display routines
NORM_VIDEO      EQU     07H
BOLD            EQU 0FH
BOLD_UNDERL EQU 09H
BLINK           EQU 87H



;-------------------------- for special adapter cards to add COM ports

BASE_ADDRESS            equ     280h    ; base address of card i.e. COM3
PORT_DISPLACEMENT       equ 8       ; offset from COMn to COMn + 1 for card
MCONT                           equ 4
LSTAT                           equ 5
MSTAT                           equ 6





;--------------------- modem status

D_CTS   equ     01h
D_DSR   equ     02h
TERI    equ     04h
D_RLSD  equ     08h
CTS             equ     10h
DSR             equ     20h
RI              equ     40h
RLSD    equ     80h



;-------------------- line status

DATA_READY      equ     01h
OVERRUN         equ     02h
PARITY          equ     04h
FRAMING         equ     08h
BREAK           equ     10h
THRE            equ     20h
TSRE            equ     40h



;-------------------- modem control

DTR             equ     01h
RTS             equ     02h



code    segment
                assume cs:code, ds:code, es:code, ss:code
                        org             100h

first:
                        jmp     loader
                        ;jmp    tester

ASCII_signature         db "COMDEBUG by Peter Shier at TADIRAN Givat Shmuel 01/87"

busy                            db      FALSE
old_int9_off            dw      0
old_int9_seg            dw      0
graphics                        db      FALSE
video_ram                       dw      0     ; video ram segment
crt_status_port         dw      0
crt_control_port        dw      0
start_offset            dw      0         ; beginning offset in screen seg. for PRINTAT
str_ptr                         dw      0         ; pointer to ASCIIZ string to print
row                             db      0         ; row, col to print at
col                             db      0
attribute                       db      0         ; desired attribute
screen_storage          db      4000 dup(?) ;temp storage for screen contents
modem_control           dw      03fch
line_status                     dw      03fdh
modem_status            dw      03feh
port                            db      '01', 0
cursor                          db      DTR
bit                                     db      ?, 0
saved_cursor_pos        dw      ?


main_frame_msg  db " C O M D E B U G ", 0
main_frame_1    db "╔════════════════════════════════════════════════════════════════════╗", 0
main_frame_2    db "║                                                                    ║", 0
main_frame_3    db "╚════════════════════════════════════════════════════════════════════╝", 0

mod_stat_msg_1   db " Modem Status ", 0
mod_stat_msg_2   db "Delta CTS  Delta DSR  TERI  Delta RLSD  CTS  DSR  RI  RLSD", 0
mod_stat_frame_1 db "┌──────────────────────────────────────────────────────────┐", 0
mod_stat_frame_2 db "│                                                          │", 0
mod_stat_frame_3 db "└──────────────────────────────────────────────────────────┘", 0

lin_stat_msg_1   db " Line  Status ", 0
lin_stat_msg_2   db "Data Ready  Overrun  Parity  Framing  Break  THRE  TSRE", 0
lin_stat_frame_1 db "┌────────────────────────────────────────────────────────┐", 0
lin_stat_frame_2 db "│                                                        │", 0
lin_stat_frame_3 db "└────────────────────────────────────────────────────────┘", 0

mod_ctrl_msg_1   db "Mod Ctrl", 0
mod_Ctrl_msg_2   db "DTR  RTS", 0
mod_ctrl_frame_1 db "┌────────┐", 0
mod_ctrl_frame_2 db "│        │", 0
mod_ctrl_frame_3 db "└────────┘", 0

instruct_msg_1 db "<- ->  Move cursor", 0
instruct_msg_2 db "D  Display registers", 0
instruct_msg_3 db "1/0  Raise/lower DTR/RTS", 0
instruct_msg_4 db "C  Change com port", 0
instruct_msg_5 db "Esc  Exit", 0
instruct_msg_6 db "Com port = ", 0



tester          proc    near

                        call    get_video_mode
                        call    display_screen
t_10:
                        mov             ah, 0
                        int             16h
                        cmp             al, 1bh
                        jne             t_15
                        ret
t_15:
                        xchg    al, ah
                        call    com_debug
                        jmp             t_10

tester          endp


new_int9:
                        sti
                        push_all

                        push    cs
                        pop             ds

                        cmp             busy, TRUE
                        je              now_busy
                        pushf
                        call    dword ptr old_int9_off
                        mov             ax, 40h
                        mov             es, ax
                        test    byte ptr es:[17h], ALT_SHIFT
                        jz              done
                        test    byte ptr es:[18h], SCROLL_SHIFT
                        jz              done
                        mov             busy, TRUE
                        mov             al, ALT_SHIFT
                        not             al
                        and             byte ptr es:[17h], al
                        mov             al, SCROLL_SHIFT
                        not             al
                        and             byte ptr es:[18h], al
                        call    save_screen
                        call    save_cursor
done:
                        pop_all
                        iret

now_busy:
                        call    get_scan_code     ; returns scan code in al
                        cmp             al, 80h
                        jae             eoi
                        cmp             al, ESCP
                        jne             still_on
                        call    restore_screen
                        call    restore_cursor
                        mov             busy, FALSE
                        jmp             eoi
still_on:
                        call    com_debug      ; recieves scan code in al
eoi:
                        mov             al, 20h
                        out             20h, al
                        pop_all
                        iret





get_scan_code   proc    near

                        in              al, KB_DATA
                        push    ax
                        in              al, KB_CTL
                        mov             ah, al
                        or              al, 80h
                        out             KB_CTL, al
                        xchg    ah, al
                        out             KB_CTL, al
                        pop             ax
                        ret

get_scan_code   endp




save_cursor             proc    near

                        mov             ah, 03h
                        mov             bh, 00h
                        int             10h
                        mov             saved_cursor_pos, dx

                        mov             ah, 02h
                        mov             bh, 00h
                        mov             dh, 25
                        mov             dl, 0
                        int             10h
                        ret

save_cursor             endp



restore_cursor          proc    near

                        mov             ah, 02h
                        mov             bh, 00h
                        mov             dx, saved_cursor_pos
                        int             10h
                        ret

restore_cursor          endp


com_debug       proc    near

; recieves scan code in al

                        cmp             al, D
                        jne             cd_10
                        call    display_modem_status
                        call    display_line_status
                        call    display_modem_control
                        ret
cd_10:
                        cmp             al, C
                        jne             cd_20
                        call    change_port
                        call    display_port
                        call    display_modem_status
                        call    display_line_status
                        call    display_modem_control
                        ret
cd_20:
                        cmp             al, ONE
                        je              cd_30
                        cmp             al, NUM_ONE
                        jne             cd_40
cd_30:
                        mov             ah, cursor
                        mov             bh, ON
                        call    set_modem_control
                        call    display_modem_control
                        ret
cd_40:
                        cmp             al, ZERO
                        je              cd_50
                        cmp             al, NUM_ZERO
                        jne             cd_60
cd_50:
                        mov             ah, cursor
                        mov             bh, OFF
                        call    set_modem_control
                        call    display_modem_control
                        ret
cd_60:
                        cmp             al, LEFT
                        je              cd_70
                        cmp             al, RIGHT
                        jne             cd_100
cd_70:
                        cmp             cursor, DTR
                        jne             cd_80
                        mov             cursor, RTS
                        jmp             cd_90
cd_80:
                        mov             cursor, DTR
cd_90:
                        call    display_modem_control
                        ret
cd_100:
                        mov             ah, 0eh
                        mov             al, 07h
                        int             10h
                        ret

com_debug       endp





change_port             proc    near


; 'C' was pressed - must change all register addresses to those of next port

                        cmp             port + 1, '1'             ; was port 1?
                        jne             cp_10                     ; no - check for 10
                        mov             modem_control, 02fch      ; yes - set addresses for COM2
                        mov             line_status,   02fdh
                        mov             modem_status,  02feh
                        inc             port + 1                  ; set display digit
                        ret                               ; and done
cp_10:
                        cmp             port, '1'                 ; was port 10?
                        jne             cp_20                     ; no - check for 2
                        mov             port + 1, '1'             ; yes - set up for COM1
                        mov             port, '0'
                        mov             modem_control, 03fch
                        mov             line_status,   03fdh
                        mov             modem_status,  03feh
                        ret
cp_20:

                        cmp             port + 1, '2'                       ; was port 2?
                        jne             cp_30                               ; no - must be 3 - 10
                        inc             port + 1                            ; yes - set up for COM3
                        mov             modem_control, BASE_ADDRESS + MCONT
                        mov             line_status,   BASE_ADDRESS + LSTAT
                        mov             modem_status,  BASE_ADDRESS + MSTAT
                        ret
cp_30:
                        inc             port + 1                 ; port was 3 - 10
                        cmp             port + 1, 3ah            ; is this 10?
                        jne             cp_40                    ; no - set addresses
                        mov             port, '1'                ; yes - fix up display
                        mov             port + 1, '0'
cp_40:
                        add             modem_control, PORT_DISPLACEMENT  ; just increment present
                        add             line_status, PORT_DISPLACEMENT    ; values
                        add             modem_status, PORT_DISPLACEMENT
                        ret


change_port             endp





display_screen  proc    near


                        mov             str_ptr, offset main_frame_1
                        mov             row, 2
                        mov             col, 5
                        mov             attribute, BOLD
                        call    printat

                        mov             cx, 19
                        mov             row, 3
main_loop:
                        push    cx
                        mov             str_ptr, offset main_frame_2
                        mov             col, 5
                        mov             attribute, BOLD
                        call    printat
                        pop             cx
                        inc             row
                        loop    main_loop

                        mov             str_ptr, offset main_frame_3
                        mov             row, 21
                        mov             col, 5
                        mov             attribute, BOLD
                        call    printat

                        mov             str_ptr, offset main_frame_msg
                        mov             row, 2
                        mov             col, 30
                        mov             attribute, REV_VIDEO
                        call    printat

                        mov             str_ptr, offset mod_stat_frame_1
                        mov             row, 4
                        mov             col, 9
                        mov             attribute, BOLD
                        call    printat

                        mov             cx, 3
                        mov             row, 5

mod_stat_loop:

                        push    cx
                        mov             str_ptr, offset mod_stat_frame_2
                        mov             col, 9
                        mov             attribute, BOLD
                        call    printat
                        pop             cx
                        inc             row
                        loop    mod_stat_loop

                        mov             str_ptr, offset mod_stat_frame_3
                        mov             row, 8
                        mov             col, 9
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 4
                        mov             col, 31
                        mov             str_ptr, offset mod_stat_msg_1
                        mov             attribute, REV_VIDEO
                        call    printat

                        mov             row, 6
                        mov             col, 10
                        mov             str_ptr, offset mod_stat_msg_2
                        mov             attribute, BOLD
                        call    printat



                        mov             str_ptr, offset lin_stat_frame_1
                        mov             row, 9
                        mov             col, 10
                        mov             attribute, BOLD
                        call    printat

                        mov             cx, 3
                        mov             row, 10

lin_stat_loop:

                        push    cx
                        mov             str_ptr, offset lin_stat_frame_2
                        mov             col, 10
                        mov             attribute, BOLD
                        call    printat
                        pop             cx
                        inc             row
                        loop    lin_stat_loop

                        mov             str_ptr, offset lin_stat_frame_3
                        mov             row, 13
                        mov             col, 10
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 9
                        mov             col, 31
                        mov             str_ptr, offset lin_stat_msg_1
                        mov             attribute, REV_VIDEO
                        call    printat

                        mov             row, 11
                        mov             col, 11
                        mov             str_ptr, offset lin_stat_msg_2
                        mov             attribute, BOLD
                        call    printat


                        mov             str_ptr, offset mod_ctrl_frame_1
                        mov             row, 15
                        mov             col, 10
                        mov             attribute, BOLD
                        call    printat

                        mov             cx, 3
                        mov             row, 16

mod_ctrl_loop:

                        push    cx
                        mov             str_ptr, offset mod_ctrl_frame_2
                        mov             col, 10
                        mov             attribute, BOLD
                        call    printat
                        pop             cx
                        inc             row
                        loop    mod_ctrl_loop

                        mov             str_ptr, offset mod_ctrl_frame_3
                        mov             row, 19
                        mov             col, 10
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 15
                        mov             col, 11
                        mov             str_ptr, offset mod_ctrl_msg_1
                        mov             attribute, REV_VIDEO
                        call    printat

                        mov             row, 17
                        mov             col, 11
                        mov             str_ptr, offset mod_ctrl_msg_2
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 16
                        mov             col, 28
                        mov             str_ptr, offset instruct_msg_1
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 17
                        mov             col, 32
                        mov             str_ptr, offset instruct_msg_2
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 18
                        mov             col, 30
                        mov             str_ptr, offset instruct_msg_3
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 19
                        mov             col, 32
                        mov             str_ptr, offset instruct_msg_4
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 20
                        mov             col, 30
                        mov             str_ptr, offset instruct_msg_5
                        mov             attribute, BOLD
                        call    printat

                        mov             row, 16
                        mov             col, 59
                        mov             str_ptr, offset instruct_msg_6
                        mov             attribute, BOLD
                        call    printat

                        call    display_port
                        call    display_modem_status
                        call    display_line_status
                        call    display_modem_control


                        ret

display_screen  endp





display_modem_status    proc    near

                        mov             dx, modem_status
                        in              al, dx

                        test    al, D_CTS
                        jz              dms_10
                        mov             bit, '1'
                        jmp             dms_20
dms_10:
                        mov             bit, '0'
dms_20:
                        mov             row, 7
                        mov             col, 14
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, D_DSR
                        jz              dms_30
                        mov             bit, '1'
                        jmp             dms_40
dms_30:
                        mov             bit, '0'
dms_40:
                        mov             row, 7
                        mov             col, 26
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, TERI
                        jz              dms_50
                        mov             bit, '1'
                        jmp             dms_60
dms_50:
                        mov             bit, '0'
dms_60:
                        mov             row, 7
                        mov             col, 33
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, D_RLSD
                        jz              dms_70
                        mov             bit, '1'
                        jmp             dms_80
dms_70:
                        mov             bit, '0'
dms_80:
                        mov             row, 7
                        mov             col, 42
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, CTS
                        jz              dms_90
                        mov             bit, '1'
                        jmp             dms_100
dms_90:
                        mov             bit, '0'
dms_100:
                        mov             row, 7
                        mov             col, 51
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, DSR
                        jz              dms_110
                        mov             bit, '1'
                        jmp             dms_120
dms_110:
                        mov             bit, '0'
dms_120:
                        mov             row, 7
                        mov             col, 56
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, RI
                        jz              dms_130
                        mov             bit, '1'
                        jmp             dms_140
dms_130:
                        mov             bit, '0'
dms_140:
                        mov             row, 7
                        mov             col, 60
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, RLSD
                        jz              dms_150
                        mov             bit, '1'
                        jmp             dms_160
dms_150:
                        mov             bit, '0'
dms_160:
                        mov             row, 7
                        mov             col, 65
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        call    printat

                        ret

display_modem_status    endp



display_modem_control   proc    near

                        mov             dx, modem_control
                        in              al, dx

                        test    al, DTR
                        jz              dmc_10
                        mov             bit, '1'
                        jmp             dmc_20
dmc_10:
                        mov             bit, '0'
dmc_20:
                        cmp             cursor, DTR
                        jne             dmc_30
                        mov             attribute, REV_VIDEO
                        jmp             dmc_40
dmc_30:
                        mov             attribute, NORM_VIDEO
dmc_40:
                        mov             row, 18
                        mov             col, 12
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, RTS
                        jz              dmc_50
                        mov             bit, '1'
                        jmp             dmc_60
dmc_50:
                        mov             bit, '0'
dmc_60:
                        cmp             cursor, RTS
                        jne             dmc_70
                        mov             attribute, REV_VIDEO
                        jmp             dmc_80
dmc_70:
                        mov             attribute, NORM_VIDEO
dmc_80:
                        mov             row, 18
                        mov             col, 17
                        mov             str_ptr, offset bit
                        call    printat

                        ret

display_modem_control   endp






set_modem_control       proc    near

; recieves mask in ah, change flag in bh

                        mov             dx, modem_control
                        in              al, dx

                        cmp             bh, ON
                        jne             smc_10
                        or              al, ah
                        jmp             smc_20
smc_10:
                        not             ah
                        and             al, ah
smc_20:
                        out             dx, al
                        ret

set_modem_control       endp





display_line_status     proc    near

                        mov             dx, line_status
                        in              al, dx

                        test    al, DATA_READY
                        jz              dls_10
                        mov             bit, '1'
                        jmp             dls_20
dls_10:
                        mov             bit, '0'
dls_20:
                        mov             row, 12
                        mov             col, 15
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, OVERRUN
                        jz              dls_30
                        mov             bit, '1'
                        jmp             dls_40
dls_30:
                        mov             bit, '0'
dls_40:
                        mov             row, 12
                        mov             col, 26
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, PARITY
                        jz              dls_50
                        mov             bit, '1'
                        jmp             dls_60
dls_50:
                        mov             bit, '0'
dls_60:
                        mov             row, 12
                        mov             col, 34
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, FRAMING
                        jz              dls_70
                        mov             bit, '1'
                        jmp             dls_80
dls_70:
                        mov             bit, '0'
dls_80:
                        mov             row, 12
                        mov             col, 43
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, BREAK
                        jz              dls_90
                        mov             bit, '1'
                        jmp             dls_100
dls_90:
                        mov             bit, '0'
dls_100:
                        mov             row, 12
                        mov             col, 51
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, THRE
                        jz              dls_110
                        mov             bit, '1'
                        jmp             dls_120
dls_110:
                        mov             bit, '0'
dls_120:
                        mov             row, 12
                        mov             col, 57
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        push    ax
                        call    printat
                        pop             ax

                        test    al, TSRE
                        jz              dls_130
                        mov             bit, '1'
                        jmp             dls_140
dls_130:
                        mov             bit, '0'
dls_140:
                        mov             row, 12
                        mov             col, 63
                        mov             attribute, NORM_VIDEO
                        mov             str_ptr, offset bit
                        call    printat

                        ret

display_line_status     endp












display_port    proc    near

                        mov             row, 16
                        mov             col, 70
                        mov             str_ptr, offset port
                        mov             attribute, BOLD
                        call    printat
                        ret

display_port    endp


save_screen proc near

;----------------------------------------------------------------------------
; this procedure stores the entire contents of the video ram buffer to a safe
; place
;----------------------------------------------------------------------------

        mov             dx, crt_control_port

        cld
        push ds
        push ds
        pop es
        mov di, offset screen_storage
        mov ax, video_ram
        mov ds, ax
        ;cmp ax, 0b800h
        ;jne save_10

        push    es
        mov             ax, 40h
        mov             es, ax
        mov             al, es:[65h]
        mov             bh, al
        and             al, 0f7h
        out             dx, al
        pop             es


save_10:

        mov si, 0
        mov cx, 2000
        rep movsw

        pop ds
        ;cmp            video_ram, 0b800h
        ;jne            save_20
        mov             al, bh
        push    ax
        push    dx
        call    display_screen
        pop             dx
        pop             ax
        out             dx, al

save_20:

        ret

save_screen endp




restore_screen proc near

;----------------------------------------------------------------------------
; procedure to restore original contents of video ram
;----------------------------------------------------------------------------

        cld
        push ds
        pop es
        mov si, offset screen_storage
        mov ax, video_ram
        mov es, ax
        cmp ax, 0b800h
        jne res_10

        push    es
        mov             dx, crt_control_port
        mov             ax, 40h
        mov             es, ax
        mov             al, es:[65h]
        mov             bh, al
        and             al, 0f7h
        out             dx, al
        pop             es

res_10:

        mov di, 0
        mov cx, 2000
        rep movsw
        cmp     video_ram, 0b800h
        jne     res_20
        mov     al, bh
        out     dx, al

res_20:

        ret

restore_screen endp




printat proc near

;----------------------------------------------------------------------------
; procedure to write an asciiz string to video ram. printat gets its
; parameters from the following variables:
;
; str_ptr   dw  pointer to asciiz string to display
; row       db  row to display at  (0 - 24)
; col       db  column to display at  (0 - 79)
; attribute db  attribute to display with
;
; The caller need only fill these variables and then call printat. A variable
; video_ram dw ? must also be present and contain the segment of the video ram.
;----------------------------------------------------------------------------

                        xor             ax, ax
                        mov             al, row             ; calculate relative
                        mov     cl, 80              ; offset of starting position
                        mul             cl                      ; from start of video ram
                        xor     bh, bh
                        mov             bl, col
                        add             ax, bx
                        shl             ax, 1                           ; offset = ((row x 80) + col) * 2
                        mov             di, ax              ; di will index video ram


                        mov             bx, video_ram       ; initialize es to video ram
                        mov             es, bx
                        mov             ah, attribute            ; ah = attribute
                        mov             bx, str_ptr          ; bx = pointer to string
                        mov             si, 00               ; si will index string
                        mov     dx, crt_status_port

printat_10:
                        cmp             byte ptr ds:[bx + si], 0    ; is this null byte?
                        je              printat_20                  ; yes - all done
                        mov             cl, byte ptr ds:[bx + si]   ; no - enter byte
wait_1:
                        in              al, dx
                        test    al, 1
                        jnz             wait_1
                        cli
wait_2:
                        in              al, dx
                        test    al, 1
                        jz              wait_2
                        mov             es:[di], cl
                        sti
                        inc             di                                                      ; once for character byte
wait_3:
                        in              al, dx
                        test    al, 1
                        jnz             wait_3
                        cli
wait_4:
                        in              al, dx
                        test    al, 1
                        jz              wait_4
                        mov             es:[di], ah                             ; enter attribute byte
                        sti
                        inc             di                                                      ; once for attribute byte
                        inc             si                          ; ++string
                        jmp             printat_10
printat_20:
                        ret                                                                     ; all done

printat         endp



loader          proc    near


                        call    get_video_mode

                        mov             ah, 35h
                        mov             al, 09h
                        int             21h
                        mov             old_int9_off, bx
                        mov             old_int9_seg, es

                        mov             ah, 25h
                        mov             al, 09h
                        mov             dx, offset new_int9
                        int             21h


                        mov             dx, offset sign_on_msg
                        mov             ah, 09h
                        int             21h

                        mov             dx, offset loader
                        int             27h

                        ret

loader          endp




get_video_mode proc near


        mov     ax, 40h
        mov     es, ax
        mov     ax, es:[63h]
        add     ax, 4
        mov     crt_control_port, ax
        add     ax, 2
        mov             crt_status_port, ax
        mov             video_ram, 0b000h
        mov             ah, 15                          ; check if graphics display
        int             10h
        test    al, 4
        jnz             got_mode
        mov             video_ram, 0b800h       ; if so then adjust video ram address
        mov             graphics, true

got_mode:

        ret

get_video_mode endp


sign_on_msg             db      0dh, 0ah
                                db      "COMDEBUG now resident - Alt + Scroll Lock to activate"
                                db      0dh, 0ah, '$'


code            ends
                        end     first

[ RETURN TO DIRECTORY ]