mirror of https://github.com/zellyn/diskii.git
dos3: implement GetFile. Also add StartAddress
This commit is contained in:
parent
8eb11c7b93
commit
76f229ac2f
|
@ -87,8 +87,9 @@ type Operator interface {
|
|||
|
||||
// FileInfo represents a file descriptor plus the content.
|
||||
type FileInfo struct {
|
||||
Descriptor Descriptor
|
||||
Data []byte
|
||||
Descriptor Descriptor
|
||||
Data []byte
|
||||
StartAddress uint16
|
||||
}
|
||||
|
||||
// operatorFactory is the type of functions that accept a SectorDisk,
|
||||
|
|
107
lib/dos3/dos3.go
107
lib/dos3/dos3.go
|
@ -350,6 +350,37 @@ func (fd *FileDesc) FilenameString() string {
|
|||
return strings.TrimRight(string(slice), " ")
|
||||
}
|
||||
|
||||
// descriptor returns a disk.Descriptor for a FileDesc, but with the
|
||||
// length set to -1, since we can't know it without reading the file
|
||||
// contents.
|
||||
func (fd FileDesc) descriptor() disk.Descriptor {
|
||||
desc := disk.Descriptor{
|
||||
Name: fd.FilenameString(),
|
||||
Sectors: int(fd.SectorCount),
|
||||
Length: -1,
|
||||
Locked: (fd.Filetype & FiletypeLocked) > 0,
|
||||
}
|
||||
switch fd.Filetype & 0x7f {
|
||||
case FiletypeText: // Text file
|
||||
desc.Type = disk.FiletypeASCIIText
|
||||
case FiletypeInteger: // INTEGER BASIC file
|
||||
desc.Type = disk.FiletypeIntegerBASIC
|
||||
case FiletypeApplesoft: // APPLESOFT BASIC file
|
||||
desc.Type = disk.FiletypeApplesoftBASIC
|
||||
case FiletypeBinary: // BINARY file
|
||||
desc.Type = disk.FiletypeBinary
|
||||
case FiletypeS: // S type file
|
||||
desc.Type = disk.FiletypeS
|
||||
case FiletypeRelocatable: // RELOCATABLE object module file
|
||||
desc.Type = disk.FiletypeRelocatable
|
||||
case FiletypeA: // A type file
|
||||
desc.Type = disk.FiletypeA
|
||||
case FiletypeB: // B type file
|
||||
desc.Type = disk.FiletypeB
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
// Contents returns the on-disk contents of a file represented by a
|
||||
// FileDesc.
|
||||
func (fd *FileDesc) Contents(lsd disk.LogicalSectorDisk) ([]byte, error) {
|
||||
|
@ -544,20 +575,80 @@ func (o operator) Catalog(subdir string) ([]disk.Descriptor, error) {
|
|||
}
|
||||
descs := make([]disk.Descriptor, 0, len(fds))
|
||||
for _, fd := range fds {
|
||||
descs = append(descs, disk.Descriptor{
|
||||
Name: fd.FilenameString(),
|
||||
Sectors: int(fd.SectorCount),
|
||||
Length: -1, // TODO(zellyn): read actual file length
|
||||
Locked: (fd.Filetype & FiletypeLocked) > 0,
|
||||
})
|
||||
descs = append(descs, fd.descriptor())
|
||||
}
|
||||
return descs, nil
|
||||
}
|
||||
|
||||
// fileForFilename returns the FileDesc corresponding to the given
|
||||
// filename, or an error.
|
||||
func (o operator) fileForFilename(filename string) (FileDesc, error) {
|
||||
fds, _, err := ReadCatalog(o.lsd)
|
||||
if err != nil {
|
||||
return FileDesc{}, err
|
||||
}
|
||||
for _, fd := range fds {
|
||||
if fd.FilenameString() == filename {
|
||||
return fd, nil
|
||||
}
|
||||
}
|
||||
return FileDesc{}, fmt.Errorf("Filename %q not found", filename)
|
||||
}
|
||||
|
||||
// GetFile retrieves a file by name.
|
||||
func (o operator) GetFile(filename string) (disk.FileInfo, error) {
|
||||
// TODO(zellyn): Implement GetFile
|
||||
return disk.FileInfo{}, fmt.Errorf("%s does not yet implement `GetFile`", operatorName)
|
||||
fd, err := o.fileForFilename(filename)
|
||||
if err != nil {
|
||||
return disk.FileInfo{}, err
|
||||
}
|
||||
desc := fd.descriptor()
|
||||
data, err := fd.Contents(o.lsd)
|
||||
if err != nil {
|
||||
return disk.FileInfo{}, err
|
||||
}
|
||||
|
||||
fi := disk.FileInfo{
|
||||
Descriptor: desc,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
errType := "UNKNOWN"
|
||||
switch fd.Filetype & 0x7f {
|
||||
case FiletypeText: // Text file
|
||||
for data[len(data)-1] == 0 {
|
||||
data = data[:len(data)-1]
|
||||
}
|
||||
fi.Descriptor.Length = len(data)
|
||||
fi.Data = data
|
||||
return fi, nil
|
||||
|
||||
case FiletypeInteger, FiletypeApplesoft, FiletypeBinary:
|
||||
switch fd.Filetype & 0x7f {
|
||||
case FiletypeApplesoft:
|
||||
fi.StartAddress = 0x801
|
||||
case FiletypeInteger:
|
||||
// TODO(zellyn): figure out what address integer basic programs are stored at.
|
||||
case FiletypeBinary:
|
||||
fi.StartAddress = uint16(data[0]) + uint16(data[1])<<8
|
||||
data = data[2:]
|
||||
}
|
||||
length := int(data[0]) + int(data[1])*256
|
||||
data = data[2 : length+2]
|
||||
fi.Descriptor.Length = length
|
||||
fi.Data = data
|
||||
return fi, nil
|
||||
|
||||
case FiletypeS: // S type file
|
||||
errType = "S"
|
||||
case FiletypeRelocatable: // RELOCATABLE object module file
|
||||
errType = "REL"
|
||||
case FiletypeA: // A type file
|
||||
errType = "A"
|
||||
case FiletypeB: // B type file
|
||||
errType = "B"
|
||||
}
|
||||
|
||||
return disk.FileInfo{}, fmt.Errorf("%s does not yet implement `GetFile` for filetype %s", operatorName, errType)
|
||||
}
|
||||
|
||||
// operatorFactory is the factory that returns dos3 operators given
|
||||
|
|
|
@ -319,6 +319,7 @@ func (o operator) GetFile(filename string) (disk.FileInfo, error) {
|
|||
Length: len(data),
|
||||
Locked: false,
|
||||
Type: disk.FiletypeBinary,
|
||||
// TODO(zellyn): Set StartAddress if we know it.
|
||||
}
|
||||
return disk.FileInfo{
|
||||
Descriptor: desc,
|
||||
|
|
Loading…
Reference in New Issue