home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TM40.ZIP / TM.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-07-20  |  23.1 KB  |  635 lines

  1. {$C-,V-,K-}
  2. (****************************************************************************)
  3. (*                                                                          *)
  4. (*   Author:   Paul Meiners                                                 *)
  5. (*             P & M  Software Company                                      *)
  6. (*             9350 Country Creek #30                                       *)
  7. (*             Houston, Texas 77036                                         *)
  8. (*                                                                          *)
  9. (*   Phone:    (713) 772-2090                                               *)
  10. (*                                                                          *)
  11. (*   Date:     March 3, 1985                                                *)
  12. (*                                                                          *)
  13. (*   Language: Turbo PASCAL version 3.00B                                   *)
  14. (*                                                                          *)
  15. (*   Remarks:  This program provides terminal emulation with capture to     *)
  16. (*             to disk, XMODEM file transfers, color and music.  Uses       *)
  17. (*             interrupt driven serial I/O with circular queues.  Uses a    *)
  18. (*             removable window system.  VT-100 emulation is optional.      *)
  19. (*                                                                          *)
  20. (****************************************************************************)
  21.  
  22. program
  23.    TMODEM;
  24.  
  25. type
  26.    strtype             = string[255];
  27.    string40            = string[40];
  28.    string30            = string[30];
  29.    string20            = string[20];
  30.    string10            = string[10];
  31.    alt_char_array      = array[ 96..127 ] of byte;
  32.    tab_stop_array      = array[ 1..80 ] of byte;
  33.  
  34. const
  35.    version             = '4.0';
  36.    sin_buf_size        = 5120;
  37.    sin_buf_fill_lim    = 3072;
  38.    sin_buf_drain_lim   = 2048;
  39.    sout_buf_size       = 512;
  40.    capture_buf_size    = 1024;
  41.    max_dial_entries    = 16;
  42.    SOH                 = ^A;
  43.    SYN                 = ^V;
  44.    CAN                 = ^X;
  45.    NAK                 = ^U;
  46.    ACK                 = ^F;
  47.    EOT                 = ^D;
  48.    SUB                 = ^Z;
  49.    BADNAME             = #$75;
  50.    CR                  = ^M;
  51.    LF                  = ^J;
  52.    CRLF                = ^M^J;
  53.    ESC                 = #27;
  54.    NUL                 = #00;
  55.    DEL                 = #127;
  56.    FF                  = ^L;
  57.    BS                  = ^H;
  58.    HT                  = ^I;
  59.    VT                  = ^K;
  60.    default_stopbits    : integer = 1;
  61.    default_databits    : integer = 8;
  62.    default_parity      : integer = 0;       { 0=None, 1=Even, 2=Odd }
  63.    default_baud        : integer = 1200;
  64.    wait_increment      : integer = 333;     { 1/3 of a second.      }
  65.    datasegment         : integer = 0;
  66.    XON                 : integer = 17;      { XON  is a DC1 character. }
  67.    XOFF                : integer = 19;      { XOFF is a DC3 character. }
  68.    dial_pre_str        : string40 = 'ATDT ';
  69.    dial_post_str       : string10 = '|';
  70.    modem_init_str      : string40 = 'AT S0=0|';
  71.    speaker_off         : string40 = 'AT M0|';
  72.    speaker_on          : string40 = 'AT M1|';
  73.    forced_carrier      : string10 = 'FALSE';
  74.    emulation_mode      : string10 = 'FALSE';
  75.    auto_LF             : string10 = 'FALSE';
  76.    redial_time         : integer  = 60;
  77.    carrier_timeout     : integer  = 35;
  78.    com_port            : integer  = 1;
  79.    comment_ch          : char = ';';
  80.    FGcolor             : integer = 15;
  81.    BGcolor             : integer = 0;
  82.    split_screen        : string10 = 'FALSE';
  83.    max_xmodem_buffers  : integer = 64;
  84.    alt_character       : alt_char_array = ( 4,97,98,99,100,101,102,241,104,105,
  85.                          217,191,218,192,197,196,196,196,196,196,195,180,193,
  86.                          194,179,243,242,227,216,156,250,127 );
  87.    tab_stop            : tab_stop_array = ( 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
  88.                                             1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
  89.                                             1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
  90.                                             1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
  91.                                             1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 );
  92. type
  93.    sin_buffer_type     = array[1..sin_buf_size] of byte;
  94.    sout_buffer_type    = array[1..sout_buf_size] of byte;
  95.    func_buffer_type    = array[1..40] of string[75];
  96.    capture_ptr_type    = ^capture_record;
  97.    capture_record      = record
  98.                             capture_store_ptr  : integer;
  99.                             capture_buffer     : array[1..capture_buf_size] of char;
  100.                             capture_next       : capture_ptr_type;
  101.                          end;
  102.    xmodem_buf          = array[1..128] of char;
  103.    xmodem_table        = array[1..255] of xmodem_buf;
  104.    registerset         = record
  105.                             AX,BX,CX,DX,BP,DI,SE,DS,ES,Flags : integer;
  106.                          end;
  107.    dialrec             = record
  108.                             bbs_name            : string30;
  109.                             bbs_number          : string30;
  110.                             bbs_baud            : integer;
  111.                             bbs_parity          : integer;
  112.                             bbs_databits        : integer;
  113.                             bbs_stopbits        : integer;
  114.                          end;
  115.    dialarray           = record
  116.                             no_of_dial_entries  : integer;
  117.                             dir_entries         :
  118.                                 array[1..max_dial_entries] of dialrec;
  119.                          end;
  120.    sort_ptr_type       = ^dialsort;
  121.    dialsort            = record
  122.                             sort_rec            : dialrec;
  123.                             sort_next           : sort_ptr_type;
  124.                          end;
  125.    screen_char         = record
  126.                             disp_char : char;
  127.                             disp_attr : byte;
  128.                          end;
  129.    screen_line         = array[1..80] of screen_char;
  130.    screen_type         = array[1..24] of screen_line;
  131.    saved_cursor        = record
  132.                             x_coor : integer;
  133.                             y_coor : integer;
  134.                             bscan  : integer;
  135.                             sscan  : integer;
  136.                             ForeG  : integer;
  137.                             BackG  : integer;
  138.                          end;
  139.    telink_header       = record
  140.                             telink_buf_len       : byte;
  141.                             telink_hdr_id        : char;
  142.                             telink_blk_no        : byte;
  143.                             telink_blk_cmpl      : byte;
  144.                             telink_file_size     : array[1..4] of byte;
  145.                             telink_create_time   : array[1..4] of byte;
  146.                             telink_filename      : array[1..16] of char;
  147.                             telink_version       : byte;
  148.                             telink_prog_name     : array[1..16] of char;
  149.                          end;
  150.  
  151. var
  152.    mono_scr            : screen_type absolute $B000:$0000;
  153.    color_scr           : screen_type absolute $B800:$0000;
  154.    crt_mode            : byte        absolute $0040:$0049;
  155.    scroll_top          : byte;
  156.    scroll_bot          : byte;
  157.    scroll_region       : boolean;
  158.    scroll_last         : byte;
  159.    sin_buf_fill_cnt    : integer;
  160.    sin_xoff            : boolean;
  161.    sin_buffer_ptr      : ^sin_buffer_type;
  162.    sin_store_ptr       : integer;
  163.    sin_read_ptr        : integer;
  164.    sout_buffer_ptr     : ^sout_buffer_type;
  165.    sout_store_ptr      : integer;
  166.    sout_read_ptr       : integer;
  167.    sout_int_off        : boolean;
  168.    turn_IRQ_on         : byte;
  169.    turn_IRQ_off        : byte;
  170.    IRQ_vector_ofs      : integer;
  171.    IRQ_vector_seg      : integer;
  172.    hold_vector_ofs     : integer;
  173.    hold_vector_seg     : integer;
  174.    com_addr            : array[ 1..2 ] of integer absolute $0000:$0400;
  175.    base_com_addr       : integer;
  176.    int_enable_reg      : integer;
  177.    int_ident_reg       : integer;
  178.    int_ident           : byte;
  179.    line_control_reg    : integer;
  180.    modem_control_reg   : integer;
  181.    line_status_reg     : integer;
  182.    line_status         : byte;
  183.    modem_status_reg    : integer;
  184.    sync_time           : integer;
  185.    xmodem_table_ptr    : ^xmodem_table;
  186.    old_max             : integer;
  187.    old_screen          : string10;
  188.    xmodem_buf_cnt      : integer;
  189.    xmodem_ptr          : integer;
  190.    xmodem_rd           : integer;
  191.    xblocksize          : integer;
  192.    xfilesize           : integer;
  193.    batch_mode          : boolean;
  194.    recv_file_size      : real;
  195.    recv_create_time    : array[1..4] of byte;
  196.    recv_date_time      : array[1..2] of integer absolute recv_create_time;
  197.    crc_register        : integer;
  198.    crc_input           : integer;
  199.    crc_mode            : boolean;
  200.    continue_transfer   : boolean;
  201.    capture_flag        : boolean;
  202.    capture_warning     : boolean;
  203.    capture_first       : capture_ptr_type;
  204.    capture_curr        : capture_ptr_type;
  205.    printer_on          : boolean;
  206.    printer_control_off : boolean;
  207.    sort_curr           : sort_ptr_type;
  208.    sort_first          : sort_ptr_type;
  209.    sort_prev           : sort_ptr_type;
  210.    exit_program        : boolean;
  211.    default_chg         : boolean;
  212.    func_key            : ^func_buffer_type;
  213.    keyfile             : text;
  214.    block_count         : integer;
  215.    error_count         : integer;
  216.    filename            : string40;
  217.    recv_file           : file;
  218.    xmit_file           : file;
  219.    size_file           : file of byte;
  220.    textfile            : text;
  221.    textimage           : strtype;
  222.    dial_drive          : integer;
  223.    dial_PATH           : string40;
  224.    cnf_PATH            : string40;
  225.    dialfile            : file of dialarray;
  226.    dial_dir            : dialarray;
  227.    dialarray_number    : integer;
  228.    dial_str            : string40;
  229.    redial_number       : string40;
  230.    redial_name         : string30;
  231.    baud                : integer;
  232.    stopbits            : integer;
  233.    databits            : integer;
  234.    par                 : integer;
  235.    kbd_char            : char;
  236.    a_key               : string[2];
  237.    regs                : registerset;
  238.    half_duplex         : boolean;
  239.    ascii_mode          : boolean;
  240.    escape_mode         : boolean;
  241.    escape_number       : byte;
  242.    escape_register     : array[1..50] of byte;
  243.    escape_str          : strtype;
  244.    escape_type         : char;
  245.    escape_sub_type     : char;
  246.    line_drawing_chars  : boolean;
  247.    ok                  : boolean;
  248.    parity_ch           : string10;
  249.    baud_ch             : string10;
  250.    stop_ch             : string10;
  251.    data_ch             : string10;
  252.    FG,BG               : integer;
  253.    shade_no            : integer;
  254.    FG_shade            : array[ 0..7 ] of integer;
  255.    blink_state         : integer;
  256.    intensity_state     : integer;
  257.    scale               : array[ 0..20 ] of real;
  258.    notes               : array[ 1..84 ] of integer;
  259.    factor              : array[ 0..6 ] of real;
  260.    tempo               : real;
  261.    note_length         : integer;
  262.    octave              : integer;
  263.    dots                : integer;
  264.    dnote               : array[ 0..6 ] of real;
  265.    music_mode          : real;
  266.    rest_mode           : real;
  267.    silent_mode         : boolean;
  268.    monitor_mode        : boolean;
  269.    time_fix            : string10;
  270.    curr_time           : string10;
  271.    start_time          : string10;
  272.    dial_time           : string10;
  273.    a_second            : integer;
  274.    yes_no              : string[4];
  275.    mx,my               : byte;
  276.    insert_mode         : boolean;
  277.    auto_wrap           : boolean;
  278.    cursor_hold         : saved_cursor;
  279.    curr_bscan          : integer;
  280.    curr_sscan          : integer;
  281.    keypad_mode         : boolean;
  282.    rx,ry               : byte;
  283.    lx,ly               : byte;
  284.  
  285. {$I BASIC.INC}
  286. {$I RWINDOW.INC}
  287. (****************************************************************************)
  288. (*                          COMMAND DISTRIBUTOR                             *)
  289. (****************************************************************************)
  290.    procedure
  291.       exec_command(ch : char); FORWARD;
  292.  
  293. (****************************************************************************)
  294. (*                              WAIT FOR A KEY                              *)
  295. (****************************************************************************)
  296.    procedure
  297.       wait_for_key;
  298.    begin
  299.       write(' Press ANY key to continue...');
  300.       repeat
  301.          repeat
  302.             a_key := inkey;
  303.          until a_key <> '';
  304.          if length(a_key) = 2 then begin
  305.             exec_command( a_key[2] );
  306.             a_key := '';
  307.          end;
  308.       until length(a_key) = 1;
  309.    end;
  310.  
  311. (****************************************************************************)
  312. (*                           REWRITE CONFIG FILE                            *)
  313. (****************************************************************************)
  314.    procedure
  315.       rewrite_config_file;
  316.    begin
  317.       rewrite(textfile);
  318.       writeln(textfile,'CM=',com_port);
  319.       writeln(textfile,'ST=',default_stopbits);
  320.       writeln(textfile,'DA=',default_databits);
  321.       writeln(textfile,'PA=',default_parity);
  322.       writeln(textfile,'BA=',default_baud);
  323.       writeln(textfile,'WA=',wait_increment);
  324.       writeln(textfile,'PR=',dial_pre_str);
  325.       writeln(textfile,'PO=',dial_post_str);
  326.       writeln(textfile,'MI=',modem_init_str);
  327.       writeln(textfile,'SY=',speaker_on);
  328.       writeln(textfile,'SN=',speaker_off);
  329.       writeln(textfile,'RT=',redial_time);
  330.       writeln(textfile,'FC=',forced_carrier);
  331.       writeln(textfile,'CT=',carrier_timeout);
  332.       writeln(textfile,'DP=',dial_PATH);
  333.       writeln(textfile,'XO=',XON);
  334.       writeln(textfile,'XF=',XOFF);
  335.       writeln(textfile,'VT=',emulation_mode);
  336.       writeln(textfile,'LF=',auto_LF);
  337.       writeln(textfile,'FG=',FGcolor);
  338.       writeln(textfile,'BG=',BGcolor);
  339.       writeln(textfile,'CC=',comment_ch);
  340.       writeln(textfile,'SS=',split_screen);
  341.       writeln(textfile,'MX=',max_xmodem_buffers);
  342.    end;
  343.  
  344. (****************************************************************************)
  345. (*                       SETUP SPLIT SCREEN OPERATION                       *)
  346. (****************************************************************************)
  347.    procedure
  348.       setup_split;
  349.    var
  350.       i  : integer;
  351.    begin
  352.       clrscr;
  353.       rx := 1;
  354.       ry := 1;
  355.       gotoxy(1,1);
  356.       for i:=1 to 80 do write('-');
  357.       gotoxy(37,1);
  358.       write(' Remote ');
  359.       lx := 1;
  360.       ly := 1;
  361.       gotoxy(1,18);
  362.       for i:=1 to 80 do write('-');
  363.       gotoxy(37,18);
  364.       write(' Local ');
  365.       gotoxy(1,2);
  366.    end;
  367.  
  368. {$I MUSIC.INC}
  369. {$I DIRECT.INC}
  370. {$I TM1.INC}
  371. {$I TM2.INC}
  372. {$I TM3.INC}
  373. (****************************************************************************)
  374. (*                            KEYBOARD HANDLER                              *)
  375. (****************************************************************************)
  376.    procedure
  377.       local_swrite;
  378.    begin
  379.       if a_key[1]=CR then begin
  380.          scrwrite(a_key[1]);
  381.          a_key := LF;
  382.       end;
  383.       scrwrite(a_key[1]);
  384.    end;
  385.  
  386.    procedure
  387.       keyboard;
  388.    begin
  389.       if length(a_key) = 2 then begin
  390.          exec_command(a_key[2]);
  391.          if default_chg then change_defaults;
  392.       end
  393.       else begin
  394.          store_sout_buffer(a_key[1]);
  395.          if split_screen[1]='T' then begin
  396.             window(1,19,80,24);
  397.             gotoxy(lx,ly);
  398.             local_swrite;
  399.             lx := wherex;
  400.             ly := wherey;
  401.             window(1,1,80,24);
  402.             exit;
  403.          end;
  404.          if half_duplex then
  405.             local_swrite;
  406.       end;
  407.    end;
  408.  
  409. (****************************************************************************)
  410. (*                       INITIALIZE FUNCTION KEYS                           *)
  411. (****************************************************************************)
  412.    procedure
  413.       initialize_function_keys;
  414.    var
  415.       i   : byte;
  416.    begin
  417.       for i:=1 to 40 do func_key^[i]:='';
  418.       assign(keyfile,'TMODEM.KEY');
  419.       {$I-}
  420.       reset(keyfile);
  421.       {$I+}
  422.       ok:=(ioresult = 0);
  423.       if not ok then begin
  424.          rewrite(keyfile);
  425.          for i:=1 to 40 do
  426.             writeln(keyfile,func_key^[i]);
  427.       end
  428.       else begin
  429.          i :=0;
  430.          while ( not eof(keyfile) ) and ( i < 40 ) do begin
  431.             i := succ( i );
  432.             readln(keyfile,func_key^[i]);
  433.          end;
  434.       end;
  435.       close(keyfile);
  436.    end;
  437.  
  438. (****************************************************************************)
  439. (*                             READ CONFIG FILE                             *)
  440. (****************************************************************************)
  441.    procedure
  442.       read_config_file;
  443.    var
  444.       teststr  : string[2];
  445.       dataval  : integer;
  446.    begin
  447.       assign(textfile,'TMODEM.CNF');
  448.       {$I-}
  449.       reset(textfile);
  450.       {$I+}
  451.       ok:=(ioresult = 0);
  452.       if not ok then
  453.          rewrite_config_file
  454.       else begin
  455.          while not eof(textfile) do begin
  456.             readln(textfile,textimage);
  457.             teststr := copy(textimage+'  ',1,2);
  458.             upstring(teststr);
  459.             dataval := bval(copy(textimage+'          ',4,9));
  460.             delete(textimage,1,3);
  461.             if teststr = 'ST' then default_stopbits := dataval;
  462.             if teststr = 'DA' then default_databits := dataval;
  463.             if teststr = 'PA' then default_parity := dataval;
  464.             if teststr = 'BA' then default_baud := dataval;
  465.             if teststr = 'WA' then wait_increment := dataval;
  466.             if teststr = 'PR' then dial_pre_str := textimage;
  467.             if teststr = 'MI' then modem_init_str := textimage;
  468.             if teststr = 'PO' then dial_post_str := textimage;
  469.             if teststr = 'SN' then speaker_off := textimage;
  470.             if teststr = 'SY' then speaker_on := textimage;
  471.             if teststr = 'RT' then redial_time := dataval;
  472.             if teststr = 'FC' then forced_carrier := textimage;
  473.             if teststr = 'CT' then carrier_timeout := dataval;
  474.             if teststr = 'DP' then dial_PATH := textimage;
  475.             if teststr = 'VT' then emulation_mode := textimage;
  476.             if teststr = 'LF' then auto_LF := textimage;
  477.             if teststr = 'CM' then com_port := dataval;
  478.             if teststr = 'FG' then FGcolor := dataval;
  479.             if teststr = 'BG' then BGcolor := dataval;
  480.             if teststr = 'CC' then comment_ch := textimage[1];
  481.             if teststr = 'SS' then split_screen := textimage;
  482.             if teststr = 'MX' then max_xmodem_buffers := dataval;
  483.          end;
  484.       end;
  485.       close(textfile);
  486.       a_second := round( 3.003004 * wait_increment );
  487.    end;
  488.  
  489. (****************************************************************************)
  490. (*                           MAIN  LINE  CODE                               *)
  491. (****************************************************************************)
  492. begin
  493.    dial_drive := ord(default_drive) - pred( ord('A') );
  494.    getdir(dial_drive,dial_PATH);
  495.    if dial_PATH[length(dial_PATH)] <> '\' then
  496.       dial_PATH := dial_PATH + '\';
  497.    cnf_PATH := dial_PATH;
  498.    read_config_file;
  499.    FG := FGcolor;
  500.    BG := BGcolor;
  501.    blink_state := 0;
  502.    intensity_state := 0;
  503.    set_intensity;
  504.    lowvideo;
  505.    textcolor( FG );
  506.    textbackground( BG );
  507.    window(1,1,80,25);
  508.    clrscr;
  509.    initwin;
  510.    capture_flag := false;
  511.    printer_on := false;
  512.    printer_control_off := true;
  513.    ascii_mode := false;
  514.    escape_mode := false;
  515.    monitor_mode := false;
  516.    line_drawing_chars := false;
  517.    keypad_mode := false;
  518.    auto_wrap := false;
  519.    insert_mode := false;
  520.    default_chg := false;
  521.    scroll_top := 1;
  522.    scroll_bot := 24;
  523.    scroll_last := 24;
  524.    scroll_region := false;
  525.    with cursor_hold do begin
  526.       x_coor := 1;
  527.       y_coor := 1;
  528.       bscan  := 6;
  529.       sscan  := 7;
  530.       ForeG  := FG;
  531.       BackG  := BG;
  532.    end;
  533.    curr_bscan := 6;
  534.    curr_sscan := 7;
  535.    time_fix := time;
  536.    dial_time := time_fix;
  537.  
  538.    new( sin_buffer_ptr );
  539.    new( sout_buffer_ptr );
  540.    new( func_key );
  541.    if not ( max_xmodem_buffers in [ 4..255 ] ) then
  542.       max_xmodem_buffers := 64;
  543.    getmem( xmodem_table_ptr, max_xmodem_buffers * 128 );
  544.    datasegment := DSeg;
  545.  
  546.    baud := default_baud;
  547.    stopbits := default_stopbits;
  548.    databits := default_databits;
  549.    par := default_parity;
  550.    init_com_port;
  551.  
  552.    exit_program := false;
  553.    half_duplex := false;
  554.  
  555.    dial_str := modem_init_str;
  556.    dialer;
  557.    redial_number := '';
  558.    redial_name := '';
  559.    initialize_function_keys;
  560.  
  561.    mkwin(2,2,79,22,'TMODEM, ver '+version);
  562.    writeln;
  563.    writeln(' If you use this program and like it, a contribution ($20 suggested) will');
  564.    writeln(' be appreciated.');
  565.    writeln;
  566.    writeln;
  567.    writeln('                          P & M  Software Co.');
  568.    writeln('                          9350 Country Creek #30');
  569.    writeln('                          Houston, Texas 77036');
  570.    writeln;
  571.    writeln;
  572.    writeln(' You are encouraged to copy and share this program with others, on the');
  573.    writeln(' condition that the program not be sold for profit, except by the author,');
  574.    writeln(' and that this notice is not altered, bypassed, or removed.');
  575.    writeln;
  576.    gotoxy(50,wherey);
  577.    writeln('Good Luck,');
  578.    gotoxy(50,wherey);
  579.    writeln('Paul Meiners.');
  580.    writeln;
  581.    escape_win;
  582.    gotoxy(19,23);
  583.    write('Copyright (c) 1985 by: P & M  Software Co.');
  584.    reset_win;
  585.  
  586.    write(' Do You Want Music? ');
  587.    repeat until keypressed;
  588.    read(kbd,kbd_char);
  589.    write(kbd_char);
  590.    initialize_music;
  591.    if ( emulation_mode = 'T' ) or ( upcase( kbd_char ) <> 'Y' ) then
  592.       silent_mode := true
  593.    else
  594.       silent_mode := false;
  595.    rmwin;
  596.    flush_sin_buff;
  597.    display_prompts;
  598.  
  599.    delay( wait_increment );
  600.    if split_screen[1]='T' then
  601.       setup_split;
  602.    repeat
  603.       if sin_read_ptr <> sin_store_ptr then begin
  604.          kbd_char := read_sin_buffer;
  605.          if split_screen[1]='T' then begin
  606.             window(1,2,80,17);
  607.             gotoxy(rx,ry);
  608.             scrwrite(kbd_char);
  609.             rx := wherex;
  610.             ry := wherey;
  611.             window(1,1,80,24);
  612.          end
  613.          else
  614.             scrwrite(kbd_char);
  615.       end;
  616.       a_key := inkey;
  617.       if a_key <> '' then keyboard;
  618.    until exit_program;
  619.  
  620.    port[int_enable_reg] := 0;                  { Turn off modem and reset }
  621.    port[modem_control_reg] := 0;               { vectors.                 }
  622.    port[$21] := port[$21] or turn_IRQ_off;
  623.    memw[$0000:IRQ_vector_ofs] := hold_vector_ofs;
  624.    memw[$0000:IRQ_vector_seg] := hold_vector_seg;
  625.    freemem( xmodem_table_ptr, max_xmodem_buffers * 128 );
  626.    dispose( func_key );
  627.    dispose( sout_buffer_ptr );
  628.    dispose( sin_buffer_ptr );
  629.  
  630.    if capture_flag then toggle_capture_mode;
  631.    window(1,1,80,25);
  632.    clrscr;
  633.    change_drive( cnf_PATH[1] );
  634. end.
  635.