Skip to content

Commit

Permalink
Merge pull request #2 from zellyn/refactor
Browse files Browse the repository at this point in the history
Refactor to use kong instead of cobra
  • Loading branch information
zellyn authored Aug 1, 2021
2 parents 80aa964 + 09ee1c6 commit 7d03624
Show file tree
Hide file tree
Showing 60 changed files with 1,643 additions and 1,740 deletions.
9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"filewatcher.commands": [
{
"match": "\\.go",
"cmd": "echo '${file} changed'",
"event": "onFileChange",
},
]
}
97 changes: 82 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,34 @@ diskii's major disadvantage is that it mostly doesn't exist yet.

It rhymes with “whiskey”.

Discussion/support is in
[#apple2 on the retrocomputing Slack](https://retrocomputing.slack.com/messages/apple2/)
(invites [here](https://retrocomputing.herokuapp.com)).
Discussion/support is on the
[apple2infinitum Slack](https://apple2infinitum.slack.com/)
(invites [here](http://apple2.gs:3000/)).

### Goals
# Examples

Get a listing of files on a DOS 3.3 disk image:
```
diskii ls dos33master.dsk
```

… or a ProDOS disk image:
```
diskii ls ProDOS_2_4_2.po
```

… or a Super-Mon disk image:
```
diskii ls Super-Mon-2.0.dsk
```

Reorder the sectors in a disk image:
```
diskii reorder ProDOS_2_4_2.dsk ProDOS_2_4_2.po
```


# Goals

Eventually, it aims to be a comprehensive disk image manipulation
tool, but for now only some parts work.
Expand All @@ -47,8 +70,8 @@ Current disk operations supported:
| ---------------- | -------- | ------ | ------------------ |
| basic structures ||||
| ls ||||
| dump | || |
| put ||| |
| dump | || |
| put ||| |
| dumptext ||||
| delete ||||
| rename ||||
Expand All @@ -59,7 +82,7 @@ Current disk operations supported:
| init ||||
| defrag ||||

### Installing/updating
# Installing/updating
Assuming you have Go installed, run `go get -u github.com/zellyn/diskii`

You can also download automatically-built binaries from the
Expand All @@ -68,25 +91,24 @@ page](https://github.com/zellyn/diskii/releases/latest). If you
need binaries for a different architecture, please send a pull
request or open an issue.

### Short-term TODOs/roadmap/easy ways to contribute
# Short-term TODOs/roadmap/easy ways to contribute

My rough TODO list (apart from anything marked (✗) in the disk
operations matrix is listed below. Anything that an actual user needs
will be likely to get priority.

- [ ] Make `put` accept load address for appropriate filetypes.
- [ ] Implement `GetFile` for prodos
- [x] Build per-platform binaries for Linux, MacOS, Windows.
- [x] Implement `GetFile` for DOS 3.3
- [ ] Add and implement the `-l` flag for `ls`
- [x] Add `Delete` to the `disk.Operator` interface
- [x] Implement it for Super-Mon
- [ ] Implement it for Super-Mon
- [ ] Implement it for DOS 3.3
- [ ] Make 13-sector DOS disks work
- [ ] Read/write nybble formats
- [ ] Read/write gzipped files
- [ ] Add basic ProDOS structures
- [ ] Add ProDOS support
- [ ] Add ProDOS support for all commands
- [x] Make `filetypes` command use a tabwriter to write as a table

### Related tools
# Related tools

- http://a2ciderpress.com/ - the great grandaddy of them all. Windows only, unless you Wine
- http://retrocomputingaustralia.com/rca-downloads/ Michael Mulhern's MacOS package of CiderPress
Expand All @@ -107,3 +129,48 @@ will be likely to get priority.
- https://github.com/slotek/apple2-disk-util - ruby
- https://github.com/slotek/dsk2nib - C
- https://github.com/robmcmullen/atrcopy - dos3.3, python

# Notes

## Disk formats

- `.do`
- `.po`
- `.dsk` - could be DO or PO. When in doubt, assume DO.

| Physical Sectors | DOS 3.2 Logical | DOS 3.3 Logical | ProDOS/Pascal Logical | CP/M Logical |
|------------------|-----------------|-----------------|-----------------------|------------- |
| 0 | 0 | 0 | 0.0 | 0.0 |
| 1 | 1 | 7 | 4.0 | 2.3 |
| 2 | 2 | E | 0.1 | 1.2 |
| 3 | 3 | 6 | 4.1 | 0.1 |
| 4 | 4 | D | 1.0 | 3.0 |
| 5 | 5 | 5 | 5.0 | 1.3 |
| 6 | 6 | C | 1.1 | 0.2 |
| 7 | 7 | 4 | 5.1 | 3.1 |
| 8 | 8 | B | 2.0 | 2.0 |
| 9 | 9 | 3 | 6.0 | 0.3 |
| A | A | A | 2.1 | 3.2 |
| B | B | 2 | 6.1 | 2.1 |
| C | C | 9 | 3.0 | 1.0 |
| D | | 1 | 7.0 | 3.3 |
| E | | 8 | 3.1 | 2.2 |
| F | | F | 7.1 | 1.1 |

_Note: DOS 3.2 rearranged the physical sectors on disk to achieve interleaving._
### RWTS - DOS

Sector mapping:
http://www.textfiles.com/apple/ANATOMY/rwts.s.txt and search for INTRLEAV

Mapping from specified sector to physical sector:

`00 0D 0B 09 07 05 03 01 0E 0C 0A 08 06 04 02 0F`

So if you write to "T0S1" with DOS RWTS, it ends up in physical sector 0D.

## Commandline examples for thinking about how it should work

diskii ls dos33.dsk
diskii --order=do ls dos33.dsk
diskii --order=do --system=nakedos ls nakedos.dsk
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package applesoft
import (
"testing"

"github.com/zellyn/diskii/lib/basic"
"github.com/zellyn/diskii/basic"
)

// helloBinary is a simple basic program used for testing. Listing
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package integer
import (
"testing"

"github.com/zellyn/diskii/lib/basic"
"github.com/zellyn/diskii/basic"
)

// helloBinary is a simple basic program used for testing. Listing
Expand Down
57 changes: 57 additions & 0 deletions build
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -euo pipefail
export ACME="$HOME/gh/acme/ACME_Lib"
ACME_BIN="$HOME/gh/acme/acme"


$ACME_BIN -o writetest.o -r writetest.lst writetest.asm

# cp data/disks/dos33mst.dsk writetest.dsk
# diskii put -f writetest.dsk writetest writetest.o

# Also run mame? (set MAMEDIR and MAMEBIN to your local variant)
[[ -z "${MAMEDIR-}" ]] && MAMEDIR="/Users/zellyn/Library/Application Support/Ample"
[[ -z "${MAMEBIN-}" ]] && MAMEBIN="/Applications/Ample.app/Contents/MacOS/mame64"

# Write audit.o into an OpenEmulator config?
[[ -z "${TMPLS-}" ]] && TMPLS=~/gh/OpenEmulator-OSX/modules/libemulation/res/templates

DSK=$(realpath ./audit.dsk)

case "${1-none}" in
"2ee")
# mame64 apple2ee -skip_gameinfo -nosamples -window -resolution 1120x840 -flop1 /Users/zellyn/gh/a2audit/audit/audit.dsk
(cd "$MAMEDIR"; "$MAMEBIN" apple2ee -window -flop1 "$DSK" -skip_gameinfo)
;;
"2e")
(cd "$MAMEDIR"; "$MAMEBIN" apple2e -window -flop1 "$DSK" -skip_gameinfo)
;;
"2p")
(cd "$MAMEDIR"; "$MAMEBIN" apple2p -window -flop1 "$DSK" -skip_gameinfo)
;;
"2")
(cd "$MAMEDIR"; "$MAMEBIN" apple2 -window -flop1 "$DSK" -skip_gameinfo)
;;
"2ee-d")
(cd "$MAMEDIR"; "$MAMEBIN" apple2ee -window -flop1 "$DSK" -skip_gameinfo -debug)
;;
"2e-d")
(cd "$MAMEDIR"; "$MAMEBIN" apple2e -window -flop1 "$DSK" -skip_gameinfo -debug)
;;
"2p-d")
(cd "$MAMEDIR"; "$MAMEBIN" apple2p -window -flop1 "$DSK" -skip_gameinfo -debug)
;;
"2-d")
(cd "$MAMEDIR"; "$MAMEBIN" apple2 -window -flop1 "$DSK" -skip_gameinfo -debug)
;;
"oe")
(head -c 24576 /dev/zero; cat audit.o; head -c 65536 /dev/zero) | head -c 65536 > $TMPLS/Apple\ II/Apple\ IIe-test.emulation/appleIIe.mainRam.bin
sed -e 's|<property name="pc" value="0x...."/>|<property name="pc" value="0x6000"/>|' $TMPLS/Apple\ II/Apple\ IIe.xml > $TMPLS/Apple\ II/Apple\ IIe-test.emulation/info.xml
;;
"none")
;;
*)
echo Options: 2ee, 2e, 2p, 2, 2ee-d, 2e-d, 2p-d, 2-d
esac

