Add live drive regeneration and loading (#122)

This commit is contained in:
Terence Boldt 2023-01-25 22:32:47 -05:00 committed by GitHub
parent 841b11f9ae
commit b10dec3e50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 106 additions and 45 deletions

View File

@ -49,6 +49,7 @@ body:
label: Driver Version
description: What version of the driver are you running? Check with `RPI a2version`
options:
- 0028 (add live drive loading and regeneration)
- 0027 (add dynamic drive support)
- 0026 (add error handling)
- 0025 (update RPi.command)

View File

@ -0,0 +1,36 @@
// Copyright Terence J. Boldt (c)2023
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
// This file is used for handling ProDOS image generation
package drive
import (
"fmt"
"os"
"path/filepath"
"github.com/tjboldt/ProDOS-Utilities/prodos"
)
// GetDriveImageDirectory gets the default directory for driveimage
func GetDriveImageDirectory() (string, error) {
exec, err := os.Executable()
if err != nil {
fmt.Printf("ERROR: %s", err.Error())
return "", err
}
driveImageDirectory := filepath.Join(filepath.Dir(filepath.Dir(exec)), "driveimage")
return driveImageDirectory, nil
}
// GenerateDriveFromDirectory regenerates a ProDOS drive from a host directory
func GenerateDriveFromDirectory(volumeName string, directory string) (prodos.ReaderWriterAt, error) {
drive := prodos.NewMemoryFile(0x2000000)
fmt.Printf("Generating Drive in memory from: %s\n", directory)
prodos.CreateVolume(drive, volumeName, 65535)
err := prodos.AddFilesFromHostDirectory(drive, directory, "/"+volumeName+"/", true)
return drive, err
}

View File

@ -16,6 +16,7 @@ import (
"time"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/drive"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/handlers"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/info"
"github.com/tjboldt/ProDOS-Utilities/prodos"
@ -48,8 +49,6 @@ func main() {
// In case Apple II is waiting, send 0 byte to start
comm.WriteByte(0)
cwd, _ := os.Getwd()
for {
command, err := comm.ReadByte()
if err == nil {
@ -58,25 +57,13 @@ func main() {
case resetCommand:
handlers.ResetCommand()
case readBlockCommand:
var block int
block, err = handlers.ReadBlockCommand(drive1, drive2)
if err == nil && block == 0 && len(drive1Name) == 0 {
resetCwd()
drive1, _ = generateDriveFromCwd()
}
handlers.ReadBlockCommand(drive1, drive2)
case writeBlockCommand:
handlers.WriteBlockCommand(drive1, drive2)
case getTimeCommand:
handlers.GetTimeCommand()
case execCommand:
handlers.ExecCommand()
newCwd, _ := os.Getwd()
if newCwd != cwd {
cwd = newCwd
if len(drive1Name) == 0 {
drive1, _ = generateDriveFromCwd()
}
}
handlers.ExecCommand(&drive1, &drive2)
case loadFileCommand:
handlers.LoadFileCommand()
case menuCommand:
@ -117,7 +104,9 @@ func getDriveFiles(drive1Name string, drive2Name string) (prodos.ReaderWriterAt,
drive1, err = os.OpenFile(drive1Name, os.O_RDWR, 0755)
logAndExitOnErr(err)
} else {
drive1, err = generateDriveFromCwd()
directory, err := drive.GetDriveImageDirectory()
logAndExitOnErr(err)
drive1, err = drive.GenerateDriveFromDirectory("APPLE2.IO.RPI", directory)
logAndExitOnErr(err)
}
@ -136,26 +125,3 @@ func logAndExitOnErr(err error) {
os.Exit(1)
}
}
func resetCwd() {
exec, err := os.Executable()
if err != nil {
fmt.Printf("ERROR: %s", err.Error())
os.Exit(1)
}
cwd := filepath.Dir(exec)
err = os.Chdir(filepath.Join(cwd, "../driveimage"))
logAndExitOnErr(err)
}
func generateDriveFromCwd() (prodos.ReaderWriterAt, error) {
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
drive := prodos.NewMemoryFile(0x2000000)
fmt.Printf("Generating Drive in memory from: %s\n", cwd)
prodos.CreateVolume(drive, "APPLE2.IO.RPI", 65535)
err = prodos.AddFilesFromHostDirectory(drive, cwd)
return drive, err
}

View File

@ -5,5 +5,5 @@ go 1.16
require (
github.com/creack/pty v1.1.18
github.com/stianeikeland/go-rpio/v4 v4.6.0
github.com/tjboldt/ProDOS-Utilities v0.4.3
github.com/tjboldt/ProDOS-Utilities v0.4.5
)

View File

@ -2,8 +2,8 @@ github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/stianeikeland/go-rpio/v4 v4.6.0 h1:eAJgtw3jTtvn/CqwbC82ntcS+dtzUTgo5qlZKe677EY=
github.com/stianeikeland/go-rpio/v4 v4.6.0/go.mod h1:A3GvHxC1Om5zaId+HqB3HKqx4K/AqeckxB7qRjxMK7o=
github.com/tjboldt/ProDOS-Utilities v0.4.3 h1:uNC3LYO0hlForL1pxbXny1Fbk39jj6MPWjDollcApFo=
github.com/tjboldt/ProDOS-Utilities v0.4.3/go.mod h1:4D1GnCj155VTpP07052zoMN8Xa4wVpVWa+ZTBFQdtI4=
github.com/tjboldt/ProDOS-Utilities v0.4.5 h1:XT2WCUnqcaLQwBca6fn7kxcQANWxYn5YpM618ERbCUY=
github.com/tjboldt/ProDOS-Utilities v0.4.5/go.mod h1:4D1GnCj155VTpP07052zoMN8Xa4wVpVWa+ZTBFQdtI4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=

View File

@ -16,14 +16,16 @@ import (
"strings"
"time"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/drive"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/info"
"github.com/tjboldt/ProDOS-Utilities/prodos"
)
var forceLowercase = false
var execTimeoutSeconds = int(10)
// ExecCommand handles requests for the Apple II executing Linux commands
func ExecCommand() {
func ExecCommand(drive1 *prodos.ReaderWriterAt, drive2 *prodos.ReaderWriterAt) {
workingDirectory, err := os.Getwd()
if err != nil {
workingDirectory = "/home"
@ -74,6 +76,10 @@ func ExecCommand() {
a2timeout(linuxCommand)
return
}
if strings.HasPrefix(linuxCommand, "a2drive") {
a2drive(linuxCommand, drive1, drive2)
return
}
if linuxCommand == "a2prompt" {
prompt := fmt.Sprintf("A2IO:%s ", workingDirectory)
comm.WriteString(prompt)
@ -160,6 +166,7 @@ func a2help() {
"a2timeout - seconds to timeout commands\r" +
"A2LOWER - force lowercase for II+\r" +
"a2lower - disable force lowercase\r" +
"a2drive - change drive images\r" +
"\r")
}
@ -182,6 +189,57 @@ func a2timeout(linuxCommand string) {
}
}
func a2drive(linuxCommand string, drive1 *prodos.ReaderWriterAt, drive2 *prodos.ReaderWriterAt) {
params := strings.Fields(linuxCommand)
if len(params) < 3 {
showa2DriveUsage()
return
}
driveNumber, err := strconv.ParseInt(params[1], 10, 32)
if err != nil {
comm.WriteString("\rFailed to parse drive number\r")
showa2DriveUsage()
return
}
if params[2] == "regen" {
directory, err := drive.GetDriveImageDirectory()
if err != nil {
comm.WriteString("\rFailed to parse source directory\r")
return
}
if len(params) > 3 {
directory = params[3]
}
switch driveNumber {
case 1:
*drive1, err = drive.GenerateDriveFromDirectory("APPLE2.IO.RPI", directory)
if err != nil {
comm.WriteString("\rFailed to regenerate drive 1\r")
return
}
comm.WriteString("\rDrive 1 regenerated\r")
case 2:
*drive2, err = drive.GenerateDriveFromDirectory("APPLE2.IO.RPI2", directory)
if err != nil {
comm.WriteString("\rFailed to regenerate drive 2\r")
return
}
comm.WriteString("\rDrive 2 regenerated\r")
default:
comm.WriteString("\rOnly drives 1 or 2 are supported\r")
showa2DriveUsage()
return
}
}
}
func showa2DriveUsage() {
comm.WriteString("\rUsage: a2drive DRIVENUMBER [regen [PATH] | load FILENAME]\rExamples: a2drive 1 regen ~/Apple2-IO-RPi/RaspberryPi/driveimage\r a2drive 2 load /home/pi/Games.hdv\r")
}
func a2lower(enable bool) {
forceLowercase = enable
comm.WriteString(fmt.Sprintf("All commands will be converted to lowercase: %t\r", forceLowercase))

View File

@ -8,4 +8,4 @@ package info
// Version is the hexadecimal version number that
// should be incremented with each driver update
const Version = "0027"
const Version = "0028"