ProDOS-Utilities/prodos/text.go
2023-01-22 12:06:43 -05:00

192 lines
7.0 KiB
Go

// Copyright Terence J. Boldt (c)2021-2023
// 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 int) 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 int, totalBlocks int, 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)
}