Skip to content

Commit

Permalink
dos3: implement GetFile. Also add StartAddress
Browse files Browse the repository at this point in the history
  • Loading branch information
zellyn committed Nov 18, 2016
1 parent 8eb11c7 commit 76f229a
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 10 deletions.
5 changes: 3 additions & 2 deletions lib/disk/ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
107 changes: 99 additions & 8 deletions lib/dos3/dos3.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lib/supermon/supermon.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 76f229a

Please sign in to comment.