true # Signal success (since we had a bunch of conditionals that can return false status).
82 changes: 18 additions & 64 deletions cmd/applesoft.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,87 +3,41 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/zellyn/diskii/lib/basic"
"github.com/zellyn/diskii/lib/basic/applesoft"
"github.com/zellyn/diskii/lib/helpers"
"github.com/zellyn/diskii/basic"
"github.com/zellyn/diskii/basic/applesoft"
"github.com/zellyn/diskii/helpers"
"github.com/zellyn/diskii/types"
)

// applesoftCmd represents the applesoft command
var applesoftCmd = &cobra.Command{
Use: "applesoft",
Short: "work with applesoft programs",
Long: `diskii applesoft contains the subcommands useful for working
with Applesoft programs.`,
type ApplesoftCmd struct {
Decode DecodeCmd `kong:"cmd,help='Convert a binary Applesoft program to a text LISTing.'"`
}

func init() {
RootCmd.AddCommand(applesoftCmd)
type DecodeCmd struct {
Filename string `kong:"arg,default='-',type='existingfile',help='Binary Applesoft file to read, or “-” for stdin.'"`

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// applesoftCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// applesoftCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
Location uint16 `kong:"type='anybaseuint16',default='0x801',help='Starting program location in memory.'"`
Raw bool `kong:"short='r',help='Print raw control codes (no escaping)'"`
}

// ----- applesoft decode command -------------------------------------------

var location uint16 // flag for starting location in memory
var rawControlCodes bool // flag for whether to skip escaping control codes

// decodeCmd represents the decode command
var decodeCmd = &cobra.Command{
Use: "decode filename",
Short: "convert a binary applesoft program to a LISTing",
Long: `
decode converts a binary Applesoft program to a text LISTing.
Examples:
decode filename # read filename
decode - # read stdin`,
Run: func(cmd *cobra.Command, args []string) {
if err := runDecode(args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(-1)
}
},
func (d DecodeCmd) Help() string {
return `Examples:
# Dump the contents of HELLO and then decode it.
diskii dump dos33master.dsk HELLO | diskii applesoft decode -`
}

func init() {
applesoftCmd.AddCommand(decodeCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// decodeCmd.PersistentFlags().String("foo", "", "A help for foo")

decodeCmd.Flags().Uint16VarP(&location, "location", "l", 0x801, "Starting program location in memory")
decodeCmd.Flags().BoolVarP(&rawControlCodes, "raw", "r", false, "Print raw control codes (no escaping)")
}

// runDecode performs the actual decode logic.
func runDecode(args []string) error {
if len(args) != 1 {
return fmt.Errorf("decode expects one argument: the filename (or - for stdin)")
}
contents, err := helpers.FileContentsOrStdIn(args[0])
func (d *DecodeCmd) Run(globals *types.Globals) error {
contents, err := helpers.FileContentsOrStdIn(d.Filename)
if err != nil {
return err
}
listing, err := applesoft.Decode(contents, location)
listing, err := applesoft.Decode(contents, d.Location)
if err != nil {
return err
}
if rawControlCodes {
if d.Raw {
os.Stdout.WriteString(listing.String())
} else {
os.Stdout.WriteString(basic.ChevronControlCodes(listing.String()))
Expand Down
Loading

0 comments on commit 7d03624

Please sign in to comment.