'===========================================================================
' Subject: DISPLAY CONTENTS OF HARDDISK       Date: 12-19-96 (19:06)       
'  Author: Rick Elbers                        Code: QB, QBasic, PDS        
'  Origin: t030611@tip.nl                   Packet: DOS.ABC
'===========================================================================
DECLARE SUB sectorread (datas%(), sector&)
DECLARE SUB demo ()
DECLARE FUNCTION int2str$ (sword%)
'---------------------------------------------------------------------------
'XS2DISK: A program that displays the contents of your harddisk( all of it)
'Necessary requirement: DOS 4+( since there is made use of longsectors!)
'Rick Elbers december 1996
'---------------------------------------------------------------------------
CLS

'The program uses the dos 4+ format of function INT 25( read absolute disksectors)
'since i thought everybody does have a hard disk bigger then 32 MB by now.....
'There is some heavy math involved in the translation to unsigned integers and
'unsigned longs necessary for INT 25. Also there is some heavy cosmetica
'necessary to present the disksectors according to there meaning. Most of the
'math and cosmetics are however found in the demo part.
'But the most meaningful part of this contribution seems to me the function
'sectorread. The most important part of the sectorread function is the
'parameter block that is passed to the INT 25. Once you understand that you
'got it all...,well... almost...
'If you want to do something with the combination of FAT/DIRECTORY then you
'might want to add a very simple text file to your ROOTDIRECTORY. After that
'you can calculate the sector offset of the file and read him directly. That's
'quite a lot of fun, really...

'Good luck.
'-----------------------------------------------------------------------------
'Rick

demo

SUB demo
'Define the databuffer in the demo
'because we want to pass the array
'-----------------------------------
DIM datas%(&H105)
'----------------------------
'go read the 0 (boot)sector
'----------------------------
sector& = 0

'go read out the information
'----------------------------
offset% = VARPTR(datas%(0)) + &HA
'-------------------------------------------------------------------------
'The cosmetics sector: how to print things.."
'The first line will always contain: sectornr, area
'Updated will only be sectornr and sometimes the areaname
''1,15 >sectornr   1,38 > area indicator
'The second line will always contain the start line
'-------------------------------------------------------------------------
CLS
LOCATE 1, 1: PRINT "READ SECTOR: ";
LOCATE 1, 30: PRINT " AREA: ";
LOCATE 2, 1: PRINT STRING$(80, "_")
'-------------------------------------------------------------------------
'line 20 will contain the closing line which will be contant
'Line 24 will contain the prompt information which will be contant
'The lines 21,22,23 will contain additional information and
'will only sometimes be updated.
LOCATE 19, 1: PRINT STRING$(80, "_")
VIEW PRINT 24 TO 25: LOCATE 24, 1: COLOR 17, 0:
PRINT "<F5>SECTOR,<F6>CLUSTER,<ESC>END,<.>NEXT SECTOR"; : COLOR 7, 0: VIEW PRINT
'------------------------------------------------------------------------
'Let us run the program until escape
'-------------------------------------
DO
  i$ = ""                               'no keypress yet
'------------------------------------------------------------------------
'AREA DEPENDENT COSMETICS:
'--------------------------

