(* DIR.PAS -- access the directory ** Copyright (c) 1995,1996 Jochen Metzinger ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2, or (at your option) ** any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *) UNIT dir; INTERFACE USES global, geos, errors, d64; VAR DiskName, DiskID, DiskOS: STRING; (* Name, ID and OS version of disk *) IsGeosDisk: BOOLEAN; (* is it a GEOS formatted disk? *) FreeBlocks: WORD; (* free blocks on disk *) PROCEDURE InitDir; (* Initialise directory reading *) PROCEDURE RewindDir; (* set dir position to 1st entry *) FUNCTION ReadDir(VAR dr: DirRec; VAR page: WORD): BOOLEAN; (* get next dir entryand his page location *) FUNCTION DirFileName(VAR dr: DirRec): STRING; (* extract file name from dr *) IMPLEMENTATION VAR dir_block: BLOCK; dir_cnt, dir_pos: INTEGER; dir_trk, dir_sec: BYTE; brd_trk, brd_sec: BYTE; PROCEDURE InitDir; VAR i: INTEGER; BEGIN d64_read($12, $00, dir_block); err_stop; dir_trk := dir_block[0]; dir_sec := dir_block[1]; FreeBlocks := 0; FOR i := 1 TO 35 DO Inc(FreeBlocks, dir_block[4*i]); IF d64_double_sided THEN FOR i := 221 TO 255 DO Inc(FreeBlocks, dir_block[i]); DiskOS := GetString(dir_block[165],2); DiskName := TermString(GetString(dir_block[144],18),#$A0); DiskID := GetString(dir_block[162],2); IsGeosDisk := (GetString(dir_block[173], 11) = 'GEOS format'); IF IsGeosDisk THEN BEGIN brd_trk := dir_block[171]; brd_sec := dir_block[172]; END ELSE BEGIN brd_trk := 0; brd_sec := 0; END; (* else *) END; (* InitDir *) PROCEDURE RewindDir; BEGIN IF brd_trk > 0 THEN BEGIN d64_read(brd_trk, brd_sec, dir_block); err_stop; dir_block[0] := dir_trk; dir_block[1] := dir_sec; dir_cnt := 0; dir_pos := 0; END ELSE BEGIN d64_read(dir_trk, dir_sec, dir_block); err_stop; dir_cnt := 1; dir_pos := 0; END; (* else *) END; (* RewindDir *) FUNCTION NextBlock: BOOLEAN; BEGIN IF dir_block[0] = 0 THEN NextBlock := FALSE ELSE BEGIN d64_read(dir_block[0], dir_block[1], dir_block); err_stop; NextBlock := TRUE; END; END; (* NextBlock *) FUNCTION ReadDir(VAR dr: DirRec; VAR page: WORD): BOOLEAN; BEGIN IF dir_pos < 0 THEN ReadDir := FALSE ELSE BEGIN ReadDir := TRUE; Move(dir_block[dir_pos+2],dr,SizeOf(dr)); page := dir_cnt; Inc(dir_pos, 32); IF dir_pos > $FF THEN IF NOT NextBlock THEN dir_pos := -1 ELSE BEGIN INC(dir_cnt); IF dir_cnt > 2*(19+1) THEN FATAL('directory too big'); dir_pos := 0; END; (* else *) END; (* else *) END; (* ReadDir *) FUNCTION DirFileName(VAR dr: DirRec): STRING; VAR s: STRING; i: INTEGER; BEGIN (* $A0 end of string mark *) s := TermString(dr.name, #$A0); (* clean char > 192 *) FOR i := 1 TO Length(s) DO IF s[i] = #255 THEN s[i] := #126 ELSE IF s[i] >= #224 THEN s[i] := CHR(ORD(s[i])-64) ELSE IF s[i] >= #192 THEN s[i] := CHR(ORD(s[i])-96); DirFileName := s; END; (* DirFileName *) BEGIN DiskName := ''; DiskID := ''; DiskOS := ''; IsGeosDisk := FALSE; FreeBlocks := 0; dir_cnt := -1; dir_pos := -1; dir_trk := $12; dir_sec := $01; brd_trk := $00; brd_sec := $00; END. (* dir *)