mirror of
https://github.com/tjboldt/ProDOS-Utilities.git
synced 2024-11-28 12:51:35 +00:00
Added up to 128KB file load support
This commit is contained in:
parent
6fd22018e3
commit
a701c6bc51
14
main.go
14
main.go
@ -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")
|
||||||
|
@ -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])
|
||||||
|
@ -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
61
prodos/file.go
Normal 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
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user