IF (sector& AND &H7FFFFFFF) > total& OR sector& < 0 THEN sector& = 0
SELECT CASE sector& AND &H7FFFFFFF
CASE 0
sectorread datas%(), sector&
DEF SEG = VARSEG(datas%(0))
'-------------
'0) BOOTSECTOR
'--------------
'First the header
VIEW PRINT
sec$ = HEX$(sector&): LOCATE 1, 15: COLOR O, 7: PRINT STRING$(8 - LEN(sec$), "0") + sec$: COLOR 7, 0:
LOCATE 1, 38: COLOR 0, 7: PRINT "(MASTER)BOOTSECTOR OF C:\": COLOR 7, 0:
VIEW PRINT 20 TO 23: CLS 2: VIEW PRINT 3 TO 18: CLS 2: LOCATE 3, 1:
'calculate relavant details of bootrecord.
  secpclus% = PEEK(&HD + &HA)
  nrfat% = PEEK(&H10 + &HA):
  direntrancenr% = PEEK(&H12 + &HA) * 256& OR PEEK(&H11 + &HA)
  bytepsec% = PEEK(&HC + &HA) * 256& OR PEEK(&HB + &HA)
  fatsec% = PEEK(&H16 + &HA) + PEEK(&H17 + &HA) * 256
  ressec% = PEEK(&HF + &HA) * 256& + PEEK(&HE + &HA)
  help% = PEEK(&H13 + &HA) + PEEK(&H14 + &HA) * 256
  IF help% = 0 THEN
  total& = 256& * PEEK(&H21 + &HA) + PEEK(&H20 + &HA) + 65535 * (PEEK(&H22 + &HA) + PEEK(&H23 + &HA) * 256)
  ELSE
    total& = help%
  END IF
  hiddensec% = PEEK(&H1C + &HA) + PEEK(&H1D + &HA) * 256
  startdir% = nrfat% * fatsec% + ressec%
  'we have to call this ones again
  startdata% = 1 + startdir% + (direntrancenr% * 32 / bytepsec%)


  'Oke let us print the relevant details...
COLOR 7, 0: PRINT "BYTES per sector                  :"; : COLOR 0, 13: PRINT bytepsec%
COLOR 7, 0: PRINT "SECTORs per cluster               :"; : COLOR 0, 2: PRINT secpclus%
COLOR 7, 0: PRINT "NUMBER of FATs                    :"; : COLOR 0, 3: PRINT nrfat%
COLOR 7, 0: PRINT "SECTORS per FAT                   :"; : COLOR 0, 4: PRINT fatsec%
COLOR 7, 0: PRINT "Number of reserved sectors        :"; : COLOR 0, 5: PRINT ressec%
COLOR 7, 0: PRINT "Number of hidden sectors          :"; : COLOR 0, 6: PRINT hiddensec%
COLOR 7, 0: PRINT "TOTAL NUMBER OF SECTORS(dec)      :"; : COLOR 0, 15: PRINT total&
COLOR 7, 0: PRINT "START OF DOSDIRECTORY at sector   :"; : COLOR 0, 11: PRINT startdir%; "("; HEX$(startdir%); ")"
COLOR 7, 0: PRINT "START OF DATA(FILE/SUB directory) :"; : COLOR 0, 2: PRINT startdata% - 1; "("; HEX$(startdata% - 1); ")"
COLOR 7, 0: PRINT "TOTAL SPACE( BYTES) ON DISK       :"; : COLOR 0, 11: PRINT total& * bytepsec%
COLOR 7, 0: PRINT "TOTAL CLUSTERS ON DISK(hex)       :"; : COLOR 0, 10: PRINT " "; HEX$(total& \ secpclus%)
COLOR 7, 0: PRINT "BYTES PER CLUSTER                 :"; : COLOR 0, 12: PRINT secpclus% * bytepsec%

DO UNTIL i$ <> "": i$ = INKEY$: LOOP
IF MID$(i$, 2, 1) = CHR$(&H40) THEN     'f6 pressed
VIEW PRINT 24 TO 25: LOCATE 24, 50
COLOR 29, 0: INPUT "NEXT CLUSTER(hex) "; a$
COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);
sector& = (VAL("&h" + a$) AND &HFFFF&) * secpclus%

ELSEIF MID$(i$, 2, 1) = CHR$(&H3F) THEN 'f5 pressed
VIEW PRINT 24 TO 25: LOCATE 24, 50
COLOR 29, 0: INPUT "NEXT SECTOR(dec) "; sector&
COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);

ELSEIF i$ = CHR$(27) THEN
EXIT SUB
ELSE
  sector& = 1
END IF

