Date : Thu, 23 Jul 1992 17:59:07 GMT
From : agate!spool.mu.edu!sdd.hp.com!caen!hellgate.utah.edu!cc.usu.edu!ivie@ucbvax.Berkeley.EDU (CP/M lives!)
Subject: PX-8 ROM generator 3/3: PXFS.PAS
{****************************************************************************
*
* This file implements just enough of a CP/M compatible file-system to
* create files in a disk image of a ROM. In particular, it supports only
* the following operations:
*
* - Make File
* - Write Sequential
* - Close File
*
* These routines assume that they can call:
*
* - ReadRom( Block_Number : Integer, Var Buffer );
* - WriteRom( Block_Number : Integer, Buffer );
*
* They also assume that Buffer_Type is predefined as a buffer that can be
* written.
*
***************************************************************************}
Type
FCB_Name = Array[ 0..10 ] of Char; { File name and extension }
Allocation_Map = Array[ 0..15 ] of Byte;{ Disk allocation map }
Memory_FCB = Record
DRV : Byte; { Drive number; high bit writes a deleted FCB
when closed. }
NAME : FCB_Name; { File name and extension }
EX : Byte; { Extent number }
FIX : Byte; { Position of this FCB on disk; first FCB is #0 }
CR : Byte; { Current record position; high nybble
index into DM, low nybble = record in that one }
NR : Byte; { Number of records owned by this FCB }
DM : Allocation_Map; { Disk allocation map }
End;
Disk_FCB = Record
ET : Byte; { Entry type: $E5 = deleted file }
NAME : FCB_Name; { File name and extension }
EX : Byte; { Extent number }
Reserved1,
Reserved2 : Byte; { Reserved; not used }
NR : Byte; { Number of records owned by this FCB }
DM : Allocation_Map; { Disk allocation map }
End;
Const
Vector_Valid : Boolean = False; { If true, Vector contains a valid
representation of the owned clusters on
the disk. }
Var
NumClusters : Byte; { Number of clusters on the drive. }
FCBBuffer : Array [ 0..3 ] of Disk_FCB;
Vector : Array [ 0..127 ] of Boolean; { Bit map for drive. }
Procedure Zero_Directory( Blocks, FCBs : Integer );
Label 1, 2, 999;
Var Block : Integer;
Begin
1:
Vector_Valid := False;
Block := 0;
FillChar( FCBBuffer, 128, $E5 );
FCBBuffer[ 0 ].Name[ 0 ] := Chr( $37 );
FCBBuffer[ 0 ].Name[ 1 ] := Chr( Blocks shr 3 );
FCBBuffer[ 0 ].DM[ 6 ] := FCBs;
Goto 2;
2:
Write_Rom( Block, FCBBuffer );
FCBs := FCBs - 4;
Block := Block + 1;
If( FCBs > 0 ) Then Goto 2;
Goto 999;
999:
End;
Procedure Get_FCB( Var FCB : Memory_FCB );
Label 1, 2, 3, 4, 999;
Var
Block : Integer;
FIX : Byte;
Begin
1:
Block := FCB.FIX shr 2;
Read_ROM( Block, FCBBuffer );
FIX := FCB.FIX and 3;
If( FCBBuffer[ FIX ].ET = $E5 ) Then Goto 3;
Goto 2;
2:
FCB.DRV := FCB.DRV and $7f;
Goto 4;
3:
FCB.DRV := FCB.DRV or $80;
Goto 4;
4:
FCB.NAME := FCBBuffer[ FIX ].NAME;
FCB.EX := FCBBuffer[ FIX ].EX;
FCB.NR := FCBBuffer[ FIX ].NR;
FCB.DM := FCBBuffer[ FIX ].DM;
Goto 999;
999:
End;
Procedure Close_File( FCB : Memory_FCB );
Label 1, 2, 3, 4, 999;
Var
Block : Integer;
FIX : Byte;
Begin
1:
Block := FCB.FIX shr 2;
Read_Rom( Block, FCBBuffer );
FIX := FCB.FIX and 3;
if( ( FCB.DRV and $80 ) <> 0 ) Then Goto 3;
Goto 2;
2:
FCBBuffer[ FIX ].ET := 0;
Goto 4;
3:
FCBBuffer[ FIX ].ET := $E5;
Goto 4;
4:
FCBBuffer[ FIX ].Reserved1 := 0;
FCBBuffer[ FIX ].Reserved2 := 0;
FCBBuffer[ FIX ].NAME := FCB.NAME;
FCBBuffer[ FIX ].EX := FCB.EX;
FCBBuffer[ FIX ].NR := FCB.NR;
FCBBuffer[ FIX ].DM := FCB.DM;
Write_Rom( Block, FCBBuffer );
Goto 999;
999:
End;
Procedure Init_FCB( Var FCB : Memory_FCB );
Begin
FCB.DRV := FCB.DRV and $7f;
FCB.FIX := 0;
FCB.CR := 0;
FCB.NR := 0;
FillChar( FCB.DM, 16, 0 );
End;
Function Make_File( Var FCB : Memory_FCB ) : Boolean;
Label 1, 2, 3, 4, 5, 6, 7, 999;
Var
FIX : Byte;
Block : Integer;
FCBs : Integer;
Begin
1:
Init_FCB( FCB );
FIX := 1;
Block := 0;
Read_Rom( Block, FCBBuffer );
FCBs := FCBBuffer[ 0 ].DM[ 6 ];
Goto 2;
2:
If( ( FIX and 3 ) = 0 ) Then Goto 3;
Goto 4;
3:
Block := Block + 1;
Read_Rom( Block, FCBBuffer );
Goto 4;
4:
If( FCBBuffer[ FIX and 3 ].ET = $E5 ) Then Goto 5;
Goto 6;
5:
FCB.FIX := FIX;
Close_File( FCB );
Make_File := True;
Goto 999;
6:
FIX := FIX + 1;
If( FIX < FCBs ) Then Goto 2;
Goto 7;
7:
Make_File := False;
Goto 999;
999:
End;
Procedure Build_Vector;
Label 1, 2, 3, 4, 5, 6, 7, 8, 9, 999;
Var
FIX : Byte;
Block : Integer;
FCBs : Byte;
I, DMIX : Integer;
Begin
1:
FIX := 1;
Block := 0;
For I := 0 to 127 do
Vector[ I ] := False;
Read_Rom( Block, FCBBuffer );
NumClusters := Ord( FCBBuffer[ 0 ].Name[ 1 ] );
FCBs := FCBBuffer[ 0 ].DM[ 6 ];
Goto 2;
2:
If( ( FIX and 3 ) = 0 ) Then Goto 3;
Goto 4;
3:
Block := Block + 1;
Read_Rom( Block, FCBBuffer );
Goto 4;
4:
If( FIX < FCBs ) Then Goto 6;
Goto 5;
5:
Vector[ 0 ] := True;
Vector_Valid := True;
Goto 999;
6:
If( FCBBuffer[ FIX and 3 ].ET = $E5 ) Then Goto 9;
Goto 7;
7:
DMIX := 0;
Goto 8;
8:
Vector[ FCBBuffer[ FIX and 3 ].DM[ DMIX ] ] := True;
DMIX := DMIX + 1;
If( DMIX < 16 ) Then Goto 8;
Goto 9;
9:
FIX := FIX + 1;
Goto 2;
999:
End;
Function Allocate( Var FCB: Memory_FCB ) : Boolean;
Label 1, 2, 3, 4, 5, 6, 7, 999;
Var
CurCluster : Byte;
Begin
1:
If( Vector_Valid ) Then Goto 3;
Goto 2;
2:
Build_Vector;
Goto 3;
3:
CurCluster := 0;
Goto 4;
4:
If( Vector[ CurCluster ] ) Then Goto 5;
Goto 6;
5:
CurCluster := CurCluster + 1;
If( CurCluster < NumClusters ) Then Goto 4;
Goto 7;
6:
FCB.DM[ FCB.CR shr 4 ] := CurCluster;
Vector[ CurCluster ] := True;
Allocate := True;
Goto 999;
7:
Allocate := False;
Goto 999;
999:
End;
Function Write_Sequential( Var FCB : Memory_FCB; Var Buffer ) :
Boolean;
Label 1, 2, 3, 4, 5, 6, 7, 8, 999;
Var
Block : Integer;
Begin
1:
If( FCB.NR > 127 ) Then Goto 2;
Goto 3;
2:
Close_File( FCB );
FCB.EX := FCB.EX + 1;
If( Make_File( FCB ) ) Then Goto 3;
Goto 7;
3:
Block := FCB.DM[ FCB.CR SHR 4 ] * 8;
If( Block = 0 ) Then Goto 4;
Goto 5;
4:
If( Allocate( FCB ) ) Then Goto 3;
Goto 8;
5:
Write_Rom( Block + ( FCB.CR and 7 ), Buffer );
FCB.NR := FCB.NR + 1;
FCB.CR := FCB.CR + 1;
Write_Sequential := True;
If( ( FCB.CR and 7 ) = 0 ) Then Goto 6;
Goto 999;
6:
FCB.CR := ( FCB.CR + $10 ) and $F0;
Goto 999;
7:
Writeln( '%Write_Sequential: Directory full.' );
Write_Sequential := False;
Goto 999;
8:
Writeln( '%Write_Sequential: ROM full.' );
Write_Sequential := False;
Goto 999;
999:
End;
End of INFO-CPM Digest V92 Issue #72
************************************