mirror of
https://github.com/tjboldt/ProDOS-Utilities.git
synced 2024-11-28 12:51:35 +00:00
192 lines
7.0 KiB
Go
192 lines
7.0 KiB
Go
// Copyright Terence J. Boldt (c)2021-2024
|
|
// Use of this source code is governed by an MIT
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// This file provides text dumps for directories
|
|
// and blocks
|
|
|
|
package prodos
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// TimeToString displays the date and time in ProDOS format
|
|
func TimeToString(printTime time.Time) string {
|
|
return fmt.Sprintf("%04d-%s-%02d %02d:%02d",
|
|
printTime.Year(),
|
|
strings.ToUpper(printTime.Month().String()[0:3]),
|
|
printTime.Day(),
|
|
printTime.Hour(),
|
|
printTime.Minute(),
|
|
)
|
|
}
|
|
|
|
// FileTypeToString display the file type as a string
|
|
func FileTypeToString(fileType uint8) string {
|
|
switch fileType {
|
|
case 1:
|
|
return "BAD"
|
|
case 4:
|
|
return "TXT"
|
|
case 6:
|
|
return "BIN"
|
|
case 7:
|
|
return "FNT"
|
|
case 15:
|
|
return "DIR"
|
|
case 252:
|
|
return "BAS"
|
|
case 253:
|
|
return "VAR"
|
|
case 255:
|
|
return "SYS"
|
|
default:
|
|
return fmt.Sprintf("$%02X", fileType)
|
|
}
|
|
/*
|
|
File Type Preferred Use
|
|
$00 Typeless file (SOS and ProDOS)
|
|
$01 Bad block file
|
|
$02 * Pascal code file
|
|
$03 * Pascal text file
|
|
$04 ASCII text file (SOS and ProDOS)
|
|
$05 * Pascal data file
|
|
$06 General binary file (SOS and ProDOS)
|
|
$07 * Font file
|
|
$08 Graphics screen file
|
|
$09 * Business BASIC program file
|
|
$0A * Business BASIC data file
|
|
$0B * Word Processor file
|
|
$0C * SOS system file
|
|
$0D,$0E * SOS reserved
|
|
$0F Directory file (SOS and ProDOS)
|
|
$10 * RPS data file
|
|
$11 * RPS index file
|
|
$12 * AppleFile discard file
|
|
$13 * AppleFile model file
|
|
$14 * AppleFile report format file
|
|
$15 * Screen Library file
|
|
$16-$18 * SOS reserved
|
|
$19 AppleWorks Data Base file
|
|
$1A AppleWorks Word Processor file
|
|
$1B AppleWorks Spreadsheet file
|
|
$1C-$EE Reserved
|
|
$EF Pascal area
|
|
$F0 ProDOS CI added command file
|
|
$F1-$F8 ProDOS user defined files 1-8
|
|
$F9 ProDOS reserved
|
|
$FA Integer BASIC program file
|
|
$FB Integer BASIC variable file
|
|
$FC Applesoft program file
|
|
$FD Applesoft variables file
|
|
$FE Relocatable code file (EDASM)
|
|
$FF ProDOS system file
|
|
*/
|
|
}
|
|
|
|
// DumpFileEntry dumps the file entry values as text
|
|
func DumpFileEntry(fileEntry FileEntry) {
|
|
fmt.Printf("FileName: %s\n", fileEntry.FileName)
|
|
fmt.Printf("Creation time: %d-%s-%d %02d:%02d\n", fileEntry.CreationTime.Year(), fileEntry.CreationTime.Month(), fileEntry.CreationTime.Day(), fileEntry.CreationTime.Hour(), fileEntry.CreationTime.Minute())
|
|
fmt.Printf("Modified time: %d-%s-%d %02d:%02d\n", fileEntry.ModifiedTime.Year(), fileEntry.ModifiedTime.Month(), fileEntry.ModifiedTime.Day(), fileEntry.ModifiedTime.Hour(), fileEntry.ModifiedTime.Minute())
|
|
fmt.Printf("AuxType: %04X\n", fileEntry.AuxType)
|
|
fmt.Printf("EOF: %06X\n", fileEntry.EndOfFile)
|
|
fmt.Printf("Blocks used: %04X\n", fileEntry.BlocksUsed)
|
|
fmt.Printf("Starting block: %04X\n", fileEntry.KeyPointer)
|
|
fmt.Printf("File type: %02X\n", fileEntry.FileType)
|
|
fmt.Printf("Storage type: %02X\n", fileEntry.StorageType)
|
|
fmt.Printf("Header pointer: %04X\n", fileEntry.HeaderPointer)
|
|
fmt.Printf("Access: %04X\n", fileEntry.Access)
|
|
fmt.Printf("Directory block: %04X\n", fileEntry.DirectoryBlock)
|
|
fmt.Printf("Directory offset: %04X\n", fileEntry.DirectoryOffset)
|
|
fmt.Printf("\n")
|
|
}
|
|
|
|
// DumpVolumeHeader dumps the volume header values as text
|
|
func DumpVolumeHeader(volumeHeader VolumeHeader) {
|
|
fmt.Printf("Next block: %d\n", volumeHeader.NextBlock)
|
|
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("ProDOS version (should be 0): %d\n", volumeHeader.Version)
|
|
fmt.Printf("ProDOS mininum version (should be 0): %d\n", volumeHeader.MinVersion)
|
|
fmt.Printf("Entry length (should be 39): %d\n", volumeHeader.EntryLength)
|
|
fmt.Printf("Entries per block (should be 13): %d\n", volumeHeader.EntriesPerBlock)
|
|
fmt.Printf("File count: %d\n", volumeHeader.ActiveFileCount)
|
|
fmt.Printf("Bitmap starting block: %d\n", volumeHeader.BitmapStartBlock)
|
|
fmt.Printf("Total blocks: %d\n", volumeHeader.TotalBlocks)
|
|
}
|
|
|
|
// DumpDirectoryHeader dumps the directory header as text
|
|
func DumpDirectoryHeader(directoryHeader DirectoryHeader) {
|
|
fmt.Printf("Starting block: %04X\n", directoryHeader.StartingBlock)
|
|
fmt.Printf("Previous block: %04X\n", directoryHeader.PreviousBlock)
|
|
fmt.Printf("Next block: %04X\n", directoryHeader.NextBlock)
|
|
fmt.Printf("Is subdirectory: %t\n", directoryHeader.IsSubDirectory)
|
|
fmt.Printf("Name: %s\n", directoryHeader.Name)
|
|
fmt.Printf("Creation time: %s\n", TimeToString(directoryHeader.CreationTime))
|
|
fmt.Printf("Version: %02X\n", directoryHeader.Version)
|
|
fmt.Printf("MinVersion: %02X\n", directoryHeader.MinVersion)
|
|
fmt.Printf("Access: %02X\n", directoryHeader.Access)
|
|
fmt.Printf("Entry length: %02X\n", directoryHeader.EntryLength)
|
|
fmt.Printf("Entries per block: %02X\n", directoryHeader.EntriesPerBlock)
|
|
fmt.Printf("File count: %d\n", directoryHeader.ActiveFileCount)
|
|
fmt.Printf("Active file count: %04X\n", directoryHeader.ActiveFileCount)
|
|
fmt.Printf("Parent block: %04X\n", directoryHeader.ParentBlock)
|
|
fmt.Printf("Parent entry: %02X\n", directoryHeader.ParentEntry)
|
|
fmt.Printf("Parent entry length: %02X\n", directoryHeader.ParentEntryLength)
|
|
}
|
|
|
|
// DumpBlock dumps the block as hexadecimal and text
|
|
func DumpBlock(buffer []byte) {
|
|
for i := 0; i < len(buffer); i += 16 {
|
|
fmt.Printf("%04X: ", i)
|
|
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 && c < 127 {
|
|
fmt.Printf("%c", c)
|
|
} else {
|
|
fmt.Printf(".")
|
|
}
|
|
}
|
|
fmt.Printf("\n")
|
|
}
|
|
}
|
|
|
|
// DumpDirectory displays the directory similar to ProDOS catalog
|
|
func DumpDirectory(blocksFree uint16, totalBlocks uint16, path string, fileEntries []FileEntry) {
|
|
fmt.Printf("%s\n\n", path)
|
|
fmt.Printf("NAME TYPE BLOCKS MODIFIED CREATED ENDFILE SUBTYPE\n\n")
|
|
|
|
for i := 0; i < len(fileEntries); i++ {
|
|
var zeroTime = time.Time{}
|
|
var modifiedTime, createdTime string
|
|
if fileEntries[i].ModifiedTime == zeroTime {
|
|
modifiedTime = "<NO DATE> "
|
|
} else {
|
|
modifiedTime = TimeToString(fileEntries[i].ModifiedTime)
|
|
}
|
|
if fileEntries[i].CreationTime == zeroTime {
|
|
createdTime = "<NO DATE> "
|
|
} else {
|
|
createdTime = TimeToString(fileEntries[i].CreationTime)
|
|
}
|
|
fmt.Printf("%-15s %s%6d %s %s%8d %8d\n",
|
|
fileEntries[i].FileName,
|
|
FileTypeToString(fileEntries[i].FileType),
|
|
fileEntries[i].BlocksUsed,
|
|
modifiedTime,
|
|
createdTime,
|
|
fileEntries[i].EndOfFile,
|
|
fileEntries[i].AuxType,
|
|
)
|
|
}
|
|
fmt.Printf("\n")
|
|
fmt.Printf("BLOCKS FREE: %5d BLOCKS USED: %5d TOTAL BLOCKS: %5d\n", blocksFree, totalBlocks-blocksFree, totalBlocks)
|
|
}
|