CASE IS < startdir%
'1)FAT AREA:
'-----------
'first the header:
VIEW PRINT
LOCATE 1, 38: COLOR 0, 7: PRINT "FATAREA                    ": COLOR 7, 0:
'Second the footer
VIEW PRINT 20 TO 23: CLS 2
LOCATE 20, 1: PRINT "FAT 1 until sector "; : COLOR 0, 7: PRINT fatsec%;
COLOR 7, 0: PRINT " FAT 2 until sector "; : COLOR 0, 7: PRINT startdir%
LOCATE 21, 1: PRINT "CODED LIKE:"; : COLOR 0, 7: PRINT "'0000'=FREE "; "'FFF8-FFFF'=END OF FAIL CHAIN "; "'FFF1--FFF7'=BAD SECTORS "; "OTHER=FILE CHAIN NEXT ENTRY ";
COLOR 7, 0:
'Third lets roll the program
'----------------------------
DO
VIEW PRINT
sec$ = HEX$(sector&): LOCATE 1, 15: COLOR O, 7: PRINT STRING$(8 - LEN(sec$), "0") + sec$: COLOR 7, 0:
i$ = ""
sectorread datas%(), sector&
DEF SEG = VARSEG(datas%(0))
'-------------------------
'Let us display the data:
'-------------------------

VIEW PRINT 3 TO 18: CLS 2: LOCATE 3, 1:
  FOR i% = offset% TO offset% + &H200 - 1
    a$ = HEX$(PEEK(i%))
    PRINT a$ + STRING$(2 - LEN(a$), "0");
    IF i% MOD 2 = 1 THEN PRINT " ";
    IF i% - offset% MOD 32 = 31 THEN PRINT
  NEXT
'user input a key or <f5> or esc ?
'---------------------------------
  DO UNTIL i$ <> "": i$ = INKEY$: LOOP
  IF LEN(i$) = 2 THEN i$ = MID$(i$, 2, 1)
  sector& = sector& + 1

LOOP WHILE (sector& AND &HFFFF) < startdir% AND i$ <> CHR$(&H3F) AND i$ <> CHR$(&H40) AND i$ <> CHR$(27)'non- function key pressed
SELECT CASE i$
CASE CHR$(&H40) 'f6 pressed
  VIEW PRINT 24 TO 25: LOCATE 24, 50
  COLOR 29, 0: INPUT "NEXT CLUSTER(hex) "; a$
  COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);
  sector& = (VAL("&h" + a$) AND &HFFFF&) * secpclus%
CASE CHR$(&H3F) 'f5 pressed
  VIEW PRINT 24 TO 25: LOCATE 24, 50
  COLOR 29, 0: INPUT "NEXT SECTOR(dec) "; sector&
  COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);
  CASE CHR$(27)   'esc pressed
  EXIT SUB
END SELECT

CASE startdir% TO startdata% - 2
'2)DIRECTORY
'-----------
'First the header:
'-------------------
VIEW PRINT
sec$ = HEX$(sector&): LOCATE 1, 15: COLOR O, 7: PRINT STRING$(8 - LEN(sec$), "0") + sec$: COLOR 7, 0:
LOCATE 1, 38: COLOR 0, 7: PRINT "DOS DIRECTORY AREA       ": COLOR 7, 0:
'Second print footer
'------------------
VIEW PRINT 20 TO 23: CLS 2: LOCATE 20, 1:
PRINT " ^   ^   ^  ^                    T^^^D^^^S^^^FS^^^^^^"
PRINT "filenam.ext;atr;                timedatestartfilesize";
PRINT "legenda: T=filetime(W),D=filedate(W),S = startsector(W),FS = filesize(DW) ";
COLOR 0, 14: PRINT "STARTSECTOR FILE:= (STARTCLUSTER-2)*"; secpclus%; " + "; HEX$(startdata% - 1); : COLOR 7, 0:
'Third lets roll the program
'----------------------------
DO
VIEW PRINT
sec$ = HEX$(sector&): LOCATE 1, 15: COLOR O, 7: PRINT STRING$(8 - LEN(sec$), "0") + sec$: COLOR 7, 0:
i$ = ""
sectorread datas%(), sector&
DEF SEG = VARSEG(datas%(0))
'-------------------------
'Let us display the data:
'-------------------------
VIEW PRINT 3 TO 18: CLS 2: LOCATE 3, 1:
FOR i% = offset% TO offset% + &H200 - 1
  a% = PEEK(i%): p% = (i% - offset%) MOD 32
  IF p% < 11 THEN PRINT CHR$(a%);  ELSE a$ = HEX$(a%): PRINT STRING$(2 - LEN(a$), "0") + a$;
  IF p% = 31 AND i% <> offset% + &H200 - 1 THEN PRINT
