mirror of
https://github.com/tjboldt/Apple2-IO-RPi.git
synced 2024-12-17 14:30:17 +00:00
Add live drive regeneration and loading (#122)
This commit is contained in:
parent
841b11f9ae
commit
b10dec3e50
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -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)
|
||||
|
36
RaspberryPi/apple2driver/drive/drive.go
Normal file
36
RaspberryPi/apple2driver/drive/drive.go
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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=
|
||||
|
@ -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))
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user