• TCP<->Fossil for plain DOS

    From Alexander Grotewohl@1:218/530 to All on Tue Mar 9 01:55:56 2021
    Here is some experimental code I was working on. I kind of lost interest after it got past the "proof of concept" phase. Perhaps someone else wants to finish it and run a single node internet bbs on a plain DOS machine ;)

    sockets unit in the next message..


    {$M $4000,0,0}
    {x$DEFINE DEBUG}

    uses
    dos, crt, sockets;

    var
    h: word; { our socket handle }

    IntTable : array[0..255] of Pointer absolute 0:0;
    old14: pointer;

    buf: array[1..1024] of char;
    bcnt: word;
    bmax: word;

    {For debugging only}
    Procedure ScreenStr(s:string;x,y:integer;attr:byte);
    var
    addr:word;
    i:integer;
    begin
    addr:=(y-1)*160+(x-1)*2;
    for i:=0 to length(s)-1 do begin
    Mem[$b800:addr+i*2]:=ord(s[i+1]);
    Mem[$b800:addr+(i*2)+1]:=attr;
    end;
    end;

    type str10 = string[10];

    Function NumStr(n,len:integer):str10;
    var
    addr:word;
    i:integer;
    s:str10;
    begin
    s:='';
    for i:=len downto 1 do begin
    s:=chr(n mod 10+ord('0'))+s;
    n:=n div 10;
    end;
    NumStr:=s;
    end;


    const
    funcstat : array[0..15] of integer = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
    hex : string[16] = '0123456789ABCDEF';

    Procedure DebugOut(func:word;active:boolean);
    var i:integer;
    begin
    for i:=0 to 15 do
    if active and (i=func) then begin
    inc(funcstat[i]);
    if funcstat[i]>99 then funcstat[i]:=0;
    ScreenStr(hex[i+1]+':'+Numstr(funcstat[i],2),i*5+1,1,15);
    end
    else
    ScreenStr(hex[i+1]+':'+Numstr(funcstat[i],2),i*5+1,1,7);
    {ScreenStr('In:'+Numstr(InCount,2)+' Out:'+NumStr(OutCount,2)+
    ' Chk:'+Numstr(CheckInput,2)+' Stat:'+Numstr(LastStatus,2),1,2,7);} end;

    function do_status: word;
    var
    tcp_state: byte;
    rec: psession_info_rec;
    t: word;
    icnt, ocnt: word;
    begin
    tcp_status(h, tcp_state, icnt, ocnt, rec);
    { default }
    t:=$08;
    if (tcp_state=4) then
    t:=t or $80;
    if (icnt<>0) then
    t:=t or $0100;
    { room avail }
    t:=t or $2000;
    { buffer empty }
    t:=t or $4000;
    do_status:=t;
    end;

    procedure tcp14(flags, cs, ip, ax, bx, cx, dx, si, di, ds, es, bp: word); inter upt;
    var
    ch: char;
    cnt: word;
    icnt, ocnt: word;
    begin
    {$IFDEF DEBUG}
    DebugOut(hi(ax),TRUE);
    {$ENDIF}
    driver_doio;
    case hi(ax) of
    $00: { set baud rate }
    begin
    { we ignore the info they send because
    we do not use it }
    { gotta send status tho}
    ax:=do_status;
    { clear a buffer we keep? }
    bcnt:=0;
    bmax:=0;
    end;
    $01: { transmit wait }
    begin
    inc(bcnt);
    buf[bcnt]:=char(lo(ax));
    if (bcnt=sizeof(buf)) then
    begin
    tcp_put(h, @buf[1], bcnt, $FFFF, cnt);
    bcnt:=0;
    end;
    ax:=do_status;
    { in:
    al - character
    dx - port
    out:
    ax - status bits }
    end;
    $02: { receive wait }
    begin
    if (bcnt<>0) then
    begin
    tcp_put(h, @buf[1], bcnt, $FFFF, cnt);
    bcnt:=0;
    end;
    tcp_get(h, @ch, 1, $FFFF, cnt);
    if (cnt<>0) then
    ax:=byte(ch);
    { in:
    dx - port
    out:
    ah = $00 - blah
    al - character }
    end;
    $03: { status request }
    begin
    ax:=do_status;
    if (bcnt<>0) then
    inc(bmax);
    if (bmax > 5) then
    begin
    tcp_put(h, @buf[1], bcnt, $FFFF, cnt);
    bcnt:=0;
    bmax:=0;
    end;
    { in:
    dx - port
    out:
    ax - status bits }
    end;
    $04: { init driver }
    begin
    { in dx = port # }
    ax:=$1954; { success message }
    bx:=$100F; { duno about 10.. max func: $0C }
    end;
    $05: { deinit driver }
    begin
    { kill socket? }
    end;
    $06: { raise/lower dtr }
    begin
    { hang up! }
    if (lo(ax)=$00) then
    begin
    tcp_close(h);
    ax:=$00;
    end else
    ax:=$01;
    end;
    $07: { system timer params }
    begin
    { ignoring... }
    end;
    $08: { flush output buffer }
    begin
    if (bcnt<>0) then
    begin
    tcp_put(h, @buf[1], bcnt, $FFFF, cnt);
    bcnt:=0;
    end;
    { in dx = port # }
    end;
    $09: { purge output buffer }
    begin
    { in dx = port # }
    end;
    $0A: { purge input buffer }
    begin
    { in dx = port # }
    end;
    $0B: { transmit no wait }
    begin
    inc(bcnt);
    buf[bcnt]:=char(lo(ax));
    if (bcnt=sizeof(buf)) then
    begin
    tcp_put(h, @buf[1], bcnt, $FFFF, cnt);
    bcnt:=0;
    end;
    {ax:=do_status;}
    ax:=1;
    { in:
    al - character
    dx - port
    out:
    ax - status bits }

    { in:
    al - character
    dx - port
    out:
    ax = 1 - sent
    ax = 0 - not sent }
    end;
    $0C:
    begin { peek ahead }
    { in:
    dx - port
    out:
    ah = $00 - blah
    al - character
    ax = $FFFF- no character avail }
    end;
    $0D: { peek ahead keyboard }
    begin
    { out:
    ax - keyboard character
    ax = $FFFF- no character avail }
    end;
    $0E: { read keyboard wait }
    begin
    { out:
    ax - keyboard character }
    end;
    $0F: { enable/disable flow control }
    begin
    { ignoring.. }
    end;
    end;
    {$IFDEF DEBUG}
    DebugOut(hi(ax),FALSE);
    {$ENDIF}
    end;

    var
    done: boolean;
    ch: char;

    rec: pdriver_info_rec;
    dh: byte;
    icnt, ocnt: word;

    rec2: psession_info_rec;
    dead: boolean;

    exit: boolean;

    begin
    clrscr;
    exit:=false;

    done:=false;
    dead:=true;

    bcnt:=0;
    bmax:=0;

    if (not driver_info(rec)) then
    begin
    writeln('Trumpet driver not loaded!');
    halt(1);
    end;

    repeat
    if (tcp_listen(h, 23)<>0) then
    begin
    writeln('Failed to connect! Waiting 5 seconds...');
    {halt(1);}
    delay(5000);
    continue;
    end;

    clrscr;
    writeln('TcpFos Waiting for call on port 23... Ctrl-Q to Exit');

    repeat
    driver_doio;
    tcp_status(h, dh, icnt, ocnt, rec2);
    if (dead=false) and (dh<>4) then
    done:=true;
    if (dh=4) then
    begin
    if (dead=true) then
    dead:=false;
    Old14:=IntTable[$14];
    IntTable[$14]:=@tcp14;
    SwapVectors;
    exec(GetEnv('COMSPEC'),'/C c:\sbbs\node1\sbbs.bat qc38400');
    if (doserror<>0) then
    writeln('DOS error #: ', doserror);
    SwapVectors;
    IntTable[$14]:=Old14;
    done:=true;
    end else
    if (keypressed) then
    begin
    ch:=readkey;
    case ch of
    #0:
    begin
    ch:=readkey;
    case ch of
    #45: ;
    end;
    end;
    #17:
    begin
    done:=true;
    exit:=true;
    end;
    end;
    end else
    delay(1);
    until done;
    tcp_close(h);
    dead:=true;
    until exit;
    end.

    --- Mystic BBS v1.12 A46 2020/08/26 (Windows/32)
    * Origin: --[!dreamland BBS bbs.dreamlandbbs.org (1:218/530)