NEXT
'user input a key or <f5> or esc ?
'---------------------------------
  DO UNTIL i$ <> "": i$ = INKEY$: LOOP
  IF LEN(i$) = 2 THEN i$ = MID$(i$, 2, 1)
  sector& = sector& + 1
LOOP WHILE (sector& AND &HFFFF) < startdata% - 1 AND i$ <> CHR$(&H3F) AND i$ <> CHR$(&H40) AND i$ <> CHR$(17)'key pressed

IF i$ = CHR$(&H40) THEN     'f6 pressed
VIEW PRINT 24 TO 25: LOCATE 24, 50
COLOR 29, 0: INPUT "NEXT CLUSTER(hex) "; a$
COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);
sector& = (VAL("&h" + a$) AND &HFFFF&) * secpclus%

ELSEIF i$ = CHR$(&H3F) THEN 'f5 pressed
VIEW PRINT 24 TO 25: LOCATE 24, 50
COLOR 29, 0: INPUT "NEXT SECTOR(dec) "; sector&
COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);

ELSEIF i$ = CHR$(27) THEN
EXIT SUB

END IF


CASE ELSE                 'data
'3)DATA AREA:
'-----------
'First the header
'-----------------
VIEW PRINT
LOCATE 1, 38: COLOR 0, 7: PRINT "DATAAREA                   ": COLOR 7, 0:
'Second the footer
'------------------
VIEW PRINT 20 TO 23: CLS 2
'Third lets roll the program
'----------------------------

DO
i$ = ""
VIEW PRINT
clushelp& = (sector& \ secpclus%): clushelp& = clushelp& AND &HFFFF&
clus% = clushelp& AND &H7FFF: clus% = clus% OR -(clushelp& AND &H8000)
clus$ = HEX$(clus%)

LOCATE 20, 1: PRINT "CLUSTER NUMBER DISPLAYED: "; : COLOR 0, 7: PRINT STRING$(4 - LEN(clus$), "0") + clus$: COLOR 7, 0
LOCATE 21, 1: PRINT " 33 <   ASCII  < 126      DISPLAYED IN:"; : COLOR 0, 7: PRINT " CHARACTERS+SPACE"; : COLOR 7, 0:
LOCATE 22, 1: PRINT "ASCII < 33 OR ASCII > 126 DISPLAYED AS:"; : COLOR 0, 7: PRINT " HEXADECIMAL BYTE": COLOR 7, 0:
sec$ = HEX$(sector&): LOCATE 1, 15: COLOR O, 7: PRINT STRING$(8 - LEN(sec$), "0") + sec$: COLOR 7, 0:
sectorread datas%(), sector&
DEF SEG = VARSEG(datas%(0))
'-------------------------
'Let us display the data:
'-------------------------
VIEW PRINT 3 TO 18: CLS 2: LOCATE 3, 1:
FOR i% = offset% TO offset% + &H200 - 1
    a% = PEEK(i%)
    IF a% < 33 OR a% > 126 THEN PRINT STRING$(2 - LEN(HEX$(a%)), "0") + HEX$(a%);  ELSE PRINT CHR$(a%) + " ";
    IF (i% - offset%) MOD 32 = 31 AND i% <> offset% + &H200 - 1 THEN PRINT
  NEXT
'user input a key or <f5> or esc ?
'---------------------------------
  DO UNTIL i$ <> "": i$ = INKEY$: LOOP
  IF LEN(i$) = 2 THEN i$ = MID$(i$, 2, 1)
  sector& = sector& + 1


