[Back to HARDWARE SWAG index] [Back to Main SWAG index] [Original]

    {... so there I was, sitting in a bar when a known C Programmer  }
    {comes up to me and sniggers "still doing it in Pascal eh?"      }
    {"Yup" I replied, and tossed the bartender another hundred.      }
    {"Yeah well, when you're ready For a Real language, only C has   }
    {all the aces."                                                  }
    {I'm a Pascal Programmer.  I don't have to take that.  "Such as?"}
    {I hoped he'd bite and he did.                                   }
    {"Such as disk sector reading and writing For starters."         }
    {"Well I hope you're not bluffin', 'cause here's a trick that    }
    {I'll bet you ain't covered."                                    }
    {I pulled it out With a swish and laid it on the table.  "Even   }
    {provides support For >32M volumes, which the C run-time library }
    {manual Forgets to tell you it won't do."                        }
    {"Huh?  Where?"                                                  }
    {"Right here" I said.  "Just where it says...                    }

    Program AbsReadTest;

    {This Program demonstrates a C-style absread and absWrite For TP.}
    {As is, it reads the boot sector off drive A:, and optionally    }
    {Writes it out to the very last sector on drive A: (assumes 1.2Meg}
    {This Program IS dangerous, and is released to the public domain.}
    {I take no responsibility For use or misuse, deliberate or       }
    {accidental, of this Program or any Program which Uses the       }
    {techniques described herein.                                    }

    {Author: Mitch Davis 3:634/384.6 +61-3-890-2062 v1.0 28-Jun-92.  }

    Var bp:Pointer; {Will point to the buffer For the sector data}

    Function absread (drive:Char; nsects:Word; lsect:Word; buffer:Pointer):Boolean;

    {Works just like the C runtime one- including being restricted to 32M volumes!}

    {drive is a Character, nsects is the number of sectors, and lsect is the first}
    {sector.  buffer points to the buffer you'd like filled from disk.  Function  }
    {returns True if there was an error, or False if all went well.               }

    Var kludgebuff:Array [0..$1f] of Byte; {Read Ralf Brown's interrupt listing}
        kludgePtr:Pointer;                 {Int 25h - ES:[BP+1E] may change    }

    begin
      kludgePtr := @kludgebuff;
      absread := True;
      if drive < 'A' then Exit;
      if drive > 'Z' then Exit;
      Asm
        push  es
        push  bp
        push  di
        les   di, kludgePtr
        mov   al, drive      { Gets the passed parameter. }
        and   al, 1fh        { Cvt from ASCII to drive num }
        dec   al             { Adjust because A: is drive 0 }
        mov   cx, nsects     { number of sectors to read }
        mov   dx, lsect      { starting at sector.. }
        push  ds
        lds   bx, buffer      { Get the address of the buffer }
        mov   bp, di
        push  si
        int   25h            { Do the drive read. }
        pop   si             { Remove the flags int 25h leaves on stack}
        pop   si
        pop   ds
        pop   di
        pop   bp
        pop   es
        jc    @1
        mov   ah, 0          { No errors, so set Function to False }
        @1:
        mov   @result, ah
      end;
    end;

    Function absWrite
                (drive:Char; nsects:Word; lsect:Word; buffer:Pointer):Boolean;

    {Works just like the C one - including being restricted to 32M volumes!}

    {drive is a Character, nsects is the number of sectors, and lsect is the first}
    {sector.  buffer points to the buffer you'd like filled from disk.  Function  }
    {returns True if there was an error, or False if all went well.               }

    Var kludgebuff:Array [0..$1f] of Byte;
        kludgePtr:Pointer;

    begin
      kludgePtr := @kludgebuff;
      absWrite := True;
      if drive < 'A' then Exit;
      if drive > 'Z' then Exit;
      Asm
        push  es
        push  bp
        push  di
        les   di, kludgePtr
        mov   al, drive      { Gets the passed parameter. }
        and   al, 1fh        { Cvt from ASCII to drive num }
        dec   al             { Adjust because A: is drive 0 }
        mov   cx, nsects     { number of sectors to Write }
        mov   dx, lsect      { starting at sector.. }
        push  ds
        lds   bx, buffer      { Get the address of the buffer }
        mov   bp, di
        push  si
        int   26h            { Do the drive Write. }
        pop   si             { Remove the flags int 26h leaves on stack}
        pop   si
        pop   ds
        pop   di
        pop   bp
        pop   es
        jc    @1
        mov   ah, 0
        @1:
        mov   @result, ah
      end;
    end;

    Function absLread (drive:Char; nsects:Word; lsect:LongInt;
    buffer:Pointer):Boolean;

    {This Function reads sectors on disks which have the >32M style made popular}
    {by Compaq Dos 3.31, MS-Dos 4+ and DR-Dos 5+.                               }

    Var packet:Array [0..9] of Byte; {disk request packet - see Ralf Brown's ints}

    begin
      absLread := True;
      if drive < 'A' then Exit;
      if drive > 'Z' then Exit;
      Asm
        mov   ax, Word ptr lsect     {Get the LSB of the start sector}
        mov   Word ptr packet[0], ax {Store it in the packet         }
        mov   ax, Word ptr lsect + 2 {Get the MSB of the start sector}
        mov   Word ptr packet[2], ax {Store this one too.            }
        mov   ax, nsects             {How many sectors to read       }
        mov   Word ptr packet[4], ax
        {Insert the Pointer to the data buffer into the packet}
        push  bp ; push ds
        lds   dx, buffer      { Get the address of the buffer }
        mov   Word ptr packet[6], dx
        mov   dx, ds
        mov   Word ptr packet[8], dx
        mov   al, drive      { Gets the passed parameter. }
        and   al, 1fh        { Cvt from ASCII to drive num }
        dec   al             { Adjust because A: is drive 0 }
        int   25h            { Do the drive read. }
        pop   si             { Remove the flags int 25h leaves on stack}
        pop   ds
        pop   bp
        jc    @1
        mov   ah, 0
        @1:
        mov   @result, ah
      end;
    end;

    Function absLWrite (drive:Char; nsects:Word; lsect:LongInt;
    buffer:Pointer):Boolean;

    {This Function Writes sectors on disks which have the >32M style made popular}
    {by Compaq Dos 3.31, MS-Dos 4+ and DR-Dos 5+.                                }

    Var packet:Array [0..9] of Byte;

    begin
      absLWrite := True;
      if drive < 'A' then Exit;
      if drive > 'Z' then Exit;
      Asm
        mov   ax, Word ptr lsect
        mov   Word ptr packet[0], ax
        mov   ax, Word ptr lsect + 2
        mov   Word ptr packet[2], ax
        mov   ax, nsects
        mov   Word ptr packet[4], ax
        push  bp ; push ds
        lds   dx, buffer
        mov   Word ptr packet[6], dx
        mov   dx, ds
        mov   Word ptr packet[8], dx
        mov   al, drive      { Gets the passed parameter. }
        and   al, 1fh        { Cvt from ASCII to drive num }
        dec   al             { Adjust because A: is drive 0 }
        int   26h            { Do the drive Write. }
        pop   si             { Remove the flags int 26h leaves on stack}
        pop   ds
        pop   bp
        jc    @1
        mov   ah, 0
        @1:
        mov   @result, ah
      end;
    end;

    Function LongNeeded (drive:Char):Boolean;

    {This Function returns True or False depending on whether the long versions}
    {of absread/absWrite needed to be invoked; that is, it's a drive Formatted }
    {in the Dos 4+ >32M style.                                                 }
    {I strongly suggest you see Ralf Brown's interrupt listing For int21h subfs}
    {440d and 53 - they'll tell you all you know to understand the guts of this}
    {Function.                                                                 }

    Label Escape;

    Var drivestats:Array [0..31] of Byte;

    begin
      LongNeeded := False;
      if drive < 'A' then Exit;
      if drive > 'Z' then Exit;
      Asm
        push ds
        mov  dx, ss
        mov  ds, dx
        lea  dx, drivestats
        mov  bl, drive      { Gets the passed parameter. }
        and  bl, 1fh        { Cvt from ASCII to drive num }
        mov  ax, 440Dh
        mov  cx, 0860h
        int  21h
        jc   Escape
        mov  ax, Word ptr drivestats[0Fh]
        or   ax, ax
        jnz Escape
        mov  @Result, 1
      Escape:
        pop  ds
      end;
    end;

    begin
      getmem (bp,2048);
      Writeln (LongNeeded ('A'));
      Writeln (LongNeeded ('C'));
      Writeln (absread  ('A',1,0,bp));
    (*  Writeln (absWrite ('A',1,2399,bp)); *) {remove the comments at your own}
                                               {risk!!!}
      freemem (bp,2048);
    end.

    {So I bought him a drink.  The poor guy looked like he needed one....}

[Back to HARDWARE SWAG index] [Back to Main SWAG index] [Original]