Added up to 128KB file load support

This commit is contained in:
Terence Boldt 2021-06-06 08:00:20 -04:00
parent 6fd22018e3
commit a701c6bc51
6 changed files with 94 additions and 37 deletions

14
main.go
View File

@ -9,9 +9,10 @@ import (
func main() { func main() {
if len(os.Args) < 2 || len(os.Args) > 3 { if len(os.Args) < 2 || len(os.Args) > 3 {
fmt.Printf("Usage:") fmt.Printf("Usage:\n")
fmt.Printf(" ProDOS-Utilities DRIVE_IMAGE") fmt.Printf(" ProDOS-Utilities DRIVE_IMAGE\n")
fmt.Printf(" ProDOS-Utilities DRIVE_IMAGE /FULL_PATH") fmt.Printf(" ProDOS-Utilities DRIVE_IMAGE /FULL_PATH\n")
os.Exit(1)
} }
fileName := os.Args[1] fileName := os.Args[1]
@ -21,8 +22,13 @@ func main() {
pathName = os.Args[2] pathName = os.Args[2]
} }
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
if err != nil {
os.Exit(1)
}
// empty path or volume name means read root directory // empty path or volume name means read root directory
volumeHeader, fileEntries := prodos.ReadDirectory(fileName, pathName) volumeHeader, fileEntries := prodos.ReadDirectory(file, pathName)
fmt.Printf("VOLUME: %s\n\n", volumeHeader.VolumeName) fmt.Printf("VOLUME: %s\n\n", volumeHeader.VolumeName)
fmt.Printf("NAME TYPE BLOCKS MODIFIED CREATED ENDFILE SUBTYPE\n\n") fmt.Printf("NAME TYPE BLOCKS MODIFIED CREATED ENDFILE SUBTYPE\n\n")

View File

@ -46,15 +46,10 @@ type FileEntry struct {
ModifiedTime time.Time ModifiedTime time.Time
} }
func ReadDirectory(driveFileName string, path string) (VolumeHeader, []FileEntry) { func ReadDirectory(file *os.File, path string) (VolumeHeader, []FileEntry) {
file, err := os.OpenFile(driveFileName, os.O_RDWR, 0755)
if err != nil {
return VolumeHeader{}, nil
}
buffer := ReadBlock(file, 2) buffer := ReadBlock(file, 2)
volumeHeader := ParseVolumeHeader(buffer) volumeHeader := parseVolumeHeader(buffer)
//dumpVolumeHeader(volumeHeader) //dumpVolumeHeader(volumeHeader)
if len(path) == 0 { if len(path) == 0 {
@ -74,7 +69,7 @@ func getFileEntriesInDirectory(file *os.File, blockNumber int, currentPath int,
buffer := ReadBlock(file, blockNumber) buffer := ReadBlock(file, blockNumber)
directoryHeader := ParseDirectoryHeader(buffer) directoryHeader := parseDirectoryHeader(buffer)
fileEntries := make([]FileEntry, directoryHeader.ActiveFileCount) fileEntries := make([]FileEntry, directoryHeader.ActiveFileCount)
entryOffset := 43 // start at offset after header entryOffset := 43 // start at offset after header
@ -149,7 +144,7 @@ func parseFileEntry(buffer []byte) FileEntry {
return fileEntry return fileEntry
} }
func ParseVolumeHeader(buffer []byte) VolumeHeader { func parseVolumeHeader(buffer []byte) VolumeHeader {
nextBlock := int(buffer[2]) + int(buffer[3])*256 nextBlock := int(buffer[2]) + int(buffer[3])*256
filenameLength := buffer[4] & 15 filenameLength := buffer[4] & 15
volumeName := string(buffer[5 : filenameLength+5]) volumeName := string(buffer[5 : filenameLength+5])
@ -179,7 +174,7 @@ func ParseVolumeHeader(buffer []byte) VolumeHeader {
return volumeHeader return volumeHeader
} }
func ParseDirectoryHeader(buffer []byte) DirectoryHeader { func parseDirectoryHeader(buffer []byte) DirectoryHeader {
nextBlock := int(buffer[2]) + int(buffer[3])*256 nextBlock := int(buffer[2]) + int(buffer[3])*256
filenameLength := buffer[4] & 15 filenameLength := buffer[4] & 15
name := string(buffer[5 : filenameLength+5]) name := string(buffer[5 : filenameLength+5])

View File

@ -1,20 +0,0 @@
package prodos
import "fmt"
func DumpBlock(buffer []byte) {
for i := 0; i < len(buffer); i += 16 {
for j := i; j < i+16; j++ {
fmt.Printf("%02X ", buffer[j])
}
for j := i; j < i+16; j++ {
c := buffer[j] & 127
if c >= 32 {
fmt.Printf("%c", c)
} else {
fmt.Printf(".")
}
}
fmt.Printf("\n")
}
}

61
prodos/file.go Normal file
View File

@ -0,0 +1,61 @@
package prodos
import (
"fmt"
"os"
"strings"
)
func LoadFile(file *os.File, path string) []byte {
path = strings.ToUpper(path)
paths := strings.Split(path, "/")
var directoryBuilder strings.Builder
for i := 1; i < len(paths)-1; i++ {
directoryBuilder.WriteString("/")
directoryBuilder.WriteString(paths[i])
}
directory := directoryBuilder.String()
fileName := paths[len(paths)-1]
volumeHeader, fileEntries := ReadDirectory(file, directory)
if fileEntries == nil {
return nil
}
var fileEntry FileEntry
for i := 0; i < len(fileEntries); i++ {
if fileEntries[i].FileName == fileName {
fileEntry = fileEntries[i]
}
}
DumpVolumeHeader(volumeHeader)
fmt.Println()
DumpFileEntry(fileEntry)
switch fileEntry.StorageType {
case StorageSeedling:
return ReadBlock(file, fileEntry.StartingBlock)[0:fileEntry.EndOfFile]
case StorageSapling:
index := ReadBlock(file, fileEntry.StartingBlock)
buffer := make([]byte, fileEntry.EndOfFile)
for i := 0; i < 512 && index[i] > 0; i++ {
chunk := ReadBlock(file, int(index[i])+int(index[i+256])*256)
for j := i * 512; j < fileEntry.EndOfFile && j < i*512+512; j++ {
buffer[j] = chunk[j-i*512]
}
}
return buffer
case StorageTree:
// add tree file support later
return nil
}
return nil
}

View File

@ -7,8 +7,6 @@ import (
func ReadBlock(file *os.File, block int) []byte { func ReadBlock(file *os.File, block int) []byte {
buffer := make([]byte, 512) buffer := make([]byte, 512)
//fmt.Printf("Read block %d\n", block)
file.ReadAt(buffer, int64(block)*512) file.ReadAt(buffer, int64(block)*512)
return buffer return buffer

View File

@ -91,7 +91,7 @@ func DumpFileEntry(fileEntry FileEntry) {
fmt.Printf("\n") fmt.Printf("\n")
} }
func dumpVolumeHeader(volumeHeader VolumeHeader) { func DumpVolumeHeader(volumeHeader VolumeHeader) {
fmt.Printf("Next block: %d\n", volumeHeader.NextBlock) fmt.Printf("Next block: %d\n", volumeHeader.NextBlock)
fmt.Printf("Volume name: %s\n", volumeHeader.VolumeName) fmt.Printf("Volume name: %s\n", volumeHeader.VolumeName)
fmt.Printf("Creation time: %d-%s-%d %02d:%02d\n", volumeHeader.CreationTime.Year(), volumeHeader.CreationTime.Month(), volumeHeader.CreationTime.Day(), volumeHeader.CreationTime.Hour(), volumeHeader.CreationTime.Minute()) fmt.Printf("Creation time: %d-%s-%d %02d:%02d\n", volumeHeader.CreationTime.Year(), volumeHeader.CreationTime.Month(), volumeHeader.CreationTime.Day(), volumeHeader.CreationTime.Hour(), volumeHeader.CreationTime.Minute())
@ -103,3 +103,20 @@ func dumpVolumeHeader(volumeHeader VolumeHeader) {
fmt.Printf("Bitmap starting block: %d\n", volumeHeader.BitmapStartBlock) fmt.Printf("Bitmap starting block: %d\n", volumeHeader.BitmapStartBlock)
fmt.Printf("Total blocks: %d\n", volumeHeader.TotalBlocks) fmt.Printf("Total blocks: %d\n", volumeHeader.TotalBlocks)
} }
func DumpBlock(buffer []byte) {
for i := 0; i < len(buffer); i += 16 {
for j := i; j < i+16; j++ {
fmt.Printf("%02X ", buffer[j])
}
for j := i; j < i+16; j++ {
c := buffer[j] & 127
if c >= 32 {
fmt.Printf("%c", c)
} else {
fmt.Printf(".")
}
}
fmt.Printf("\n")
}
}