{... 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....}