diff --git a/disk/diskimagepd.go b/disk/diskimagepd.go index c188bdd..385fc16 100644 --- a/disk/diskimagepd.go +++ b/disk/diskimagepd.go @@ -74,6 +74,10 @@ func (fd *VDH) GetNameLength() int { return int(fd.Data[0] & 0xf) } +func (fd *VDH) SetNameLength(l int) { + fd.Data[0] = (fd.Data[0] & 0xf0) | byte(l&0x0f) +} + func (fd *VDH) GetStorageType() ProDOSStorageType { return ProDOSStorageType((fd.Data[0]) >> 4) } @@ -82,6 +86,21 @@ func (fd *VDH) GetDirName() string { return fd.GetVolumeName() } +func (fd *VDH) SetVolumeName(s string) { + if len(s) > 15 { + s = s[:15] + } + l := len(s) + for i := 0; i < 15; i++ { + if i < l { + fd.Data[1+i] = byte(s[i]) + } else { + fd.Data[1+i] = 0x00 + } + } + fd.SetNameLength(l) +} + func (fd *VDH) GetVolumeName() string { l := fd.GetNameLength() @@ -883,6 +902,20 @@ func (d *DSKWrapper) PRODOSGetVDH(b int) (*VDH, error) { } +func (d *DSKWrapper) PRODOSSetVDH(b int, vdh *VDH) error { + + data, e := d.PRODOSGetBlock(b) + if e != nil { + return e + } + + for i, v := range vdh.Data { + data[4+i] = v + } + + return d.PRODOSWrite(b, data) +} + func (d *DSKWrapper) PRODOSGetCatalogPathed(start int, path string, pattern string) (*VDH, []ProDOSFileDescriptor, error) { path = strings.Trim(path, "/") diff --git a/shell.go b/shell.go index e294175..55d3efb 100644 --- a/shell.go +++ b/shell.go @@ -262,6 +262,20 @@ func init() { "Mounts disk and switches to the new slot", }, }, + "setvolume": &shellCommand{ + Name: "setvolume", + Description: "Sets the ProDOS volume name", + MinArgs: 1, + MaxArgs: 1, + Code: shellVolumeName, + NeedsMount: true, + Context: sccNone, + Text: []string{ + "setvolume ", + "", + "Set ProDOS volume name. Truncated to 15 chars if too long.", + }, + }, "unmount": &shellCommand{ Name: "unmount", Description: "unmount disk image", @@ -820,10 +834,15 @@ func shellCat(args []string) int { } bs := 256 + volumename := "no-name" if info.FormatID.ID == disk.DF_PASCAL || info.FormatID.ID == disk.DF_PRODOS || info.FormatID.ID == disk.DF_PRODOS_800KB || info.FormatID.ID == disk.DF_PRODOS_400KB || info.FormatID.ID == disk.DF_PRODOS_CUSTOM { bs = 512 + vdh, err := commandVolumes[commandTarget].PRODOSGetVDH(2) + if err == nil { + volumename = vdh.GetVolumeName() + } } pattern := "*" @@ -833,6 +852,8 @@ func shellCat(args []string) int { files, _ := globDisk(commandTarget, pattern) + fmt.Printf("Volume Name is %s\n\n", volumename) + fmt.Printf("%-33s %6s %2s %-23s %s\n", "NAME", "BLOCKS", "RO", "KIND", "ADDITONAL") for _, f := range files { add := "" @@ -1042,6 +1063,36 @@ func shellMkdir(args []string) int { } +func shellVolumeName(args []string) int { + + fullpath, _ := filepath.Abs(commandVolumes[commandTarget].Filename) + + _, err := analyze(0, fullpath) + if err != nil { + return 1 + } + + name := strings.ToUpper(args[0]) + + if formatIn(commandVolumes[commandTarget].Format.ID, []disk.DiskFormatID{disk.DF_PRODOS, disk.DF_PRODOS_800KB, disk.DF_PRODOS_400KB, disk.DF_PRODOS_CUSTOM}) { + vdh, err := commandVolumes[commandTarget].PRODOSGetVDH(2) + if err != nil { + fmt.Printf("Failed to get Volume Directory Header: %v\n", err) + return -1 + } + vdh.SetVolumeName(name) + commandVolumes[commandTarget].PRODOSSetVDH(2, vdh) + fmt.Printf("Volume name is now %s\n", vdh.GetVolumeName()) + saveDisk(commandVolumes[commandTarget], fullpath) + } else { + fmt.Println("Do not support setvolume on " + commandVolumes[commandTarget].Format.String() + ".") + return 0 + } + + return 0 + +} + func isASCII(in []byte) bool { for _, v := range in { if v > 128 {