LOOP WHILE i$ <> CHR$(&H3F) AND i$ <> CHR$(&H40) AND i$ <> CHR$(27)'non- function key pressed


IF i$ = CHR$(&H40) THEN     'f6 pressed
VIEW PRINT 24 TO 25: LOCATE 24, 50
COLOR 29, 0: INPUT "NEXT CLUSTER(hex) "; a$
COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);
sector& = (VAL("&h" + a$) AND &HFFFF&) * secpclus%

ELSEIF i$ = CHR$(&H3F) THEN 'f5 pressed
VIEW PRINT 24 TO 25: LOCATE 24, 50
COLOR 29, 0: INPUT "NEXT SECTOR(dec) "; sector&
COLOR 7, 0: LOCATE 24, 50: PRINT SPACE$(29);

ELSEIF i$ = CHR$(27) THEN
EXIT SUB
END IF

END SELECT

LOOP WHILE i$ <> CHR$(27)



END SUB

FUNCTION int2str$ (sword%)
'This function is translating SWORD Integers into a string. Its only use
'is when you still use asm$ for assembler functions( like i do). In that
'case you can make your integer values usable ..
'THis function simply translates the hexa bytes
'into stringbytes as is.
'----------------------------------------------------
DEF SEG = VARSEG(sword%)
ptr% = VARPTR(sword%)
int2str$ = CHR$(PEEK(ptr%)) + CHR$(PEEK(ptr% + 1))
DEF SEG

END FUNCTION

SUB sectorread (datas%(), sector&)
'------------------------------------------------------------------------
'datas%(&h105)
'0:DW      = sector2start
'4:W       = nrsector2read
'6:DW      = offset:segment van buffer
'0A:100*W  = sectorbuffer
'------------------------------------------------------------------------
ds% = VARSEG(datas%(0)): bx% = VARPTR(datas%(0))
ds$ = int2str$(ds%): bx$ = int2str$(bx%)

helplowbyte& = sector& AND &HFFFF&
lowbyte% = helplowbyte& AND &H7FFF
datas%(0) = lowbyte% OR -(helplowbyte& AND &H8000):

helphighbyte& = ((sector& AND &HFFFF0000) \ 65535) AND &HFFFF&
highbyte% = helphighbyte& AND &H7FFF
datas%(1) = highbyte% OR -(helphighbyte& AND &H8000)

datas%(2) = &H1: datas%(4) = ds%: datas%(3) = bx% + 10
'------------------------------------------------------------------------
asm$ = ""
asm$ = asm$ + CHR$(&H50)                          'PUSH AX
asm$ = asm$ + CHR$(&H53)                          'PUSH BX
asm$ = asm$ + CHR$(&H51)                          'PUSH CX
asm$ = asm$ + CHR$(&H1E)                          'PUSH DS

asm$ = asm$ + CHR$(&HB8) + ds$                    'mov ax,ds$
asm$ = asm$ + CHR$(&H8E) + CHR$(&HD8)             'mov ds,ax
asm$ = asm$ + CHR$(&HB8) + CHR$(&H2) + CHR$(&H0)  'MOV  AX,2
asm$ = asm$ + CHR$(&HBB) + bx$                    'MOV  BX,BX$
asm$ = asm$ + CHR$(&HB9) + CHR$(&HFF) + CHR$(&HFF)'MOV  CX,-1
asm$ = asm$ + CHR$(&HCD) + CHR$(&H25)             'INT 25
asm$ = asm$ + CHR$(&H83) + CHR$(&HC4) + CHR$(&H2) 'ADD SP,2

asm$ = asm$ + CHR$(&H1F)                          'POP  DS
asm$ = asm$ + CHR$(&H59)                          'POP  CX
asm$ = asm$ + CHR$(&H5B)                          'POP  BX
asm$ = asm$ + CHR$(&H58)                          'POP  AX
'say, we are done?
asm$ = asm$ + CHR$(&HCB)                          'RETF

DEF SEG = VARSEG(asm$): offcode% = SADD(asm$)
CALL absolute(offcode%)
END SUB
