mirror of
https://github.com/tjboldt/ProDOS-Utilities.git
synced 2025-03-25 17:29:50 +00:00
Change ints to specific uints
This commit is contained in:
parent
baf9934a50
commit
375f1c764b
32
main.go
32
main.go
@ -25,21 +25,21 @@ func main() {
|
||||
var command string
|
||||
var outFileName string
|
||||
var inFileName string
|
||||
var blockNumber int
|
||||
var volumeSize int
|
||||
var blockNumber uint
|
||||
var volumeSize uint
|
||||
var volumeName string
|
||||
var fileType int
|
||||
var auxType int
|
||||
var fileType uint
|
||||
var auxType uint
|
||||
flag.StringVar(&fileName, "d", "", "A ProDOS format drive image")
|
||||
flag.StringVar(&pathName, "p", "", "Path name in ProDOS drive image (default is root of volume)")
|
||||
flag.StringVar(&command, "c", "ls", "Command to execute: ls, get, put, rm, mkdir, readblock, writeblock, create, putall, putallrecursive")
|
||||
flag.StringVar(&outFileName, "o", "", "Name of file to write")
|
||||
flag.StringVar(&inFileName, "i", "", "Name of file to read")
|
||||
flag.IntVar(&volumeSize, "s", 65535, "Number of blocks to create the volume with (default 65535, 64 to 65535, 0x0040 to 0xFFFF hex input accepted)")
|
||||
flag.UintVar(&volumeSize, "s", 65535, "Number of blocks to create the volume with (default 65535, 64 to 65535, 0x0040 to 0xFFFF hex input accepted)")
|
||||
flag.StringVar(&volumeName, "v", "NO.NAME", "Specifiy a name for the volume from 1 to 15 characters")
|
||||
flag.IntVar(&blockNumber, "b", 0, "A block number to read/write from 0 to 65535 (0x0000 to 0xFFFF hex input accepted)")
|
||||
flag.IntVar(&fileType, "t", 0, "ProDOS FileType: 0x04 for TXT, 0x06 for BIN, 0xFC for BAS, 0xFF for SYS etc., omit to autodetect")
|
||||
flag.IntVar(&auxType, "a", 0, "ProDOS AuxType from 0 to 65535 (0x0000 to 0xFFFF hex input accepted), omit to autodetect")
|
||||
flag.UintVar(&blockNumber, "b", 0, "A block number to read/write from 0 to 65535 (0x0000 to 0xFFFF hex input accepted)")
|
||||
flag.UintVar(&fileType, "t", 0, "ProDOS FileType: 0x04 for TXT, 0x06 for BIN, 0xFC for BAS, 0xFF for SYS etc., omit to autodetect")
|
||||
flag.UintVar(&auxType, "a", 0, "ProDOS AuxType from 0 to 65535 (0x0000 to 0xFFFF hex input accepted), omit to autodetect")
|
||||
flag.Parse()
|
||||
|
||||
if len(fileName) == 0 {
|
||||
@ -54,13 +54,13 @@ func main() {
|
||||
case "get":
|
||||
get(fileName, pathName, outFileName)
|
||||
case "put":
|
||||
put(fileName, pathName, fileType, auxType, inFileName)
|
||||
put(fileName, pathName, uint8(fileType), uint16(auxType), inFileName)
|
||||
case "readblock":
|
||||
readBlock(blockNumber, fileName)
|
||||
readBlock(uint16(blockNumber), fileName)
|
||||
case "writeblock":
|
||||
writeBlock(blockNumber, fileName, inFileName)
|
||||
writeBlock(uint16(blockNumber), fileName, inFileName)
|
||||
case "create":
|
||||
create(fileName, volumeName, volumeSize)
|
||||
create(fileName, volumeName, uint16(volumeSize))
|
||||
case "putall":
|
||||
putall(fileName, inFileName, pathName, false)
|
||||
case "putallrecursive":
|
||||
@ -147,7 +147,7 @@ func putall(fileName string, inFileName string, pathName string, recursive bool)
|
||||
}
|
||||
}
|
||||
|
||||
func create(fileName string, volumeName string, volumeSize int) {
|
||||
func create(fileName string, volumeName string, volumeSize uint16) {
|
||||
file, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to create file: %s\n", err)
|
||||
@ -157,7 +157,7 @@ func create(fileName string, volumeName string, volumeSize int) {
|
||||
prodos.CreateVolume(file, volumeName, volumeSize)
|
||||
}
|
||||
|
||||
func writeBlock(blockNumber int, fileName string, inFileName string) {
|
||||
func writeBlock(blockNumber uint16, fileName string, inFileName string) {
|
||||
checkInFileName(inFileName)
|
||||
fmt.Printf("Writing block 0x%04X (%d):\n\n", blockNumber, blockNumber)
|
||||
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
||||
@ -174,7 +174,7 @@ func writeBlock(blockNumber int, fileName string, inFileName string) {
|
||||
prodos.WriteBlock(file, blockNumber, inFile)
|
||||
}
|
||||
|
||||
func readBlock(blockNumber int, fileName string) {
|
||||
func readBlock(blockNumber uint16, fileName string) {
|
||||
fmt.Printf("Reading block 0x%04X (%d):\n\n", blockNumber, blockNumber)
|
||||
file, err := os.OpenFile(fileName, os.O_RDONLY, 0755)
|
||||
if err != nil {
|
||||
@ -190,7 +190,7 @@ func readBlock(blockNumber int, fileName string) {
|
||||
prodos.DumpBlock(block)
|
||||
}
|
||||
|
||||
func put(fileName string, pathName string, fileType int, auxType int, inFileName string) {
|
||||
func put(fileName string, pathName string, fileType uint8, auxType uint16, inFileName string) {
|
||||
checkPathName(pathName)
|
||||
checkInFileName(inFileName)
|
||||
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
||||
|
112
prodos/bitmap.go
112
prodos/bitmap.go
@ -33,13 +33,13 @@ func ReadVolumeBitmap(reader io.ReaderAt) ([]byte, error) {
|
||||
totalBitmapBlocks++
|
||||
}
|
||||
|
||||
for i := 0; i < totalBitmapBlocks; i++ {
|
||||
for i := uint16(0); i < totalBitmapBlocks; i++ {
|
||||
bitmapBlock, err := ReadBlock(reader, i+volumeHeader.BitmapStartBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for j := 0; j < 512 && i*512+j < totalBitmapBytes; j++ {
|
||||
for j := uint16(0); j < 512 && i*512+j < totalBitmapBytes; j++ {
|
||||
bitmap[i*512+j] = bitmapBlock[j]
|
||||
}
|
||||
}
|
||||
@ -48,10 +48,10 @@ func ReadVolumeBitmap(reader io.ReaderAt) ([]byte, error) {
|
||||
}
|
||||
|
||||
// GetFreeBlockCount gets the number of free blocks on a ProDOS image
|
||||
func GetFreeBlockCount(volumeBitmap []byte, totalBlocks int) int {
|
||||
freeBlockCount := 0
|
||||
func GetFreeBlockCount(volumeBitmap []byte, totalBlocks uint16) uint16 {
|
||||
freeBlockCount := uint16(0)
|
||||
|
||||
for i := 0; i < totalBlocks; i++ {
|
||||
for i := uint16(0); i < totalBlocks; i++ {
|
||||
if checkFreeBlockInVolumeBitmap(volumeBitmap, i) {
|
||||
freeBlockCount++
|
||||
}
|
||||
@ -77,13 +77,13 @@ func writeVolumeBitmap(readerWriter ReaderWriterAt, bitmap []byte) error {
|
||||
totalBitmapBlocks++
|
||||
}
|
||||
|
||||
for i := 0; i < totalBitmapBlocks; i++ {
|
||||
for i := uint16(0); i < totalBitmapBlocks; i++ {
|
||||
bitmapBlock, err := ReadBlock(readerWriter, i+volumeHeader.BitmapStartBlock)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for j := 0; j < 512 && i*512+j < totalBitmapBytes; j++ {
|
||||
for j := uint16(0); j < 512 && i*512+j < totalBitmapBytes; j++ {
|
||||
bitmapBlock[j] = bitmap[i*512+j]
|
||||
}
|
||||
|
||||
@ -96,9 +96,10 @@ func writeVolumeBitmap(readerWriter ReaderWriterAt, bitmap []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createVolumeBitmap(numberOfBlocks int) []byte {
|
||||
volumeBitmapBlocks := numberOfBlocks / 512 / 8
|
||||
if volumeBitmapBlocks*8*512 < numberOfBlocks {
|
||||
func createVolumeBitmap(numberOfBlocks uint16) []byte {
|
||||
// needs to be > uint16 because it's multiplying by a uint16
|
||||
volumeBitmapBlocks := uint32(numberOfBlocks / 512 / 8)
|
||||
if volumeBitmapBlocks*8*512 < uint32(numberOfBlocks) {
|
||||
volumeBitmapBlocks++
|
||||
}
|
||||
|
||||
@ -119,30 +120,31 @@ func createVolumeBitmap(numberOfBlocks int) []byte {
|
||||
markBlockInVolumeBitmap(volumeBitmap, 5)
|
||||
|
||||
// volume bitmap blocks
|
||||
for i := 0; i < volumeBitmapBlocks; i++ {
|
||||
markBlockInVolumeBitmap(volumeBitmap, 6+i)
|
||||
for i := uint32(0); i < volumeBitmapBlocks; i++ {
|
||||
markBlockInVolumeBitmap(volumeBitmap, uint16(6+i))
|
||||
}
|
||||
|
||||
// blocks beyond the volume
|
||||
totalBlocksInBitmap := volumeBitmapBlocks * 512 * 8
|
||||
blocksBeyondEnd := totalBlocksInBitmap - numberOfBlocks
|
||||
blocksBeyondEnd := totalBlocksInBitmap - uint32(numberOfBlocks)
|
||||
if blocksBeyondEnd > 0 {
|
||||
for i := totalBlocksInBitmap - blocksBeyondEnd; i < totalBlocksInBitmap; i++ {
|
||||
markBlockInVolumeBitmap(volumeBitmap, i)
|
||||
markBlockInVolumeBitmap(volumeBitmap, uint16(i))
|
||||
}
|
||||
}
|
||||
|
||||
return volumeBitmap
|
||||
}
|
||||
|
||||
func findFreeBlocks(volumeBitmap []byte, numberOfBlocks int) []int {
|
||||
blocks := make([]int, numberOfBlocks)
|
||||
func findFreeBlocks(volumeBitmap []byte, numberOfBlocks uint16) []uint16 {
|
||||
blocks := make([]uint16, numberOfBlocks)
|
||||
|
||||
blocksFound := 0
|
||||
blocksFound := uint16(0)
|
||||
|
||||
for i := 0; i < len(volumeBitmap)*8; i++ {
|
||||
if checkFreeBlockInVolumeBitmap(volumeBitmap, i) {
|
||||
blocks[blocksFound] = i
|
||||
// needs to be > uint16 because it's multiplying by a uint16
|
||||
for i := uint32(0); i < uint32(len(volumeBitmap))*8; i++ {
|
||||
if checkFreeBlockInVolumeBitmap(volumeBitmap, uint16(i)) {
|
||||
blocks[blocksFound] = uint16(i)
|
||||
blocksFound++
|
||||
if blocksFound == numberOfBlocks {
|
||||
return blocks
|
||||
@ -153,87 +155,29 @@ func findFreeBlocks(volumeBitmap []byte, numberOfBlocks int) []int {
|
||||
return nil
|
||||
}
|
||||
|
||||
func markBlockInVolumeBitmap(volumeBitmap []byte, blockNumber int) {
|
||||
func markBlockInVolumeBitmap(volumeBitmap []byte, blockNumber uint16) {
|
||||
bitToChange := blockNumber % 8
|
||||
byteToChange := blockNumber / 8
|
||||
|
||||
byteToAnd := 0b11111111
|
||||
byteToAnd := (uint8(0b10000000) >> uint8(bitToChange)) ^ 0b11111111
|
||||
|
||||
switch bitToChange {
|
||||
case 0:
|
||||
byteToAnd = 0b01111111
|
||||
case 1:
|
||||
byteToAnd = 0b10111111
|
||||
case 2:
|
||||
byteToAnd = 0b11011111
|
||||
case 3:
|
||||
byteToAnd = 0b11101111
|
||||
case 4:
|
||||
byteToAnd = 0b11110111
|
||||
case 5:
|
||||
byteToAnd = 0b11111011
|
||||
case 6:
|
||||
byteToAnd = 0b11111101
|
||||
case 7:
|
||||
byteToAnd = 0b11111110
|
||||
}
|
||||
|
||||
//fmt.Printf("blockNumber: $%04X byteToWrite: 0b%08b volumeBitmap: $%02X byteToChange: $%04X\n", blockNumber, byteToWrite, volumeBitmap[byteToChange], byteToChange)
|
||||
volumeBitmap[byteToChange] &= byte(byteToAnd)
|
||||
}
|
||||
|
||||
func freeBlockInVolumeBitmap(volumeBitmap []byte, blockNumber int) {
|
||||
func freeBlockInVolumeBitmap(volumeBitmap []byte, blockNumber uint16) {
|
||||
bitToChange := blockNumber % 8
|
||||
byteToChange := blockNumber / 8
|
||||
|
||||
byteToOr := 0b00000000
|
||||
|
||||
switch bitToChange {
|
||||
case 0:
|
||||
byteToOr = 0b10000000
|
||||
case 1:
|
||||
byteToOr = 0b01000000
|
||||
case 2:
|
||||
byteToOr = 0b00100000
|
||||
case 3:
|
||||
byteToOr = 0b00010000
|
||||
case 4:
|
||||
byteToOr = 0b00001000
|
||||
case 5:
|
||||
byteToOr = 0b00000100
|
||||
case 6:
|
||||
byteToOr = 0b00000010
|
||||
case 7:
|
||||
byteToOr = 0b00000001
|
||||
}
|
||||
byteToOr := uint8(0b10000000) >> uint8(bitToChange)
|
||||
|
||||
volumeBitmap[byteToChange] |= byte(byteToOr)
|
||||
}
|
||||
|
||||
func checkFreeBlockInVolumeBitmap(volumeBitmap []byte, blockNumber int) bool {
|
||||
func checkFreeBlockInVolumeBitmap(volumeBitmap []byte, blockNumber uint16) bool {
|
||||
bitToCheck := blockNumber % 8
|
||||
byteToCheck := blockNumber / 8
|
||||
|
||||
byteToAnd := 0b00000000
|
||||
|
||||
switch bitToCheck {
|
||||
case 0:
|
||||
byteToAnd = 0b10000000
|
||||
case 1:
|
||||
byteToAnd = 0b01000000
|
||||
case 2:
|
||||
byteToAnd = 0b00100000
|
||||
case 3:
|
||||
byteToAnd = 0b00010000
|
||||
case 4:
|
||||
byteToAnd = 0b00001000
|
||||
case 5:
|
||||
byteToAnd = 0b00000100
|
||||
case 6:
|
||||
byteToAnd = 0b00000010
|
||||
case 7:
|
||||
byteToAnd = 0b00000001
|
||||
}
|
||||
byteToAnd := uint8(0b10000000) >> uint8(bitToCheck)
|
||||
|
||||
return (volumeBitmap[byteToCheck] & byte(byteToAnd)) > 0
|
||||
}
|
||||
|
@ -14,10 +14,10 @@ import (
|
||||
|
||||
func TestCreateVolumeBitmap(t *testing.T) {
|
||||
var tests = []struct {
|
||||
blocks int
|
||||
want int
|
||||
blocks uint16
|
||||
want uint16
|
||||
}{
|
||||
{65536, 8192},
|
||||
{65535, 8192},
|
||||
{65533, 8192},
|
||||
{140, 512},
|
||||
}
|
||||
@ -26,7 +26,7 @@ func TestCreateVolumeBitmap(t *testing.T) {
|
||||
testname := fmt.Sprintf("%d", tt.blocks)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
volumeBitMap := createVolumeBitmap(tt.blocks)
|
||||
ans := len(volumeBitMap)
|
||||
ans := uint16(len(volumeBitMap))
|
||||
if ans != tt.want {
|
||||
t.Errorf("got %d, want %d", ans, tt.want)
|
||||
}
|
||||
@ -36,7 +36,7 @@ func TestCreateVolumeBitmap(t *testing.T) {
|
||||
|
||||
func TestCheckFreeBlockInVolumeBitmap(t *testing.T) {
|
||||
var tests = []struct {
|
||||
blocks int
|
||||
blocks uint16
|
||||
want bool
|
||||
}{
|
||||
{0, false}, // boot block
|
||||
@ -63,7 +63,7 @@ func TestCheckFreeBlockInVolumeBitmap(t *testing.T) {
|
||||
|
||||
func TestMarkBlockInVolumeBitmap(t *testing.T) {
|
||||
var tests = []struct {
|
||||
blocks int
|
||||
blocks uint16
|
||||
want bool
|
||||
}{
|
||||
{0, false}, // boot block
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// ReadBlock reads a block from a ProDOS volume into a byte array
|
||||
func ReadBlock(reader io.ReaderAt, block int) ([]byte, error) {
|
||||
func ReadBlock(reader io.ReaderAt, block uint16) ([]byte, error) {
|
||||
buffer := make([]byte, 512)
|
||||
|
||||
_, err := reader.ReadAt(buffer, int64(block)*512)
|
||||
@ -27,7 +27,7 @@ func ReadBlock(reader io.ReaderAt, block int) ([]byte, error) {
|
||||
}
|
||||
|
||||
// WriteBlock writes a block to a ProDOS volume from a byte array
|
||||
func WriteBlock(writer io.WriterAt, block int, buffer []byte) error {
|
||||
func WriteBlock(writer io.WriterAt, block uint16, buffer []byte) error {
|
||||
_, err := writer.WriteAt(buffer, int64(block)*512)
|
||||
if err != nil {
|
||||
errString := fmt.Sprintf("failed to write block %04X: %s", block, err.Error())
|
||||
|
@ -19,33 +19,33 @@ import (
|
||||
type VolumeHeader struct {
|
||||
VolumeName string
|
||||
CreationTime time.Time
|
||||
ActiveFileCount int
|
||||
BitmapStartBlock int
|
||||
TotalBlocks int
|
||||
NextBlock int
|
||||
EntryLength int
|
||||
EntriesPerBlock int
|
||||
MinVersion int
|
||||
Version int
|
||||
ActiveFileCount uint16
|
||||
BitmapStartBlock uint16
|
||||
TotalBlocks uint16
|
||||
NextBlock uint16
|
||||
EntryLength uint8
|
||||
EntriesPerBlock uint8
|
||||
MinVersion uint8
|
||||
Version uint8
|
||||
}
|
||||
|
||||
// DirectoryHeader from ProDOS
|
||||
type DirectoryHeader struct {
|
||||
PreviousBlock int
|
||||
NextBlock int
|
||||
PreviousBlock uint16
|
||||
NextBlock uint16
|
||||
IsSubDirectory bool
|
||||
Name string
|
||||
CreationTime time.Time
|
||||
Version int
|
||||
MinVersion int
|
||||
Access int
|
||||
EntryLength int
|
||||
EntriesPerBlock int
|
||||
ActiveFileCount int
|
||||
StartingBlock int
|
||||
ParentBlock int
|
||||
ParentEntry int
|
||||
ParentEntryLength int
|
||||
Version uint8
|
||||
MinVersion uint8
|
||||
Access uint8
|
||||
EntryLength uint8
|
||||
EntriesPerBlock uint8
|
||||
ActiveFileCount uint16
|
||||
StartingBlock uint16
|
||||
ParentBlock uint16
|
||||
ParentEntry uint16
|
||||
ParentEntryLength uint8
|
||||
}
|
||||
|
||||
const (
|
||||
@ -65,22 +65,22 @@ const (
|
||||
|
||||
// FileEntry from ProDOS
|
||||
type FileEntry struct {
|
||||
StorageType int
|
||||
StorageType uint8
|
||||
FileName string
|
||||
FileType int
|
||||
FileType uint8
|
||||
CreationTime time.Time
|
||||
KeyPointer int
|
||||
Version int
|
||||
MinVersion int
|
||||
BlocksUsed int
|
||||
EndOfFile int
|
||||
Access int
|
||||
AuxType int
|
||||
KeyPointer uint16
|
||||
Version uint8
|
||||
MinVersion uint8
|
||||
BlocksUsed uint16
|
||||
EndOfFile uint32
|
||||
Access uint8
|
||||
AuxType uint16
|
||||
ModifiedTime time.Time
|
||||
HeaderPointer int
|
||||
HeaderPointer uint16
|
||||
|
||||
DirectoryBlock int
|
||||
DirectoryOffset int
|
||||
DirectoryBlock uint16
|
||||
DirectoryOffset uint16
|
||||
}
|
||||
|
||||
// ReadDirectory reads the directory information from a specified path
|
||||
@ -183,7 +183,7 @@ func CreateDirectory(readerWriter ReaderWriterAt, path string) error {
|
||||
ActiveFileCount: 0,
|
||||
StartingBlock: blockList[0],
|
||||
ParentBlock: fileEntry.DirectoryBlock,
|
||||
ParentEntry: (fileEntry.DirectoryOffset - 0x04) / 0x27,
|
||||
ParentEntry: uint16(fileEntry.DirectoryOffset-0x04) / 0x27,
|
||||
ParentEntryLength: 0x27,
|
||||
}
|
||||
|
||||
@ -219,18 +219,18 @@ func getFreeFileEntryInDirectory(readerWriter ReaderWriterAt, directory string)
|
||||
if err != nil {
|
||||
return FileEntry{}, err
|
||||
}
|
||||
entryOffset := 43 // start at offset after header
|
||||
entryNumber := 2 // header is essentially the first entry so start at 2
|
||||
entryOffset := uint16(43) // start at offset after header
|
||||
entryNumber := 2 // header is essentially the first entry so start at 2
|
||||
|
||||
for {
|
||||
if entryNumber > 13 {
|
||||
nextBlockNumber := int(buffer[2]) + int(buffer[3])*256
|
||||
nextBlockNumber := uint16(buffer[2]) + uint16(buffer[3])*256
|
||||
// if we ran out of blocks in the directory, expand directory or fail
|
||||
if nextBlockNumber == 0 {
|
||||
if !directoryHeader.IsSubDirectory {
|
||||
return FileEntry{}, errors.New("no free file entries found")
|
||||
}
|
||||
nextBlockNumber, err = expandDirectory(readerWriter, nextBlockNumber, buffer, blockNumber, directoryHeader)
|
||||
nextBlockNumber, err = expandDirectory(readerWriter, buffer, blockNumber, directoryHeader)
|
||||
if err != nil {
|
||||
return FileEntry{}, err
|
||||
}
|
||||
@ -260,7 +260,7 @@ func getFreeFileEntryInDirectory(readerWriter ReaderWriterAt, directory string)
|
||||
}
|
||||
}
|
||||
|
||||
func expandDirectory(readerWriter ReaderWriterAt, nextBlockNumber int, buffer []byte, blockNumber int, directoryHeader DirectoryHeader) (int, error) {
|
||||
func expandDirectory(readerWriter ReaderWriterAt, buffer []byte, blockNumber uint16, directoryHeader DirectoryHeader) (uint16, error) {
|
||||
volumeBitMap, err := ReadVolumeBitmap(readerWriter)
|
||||
if err != nil {
|
||||
errString := fmt.Sprintf("failed to get volume bitmap to expand directory: %s", err)
|
||||
@ -271,7 +271,7 @@ func expandDirectory(readerWriter ReaderWriterAt, nextBlockNumber int, buffer []
|
||||
return 0, errors.New("failed to get free block to expand directory")
|
||||
}
|
||||
|
||||
nextBlockNumber = blockList[0]
|
||||
nextBlockNumber := blockList[0]
|
||||
buffer[0x02] = byte(nextBlockNumber & 0x00FF)
|
||||
buffer[0x03] = byte(nextBlockNumber >> 8)
|
||||
WriteBlock(readerWriter, blockNumber, buffer)
|
||||
@ -296,8 +296,8 @@ func expandDirectory(readerWriter ReaderWriterAt, nextBlockNumber int, buffer []
|
||||
errString := fmt.Sprintf("failed to read parent block to expand directory: %s", err)
|
||||
return 0, errors.New(errString)
|
||||
}
|
||||
directoryEntryOffset := directoryHeader.ParentEntry*directoryHeader.EntryLength + 0x04
|
||||
directoryFileEntry := parseFileEntry(buffer[directoryEntryOffset:directoryEntryOffset+0x28], directoryHeader.ParentBlock, directoryHeader.ParentEntry*directoryHeader.EntryLength+0x04)
|
||||
directoryEntryOffset := directoryHeader.ParentEntry*uint16(directoryHeader.EntryLength) + 0x04
|
||||
directoryFileEntry := parseFileEntry(buffer[directoryEntryOffset:directoryEntryOffset+0x28], directoryHeader.ParentBlock, directoryHeader.ParentEntry*uint16(directoryHeader.EntryLength)+0x04)
|
||||
directoryFileEntry.BlocksUsed++
|
||||
directoryFileEntry.EndOfFile += 0x200
|
||||
writeFileEntry(readerWriter, directoryFileEntry)
|
||||
@ -305,7 +305,7 @@ func expandDirectory(readerWriter ReaderWriterAt, nextBlockNumber int, buffer []
|
||||
return nextBlockNumber, nil
|
||||
}
|
||||
|
||||
func getFileEntriesInDirectory(reader io.ReaderAt, blockNumber int, currentPath int, paths []string) (DirectoryHeader, []FileEntry, error) {
|
||||
func getFileEntriesInDirectory(reader io.ReaderAt, blockNumber uint16, currentPath int, paths []string) (DirectoryHeader, []FileEntry, error) {
|
||||
buffer, err := ReadBlock(reader, blockNumber)
|
||||
if err != nil {
|
||||
return DirectoryHeader{}, nil, err
|
||||
@ -314,9 +314,9 @@ func getFileEntriesInDirectory(reader io.ReaderAt, blockNumber int, currentPath
|
||||
directoryHeader := parseDirectoryHeader(buffer, blockNumber)
|
||||
|
||||
fileEntries := make([]FileEntry, directoryHeader.ActiveFileCount)
|
||||
entryOffset := 43 // start at offset after header
|
||||
activeEntries := 0
|
||||
entryNumber := 2 // header is essentially the first entry so start at 2
|
||||
entryOffset := uint16(43) // start at offset after header
|
||||
activeEntries := uint16(0)
|
||||
entryNumber := uint8(2) // header is essentially the first entry so start at 2
|
||||
|
||||
nextBlock := directoryHeader.NextBlock
|
||||
|
||||
@ -338,7 +338,7 @@ func getFileEntriesInDirectory(reader io.ReaderAt, blockNumber int, currentPath
|
||||
if err != nil {
|
||||
return DirectoryHeader{}, nil, err
|
||||
}
|
||||
nextBlock = int(buffer[2]) + int(buffer[3])*256
|
||||
nextBlock = uint16(buffer[2]) + uint16(buffer[3])*256
|
||||
}
|
||||
fileEntry := parseFileEntry(buffer[entryOffset:entryOffset+40], blockNumber, entryOffset)
|
||||
|
||||
@ -359,21 +359,21 @@ func getFileEntriesInDirectory(reader io.ReaderAt, blockNumber int, currentPath
|
||||
}
|
||||
}
|
||||
|
||||
func parseFileEntry(buffer []byte, blockNumber int, entryOffset int) FileEntry {
|
||||
storageType := int(buffer[0] >> 4)
|
||||
fileNameLength := int(buffer[0] & 15)
|
||||
func parseFileEntry(buffer []byte, blockNumber uint16, entryOffset uint16) FileEntry {
|
||||
storageType := buffer[0] >> 4
|
||||
fileNameLength := buffer[0] & 15
|
||||
fileName := string(buffer[1 : fileNameLength+1])
|
||||
fileType := int(buffer[16])
|
||||
startingBlock := int(buffer[17]) + int(buffer[18])*256
|
||||
blocksUsed := int(buffer[19]) + int(buffer[20])*256
|
||||
endOfFile := int(buffer[21]) + int(buffer[22])*256 + int(buffer[23])*65536
|
||||
fileType := buffer[16]
|
||||
startingBlock := uint16(buffer[17]) + uint16(buffer[18])*256
|
||||
blocksUsed := uint16(buffer[19]) + uint16(buffer[20])*256
|
||||
endOfFile := uint32(buffer[21]) + uint32(buffer[22])*256 + uint32(buffer[23])*65536
|
||||
creationTime := DateTimeFromProDOS(buffer[24:28])
|
||||
version := int(buffer[28])
|
||||
minVersion := int(buffer[29])
|
||||
access := int(buffer[30])
|
||||
auxType := int(buffer[31]) + int(buffer[32])*256
|
||||
version := buffer[28]
|
||||
minVersion := buffer[29]
|
||||
access := buffer[30]
|
||||
auxType := uint16(buffer[31]) + uint16(buffer[32])*256
|
||||
modifiedTime := DateTimeFromProDOS((buffer[33:37]))
|
||||
headerPointer := int(buffer[0x25]) + int(buffer[0x26])*256
|
||||
headerPointer := uint16(buffer[0x25]) + uint16(buffer[0x26])*256
|
||||
|
||||
fileEntry := FileEntry{
|
||||
StorageType: storageType,
|
||||
@ -427,24 +427,24 @@ func writeFileEntry(writer io.WriterAt, fileEntry FileEntry) {
|
||||
buffer[0x26] = byte(fileEntry.HeaderPointer >> 8)
|
||||
|
||||
//fmt.Printf("Writing file entry at block: %04X offset: %04X\n", fileEntry.DirectoryBlock, fileEntry.DirectoryOffset)
|
||||
_, err := writer.WriteAt(buffer, int64(fileEntry.DirectoryBlock*512+fileEntry.DirectoryOffset))
|
||||
_, err := writer.WriteAt(buffer, int64(fileEntry.DirectoryBlock)*512+int64(fileEntry.DirectoryOffset))
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func parseVolumeHeader(buffer []byte) VolumeHeader {
|
||||
nextBlock := int(buffer[2]) + int(buffer[3])*256
|
||||
nextBlock := uint16(buffer[2]) + uint16(buffer[3])*256
|
||||
filenameLength := buffer[4] & 15
|
||||
volumeName := string(buffer[5 : filenameLength+5])
|
||||
creationTime := DateTimeFromProDOS(buffer[28:32])
|
||||
version := int(buffer[32])
|
||||
minVersion := int(buffer[33])
|
||||
entryLength := int(buffer[35])
|
||||
entriesPerBlock := int(buffer[36])
|
||||
fileCount := int(buffer[37]) + int(buffer[38])*256
|
||||
bitmapBlock := int(buffer[39]) + int(buffer[40])*256
|
||||
totalBlocks := int(buffer[41]) + int(buffer[42])*256
|
||||
version := buffer[32]
|
||||
minVersion := buffer[33]
|
||||
entryLength := buffer[35]
|
||||
entriesPerBlock := buffer[36]
|
||||
fileCount := uint16(buffer[37]) + uint16(buffer[38])*256
|
||||
bitmapBlock := uint16(buffer[39]) + uint16(buffer[40])*256
|
||||
totalBlocks := uint16(buffer[41]) + uint16(buffer[42])*256
|
||||
|
||||
if minVersion > 0 {
|
||||
panic("Unsupported ProDOS version")
|
||||
@ -465,22 +465,22 @@ func parseVolumeHeader(buffer []byte) VolumeHeader {
|
||||
return volumeHeader
|
||||
}
|
||||
|
||||
func parseDirectoryHeader(buffer []byte, blockNumber int) DirectoryHeader {
|
||||
previousBlock := int(buffer[0x00]) + int(buffer[0x01])*256
|
||||
nextBlock := int(buffer[0x02]) + int(buffer[0x03])*256
|
||||
func parseDirectoryHeader(buffer []byte, blockNumber uint16) DirectoryHeader {
|
||||
previousBlock := uint16(buffer[0x00]) + uint16(buffer[0x01])*256
|
||||
nextBlock := uint16(buffer[0x02]) + uint16(buffer[0x03])*256
|
||||
isSubDirectory := (buffer[0x04] & 0xF0) == 0xE0
|
||||
filenameLength := buffer[0x04] & 0x0F
|
||||
name := string(buffer[0x05 : filenameLength+0x05])
|
||||
creationTime := DateTimeFromProDOS(buffer[0x1C:0x20])
|
||||
version := int(buffer[0x20])
|
||||
minVersion := int(buffer[0x21])
|
||||
access := int(buffer[0x22])
|
||||
entryLength := int(buffer[0x23])
|
||||
entriesPerBlock := int(buffer[0x24])
|
||||
fileCount := int(buffer[0x25]) + int(buffer[0x26])*256
|
||||
parentBlock := int(buffer[0x27]) + int(buffer[0x28])*256
|
||||
parentEntry := int(buffer[0x29])
|
||||
parentEntryLength := int(buffer[0x2A])
|
||||
version := buffer[0x20]
|
||||
minVersion := buffer[0x21]
|
||||
access := buffer[0x22]
|
||||
entryLength := buffer[0x23]
|
||||
entriesPerBlock := buffer[0x24]
|
||||
fileCount := uint16(buffer[0x25]) + uint16(buffer[0x26])*256
|
||||
parentBlock := uint16(buffer[0x27]) + uint16(buffer[0x28])*256
|
||||
parentEntry := uint16(buffer[0x29])
|
||||
parentEntryLength := buffer[0x2A]
|
||||
|
||||
directoryEntry := DirectoryHeader{
|
||||
PreviousBlock: previousBlock,
|
||||
|
@ -29,12 +29,12 @@ func LoadFile(reader io.ReaderAt, path string) ([]byte, error) {
|
||||
|
||||
buffer := make([]byte, fileEntry.EndOfFile)
|
||||
|
||||
for i := 0; i < len(blockList); i++ {
|
||||
for i := uint16(0); i < uint16(len(blockList)); i++ {
|
||||
block, err := ReadBlock(reader, blockList[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for j := 0; j < 512 && i*512+j < fileEntry.EndOfFile; j++ {
|
||||
for j := uint16(0); j < 512 && uint32(i)*512+uint32(j) < fileEntry.EndOfFile; j++ {
|
||||
buffer[i*512+j] = block[j]
|
||||
}
|
||||
}
|
||||
@ -43,7 +43,7 @@ func LoadFile(reader io.ReaderAt, path string) ([]byte, error) {
|
||||
}
|
||||
|
||||
// WriteFile writes a file to a ProDOS volume from a byte array
|
||||
func WriteFile(readerWriter ReaderWriterAt, path string, fileType int, auxType int, createdTime time.Time, modifiedTime time.Time, buffer []byte) error {
|
||||
func WriteFile(readerWriter ReaderWriterAt, path string, fileType uint8, auxType uint16, createdTime time.Time, modifiedTime time.Time, buffer []byte) error {
|
||||
directory, fileName := GetDirectoryAndFileNameFromPath(path)
|
||||
|
||||
if len(fileName) > 15 {
|
||||
@ -56,7 +56,7 @@ func WriteFile(readerWriter ReaderWriterAt, path string, fileType int, auxType i
|
||||
}
|
||||
|
||||
// get list of blocks to write file to
|
||||
blockList, err := createBlockList(readerWriter, len(buffer))
|
||||
blockList, err := createBlockList(readerWriter, uint32(len(buffer)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -88,11 +88,11 @@ func WriteFile(readerWriter ReaderWriterAt, path string, fileType int, auxType i
|
||||
return err
|
||||
}
|
||||
fileEntry.FileName = fileName
|
||||
fileEntry.BlocksUsed = len(blockList)
|
||||
fileEntry.BlocksUsed = uint16(len(blockList))
|
||||
fileEntry.CreationTime = createdTime
|
||||
fileEntry.ModifiedTime = modifiedTime
|
||||
fileEntry.AuxType = auxType
|
||||
fileEntry.EndOfFile = len(buffer)
|
||||
fileEntry.EndOfFile = uint32(len(buffer))
|
||||
fileEntry.FileType = fileType
|
||||
fileEntry.KeyPointer = blockList[0]
|
||||
fileEntry.Version = 0x24
|
||||
@ -197,24 +197,24 @@ func GetDirectoryAndFileNameFromPath(path string) (string, string) {
|
||||
return directory, fileName
|
||||
}
|
||||
|
||||
func updateVolumeBitmap(readerWriter ReaderWriterAt, blockList []int) error {
|
||||
func updateVolumeBitmap(readerWriter ReaderWriterAt, blockList []uint16) error {
|
||||
|
||||
volumeBitmap, err := ReadVolumeBitmap(readerWriter)
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
return err
|
||||
}
|
||||
for i := 0; i < len(blockList); i++ {
|
||||
for i := uint16(0); i < uint16(len(blockList)); i++ {
|
||||
markBlockInVolumeBitmap(volumeBitmap, blockList[i])
|
||||
}
|
||||
return writeVolumeBitmap(readerWriter, volumeBitmap)
|
||||
}
|
||||
|
||||
func writeSeedlingFile(writer io.WriterAt, buffer []byte, blockList []int) {
|
||||
func writeSeedlingFile(writer io.WriterAt, buffer []byte, blockList []uint16) {
|
||||
WriteBlock(writer, blockList[0], buffer)
|
||||
}
|
||||
|
||||
func writeSaplingFile(writer io.WriterAt, buffer []byte, blockList []int) {
|
||||
func writeSaplingFile(writer io.WriterAt, buffer []byte, blockList []uint16) {
|
||||
// write index block with pointers to data blocks
|
||||
indexBuffer := make([]byte, 512)
|
||||
for i := 0; i < 256; i++ {
|
||||
@ -249,7 +249,7 @@ func writeSaplingFile(writer io.WriterAt, buffer []byte, blockList []int) {
|
||||
}
|
||||
}
|
||||
|
||||
func writeTreeFile(writer io.WriterAt, buffer []byte, blockList []int) {
|
||||
func writeTreeFile(writer io.WriterAt, buffer []byte, blockList []uint16) {
|
||||
// write master index block with pointers to index blocks
|
||||
indexBuffer := make([]byte, 512)
|
||||
numberOfIndexBlocks := len(blockList)/256 + 1
|
||||
@ -303,17 +303,17 @@ func writeTreeFile(writer io.WriterAt, buffer []byte, blockList []int) {
|
||||
}
|
||||
}
|
||||
|
||||
func getDataBlocklist(reader io.ReaderAt, fileEntry FileEntry) ([]int, error) {
|
||||
func getDataBlocklist(reader io.ReaderAt, fileEntry FileEntry) ([]uint16, error) {
|
||||
return getBlocklist(reader, fileEntry, true)
|
||||
}
|
||||
|
||||
func getAllBlockList(reader io.ReaderAt, fileEntry FileEntry) ([]int, error) {
|
||||
func getAllBlockList(reader io.ReaderAt, fileEntry FileEntry) ([]uint16, error) {
|
||||
return getBlocklist(reader, fileEntry, false)
|
||||
}
|
||||
|
||||
// Returns all blocks, including index blocks
|
||||
func getBlocklist(reader io.ReaderAt, fileEntry FileEntry, dataOnly bool) ([]int, error) {
|
||||
blocks := make([]int, fileEntry.BlocksUsed)
|
||||
func getBlocklist(reader io.ReaderAt, fileEntry FileEntry, dataOnly bool) ([]uint16, error) {
|
||||
blocks := make([]uint16, fileEntry.BlocksUsed)
|
||||
|
||||
switch fileEntry.StorageType {
|
||||
case StorageSeedling:
|
||||
@ -324,10 +324,10 @@ func getBlocklist(reader io.ReaderAt, fileEntry FileEntry, dataOnly bool) ([]int
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockOffset := 1
|
||||
blockOffset := uint16(1)
|
||||
blocks[0] = fileEntry.KeyPointer
|
||||
for i := 0; i < fileEntry.BlocksUsed-1; i++ {
|
||||
blocks[i+blockOffset] = int(index[i]) + int(index[i+256])*256
|
||||
for i := uint16(0); i < fileEntry.BlocksUsed-1; i++ {
|
||||
blocks[i+blockOffset] = uint16(index[i]) + uint16(index[i+256])*256
|
||||
}
|
||||
if dataOnly {
|
||||
return blocks[1:], nil
|
||||
@ -335,10 +335,10 @@ func getBlocklist(reader io.ReaderAt, fileEntry FileEntry, dataOnly bool) ([]int
|
||||
return blocks, nil
|
||||
case StorageTree:
|
||||
// this is actually too large
|
||||
dataBlocks := make([]int, fileEntry.BlocksUsed)
|
||||
dataBlocks := make([]uint16, fileEntry.BlocksUsed)
|
||||
// this is also actually too large
|
||||
numberOfIndexBlocks := fileEntry.BlocksUsed/256 + 2
|
||||
indexBlocks := make([]int, numberOfIndexBlocks)
|
||||
indexBlocks := make([]uint16, numberOfIndexBlocks)
|
||||
masterIndex, err := ReadBlock(reader, fileEntry.KeyPointer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -348,8 +348,8 @@ func getBlocklist(reader io.ReaderAt, fileEntry FileEntry, dataOnly bool) ([]int
|
||||
indexBlocks[0] = fileEntry.KeyPointer
|
||||
indexBlockCount := 1
|
||||
|
||||
for i := 0; i < 128; i++ {
|
||||
indexBlock := int(masterIndex[i]) + int(masterIndex[i+256])*256
|
||||
for i := uint16(0); i < 128; i++ {
|
||||
indexBlock := uint16(masterIndex[i]) + uint16(masterIndex[i+256])*256
|
||||
if indexBlock == 0 {
|
||||
break
|
||||
}
|
||||
@ -359,12 +359,12 @@ func getBlocklist(reader io.ReaderAt, fileEntry FileEntry, dataOnly bool) ([]int
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for j := 0; j < 256 && i*256+j < fileEntry.BlocksUsed; j++ {
|
||||
if (int(index[j]) + int(index[j+256])*256) == 0 {
|
||||
for j := uint16(0); j < 256 && i*256+j < fileEntry.BlocksUsed; j++ {
|
||||
if (uint16(index[j]) + uint16(index[j+256])*256) == 0 {
|
||||
break
|
||||
}
|
||||
numberOfDataBlocks++
|
||||
dataBlocks[i*256+j] = int(index[j]) + int(index[j+256])*256
|
||||
dataBlocks[i*256+j] = uint16(index[j]) + uint16(index[j+256])*256
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,8 +379,8 @@ func getBlocklist(reader io.ReaderAt, fileEntry FileEntry, dataOnly bool) ([]int
|
||||
return nil, errors.New("unsupported file storage type")
|
||||
}
|
||||
|
||||
func createBlockList(reader io.ReaderAt, fileSize int) ([]int, error) {
|
||||
numberOfBlocks := fileSize / 512
|
||||
func createBlockList(reader io.ReaderAt, fileSize uint32) ([]uint16, error) {
|
||||
numberOfBlocks := uint16(fileSize / 512)
|
||||
|
||||
if fileSize%512 > 0 {
|
||||
numberOfBlocks++
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func TestCreateBlocklist(t *testing.T) {
|
||||
var tests = []struct {
|
||||
fileSize int
|
||||
wantBlocks int
|
||||
fileSize uint32
|
||||
wantBlocks uint16
|
||||
}{
|
||||
{1, 1},
|
||||
{512, 1},
|
||||
@ -33,7 +33,7 @@ func TestCreateBlocklist(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error("got error, want nil")
|
||||
}
|
||||
if len(blockList) != tt.wantBlocks {
|
||||
if uint16(len(blockList)) != tt.wantBlocks {
|
||||
t.Errorf("got %d blocks, want %d", len(blockList), tt.wantBlocks)
|
||||
}
|
||||
})
|
||||
@ -41,7 +41,7 @@ func TestCreateBlocklist(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateVolumeBitmap(t *testing.T) {
|
||||
blockList := []int{10, 11, 12, 100, 120}
|
||||
blockList := []uint16{10, 11, 12, 100, 120}
|
||||
|
||||
virtualDisk := NewMemoryFile(0x2000000)
|
||||
CreateVolume(virtualDisk, "VIRTUAL.DISK", 0xFFFE)
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
|
||||
// CreateVolume formats a new ProDOS volume including boot block,
|
||||
// volume bitmap and empty directory
|
||||
func CreateVolume(readerWriter ReaderWriterAt, volumeName string, numberOfBlocks int) {
|
||||
func CreateVolume(readerWriter ReaderWriterAt, volumeName string, numberOfBlocks uint16) {
|
||||
if numberOfBlocks > 65535 || numberOfBlocks < 64 {
|
||||
return
|
||||
}
|
||||
@ -26,7 +26,7 @@ func CreateVolume(readerWriter ReaderWriterAt, volumeName string, numberOfBlocks
|
||||
}
|
||||
|
||||
blankBlock := make([]byte, 512)
|
||||
for i := 0; i < numberOfBlocks; i++ {
|
||||
for i := uint16(0); i < numberOfBlocks; i++ {
|
||||
WriteBlock(readerWriter, i, blankBlock)
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,9 @@ import (
|
||||
|
||||
func TestCreateVolume(t *testing.T) {
|
||||
var tests = []struct {
|
||||
blocks int
|
||||
blocks uint16
|
||||
wantVolumeName string
|
||||
wantFreeBlocks int
|
||||
wantFreeBlocks uint16
|
||||
}{
|
||||
{65535, "MAX", 65513},
|
||||
{65500, "ALMOST.MAX", 65478},
|
||||
|
@ -12,6 +12,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -75,8 +77,8 @@ func AddFilesFromHostDirectory(
|
||||
func WriteFileFromFile(
|
||||
readerWriter ReaderWriterAt,
|
||||
pathName string,
|
||||
fileType int,
|
||||
auxType int,
|
||||
fileType uint8,
|
||||
auxType uint16,
|
||||
modifiedTime time.Time,
|
||||
inFileName string,
|
||||
ignoreDuplicates bool,
|
||||
@ -117,6 +119,11 @@ func WriteFileFromFile(
|
||||
case ".SYS", ".TXT", ".BAS", ".BIN":
|
||||
pathName = strings.TrimSuffix(pathName, ext)
|
||||
}
|
||||
match, err := regexp.MatchString("^\\.(BIN|SYS|TXT|BAS)\\$[0-9]{4}", ext)
|
||||
|
||||
if err == nil && match {
|
||||
pathName = strings.TrimSuffix(pathName, ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,9 +147,12 @@ func WriteFileFromFile(
|
||||
return WriteFile(readerWriter, pathName, fileType, auxType, time.Now(), modifiedTime, inFile)
|
||||
}
|
||||
|
||||
func convertFileByType(inFileName string, inFile []byte) (int, int, []byte, error) {
|
||||
fileType := 0x06 // default to BIN
|
||||
auxType := 0x2000 // default to $2000
|
||||
func convertFileByType(inFileName string, inFile []byte) (uint16, uint8, []byte, error) {
|
||||
var auxType uint16
|
||||
var fileType uint8
|
||||
|
||||
fileType = 0x06 // default to BIN
|
||||
auxType = 0x2000 // default to $2000
|
||||
|
||||
var err error
|
||||
|
||||
@ -166,36 +176,57 @@ func convertFileByType(inFileName string, inFile []byte) (int, int, []byte, erro
|
||||
// Length
|
||||
binary.BigEndian.Uint32(inFile[0x2E:]) == 0x00000008 {
|
||||
|
||||
fileType = int(binary.BigEndian.Uint16(inFile[0x34:]))
|
||||
auxType = int(binary.BigEndian.Uint32(inFile[0x36:]))
|
||||
fileType = uint8(binary.BigEndian.Uint16(inFile[0x34:]))
|
||||
auxType = uint16(binary.BigEndian.Uint32(inFile[0x36:]))
|
||||
inFile = inFile[0x3A:]
|
||||
} else {
|
||||
// use extension to determine file type
|
||||
ext := strings.ToUpper(filepath.Ext(inFileName))
|
||||
|
||||
switch ext {
|
||||
case ".BAS":
|
||||
inFile, err = ConvertTextToBasic(string(inFile))
|
||||
fileType = 0xFC
|
||||
auxType = 0x0801
|
||||
match, err := regexp.MatchString("^\\.(BIN|SYS|TXT|BAS)\\$[0-9]{4}", ext)
|
||||
|
||||
if err == nil && match {
|
||||
parts := strings.Split(ext, "$")
|
||||
extAuxType, err := strconv.ParseUint(parts[1], 16, 16)
|
||||
if err != nil {
|
||||
return 0, 0, nil, err
|
||||
}
|
||||
case ".SYS":
|
||||
fileType = 0xFF
|
||||
auxType = 0x2000
|
||||
case ".BIN":
|
||||
fileType = 0x06
|
||||
auxType = 0x2000
|
||||
case ".TXT":
|
||||
inFile = []byte(strings.ReplaceAll(strings.ReplaceAll(string(inFile), "\r\n", "r"), "\n", "\r"))
|
||||
fileType = 0x04
|
||||
auxType = 0x0000
|
||||
case ".JPG", ".PNG":
|
||||
inFile = ConvertImageToHiResMonochrome(inFile)
|
||||
fileType = 0x06
|
||||
auxType = 0x2000
|
||||
auxType = uint16(extAuxType)
|
||||
switch parts[0] {
|
||||
case ".BAS":
|
||||
fileType = 0xFC
|
||||
case ".SYS":
|
||||
fileType = 0xFF
|
||||
case ".BIN":
|
||||
fileType = 0x06
|
||||
case ".TXT":
|
||||
fileType = 0x04
|
||||
}
|
||||
} else {
|
||||
switch ext {
|
||||
case ".BAS":
|
||||
inFile, err = ConvertTextToBasic(string(inFile))
|
||||
fileType = 0xFC
|
||||
auxType = 0x0801
|
||||
|
||||
if err != nil {
|
||||
return 0, 0, nil, err
|
||||
}
|
||||
case ".SYS":
|
||||
fileType = 0xFF
|
||||
auxType = 0x2000
|
||||
case ".BIN":
|
||||
fileType = 0x06
|
||||
auxType = 0x2000
|
||||
case ".TXT":
|
||||
inFile = []byte(strings.ReplaceAll(strings.ReplaceAll(string(inFile), "\r\n", "r"), "\n", "\r"))
|
||||
fileType = 0x04
|
||||
auxType = 0x0000
|
||||
case ".JPG", ".PNG":
|
||||
inFile = ConvertImageToHiResMonochrome(inFile)
|
||||
fileType = 0x06
|
||||
auxType = 0x2000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ func TimeToString(printTime time.Time) string {
|
||||
}
|
||||
|
||||
// FileTypeToString display the file type as a string
|
||||
func FileTypeToString(fileType int) string {
|
||||
func FileTypeToString(fileType uint8) string {
|
||||
switch fileType {
|
||||
case 1:
|
||||
return "BAD"
|
||||
@ -159,7 +159,7 @@ func DumpBlock(buffer []byte) {
|
||||
}
|
||||
|
||||
// DumpDirectory displays the directory similar to ProDOS catalog
|
||||
func DumpDirectory(blocksFree int, totalBlocks int, path string, fileEntries []FileEntry) {
|
||||
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")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user