Autodetect diskette file format
This commit is contained in:
parent
b9f893f96b
commit
5847a0f8a5
|
@ -105,9 +105,7 @@ func (a *Apple2) AddDisk2(slot int, diskRomFile string, diskImage string) error
|
||||||
a.insertCard(&c, slot)
|
a.insertCard(&c, slot)
|
||||||
|
|
||||||
if diskImage != "" {
|
if diskImage != "" {
|
||||||
//diskette, err := loadDisquette(diskImage)
|
diskette, err := loadDisquette(diskImage)
|
||||||
//diskette, err := loadDisquetteTimed(diskImage)
|
|
||||||
diskette, err := loadDisquetteWoz(diskImage)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,13 +39,6 @@ type cardDisk2Drive struct {
|
||||||
tracksStep int // Stepmotor for tracks position. 4 steps per track
|
tracksStep int // Stepmotor for tracks position. 4 steps per track
|
||||||
}
|
}
|
||||||
|
|
||||||
type diskette interface {
|
|
||||||
powerOn(cycle uint64)
|
|
||||||
powerOff(cycle uint64)
|
|
||||||
read(quarterTrack int, cycle uint64) uint8
|
|
||||||
write(quarterTrack int, value uint8, cycle uint64)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
diskBitCycle = 4 // There is a dataLatch bit transferred every 4 cycles
|
diskBitCycle = 4 // There is a dataLatch bit transferred every 4 cycles
|
||||||
diskLatchReadCycles = 7 // Loaded data is available for a little more than 7ns
|
diskLatchReadCycles = 7 // Loaded data is available for a little more than 7ns
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package apple2
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
type diskette interface {
|
||||||
|
powerOn(cycle uint64)
|
||||||
|
powerOff(cycle uint64)
|
||||||
|
read(quarterTrack int, cycle uint64) uint8
|
||||||
|
write(quarterTrack int, value uint8, cycle uint64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadDisquette(filename string) (diskette, error) {
|
||||||
|
data, err := loadResource(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if isFileNibOrDsk(data) {
|
||||||
|
f, err := newFileNibOrDsk(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var d diskette16sector
|
||||||
|
d.nib = f
|
||||||
|
return &d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if isFileWoz(data) {
|
||||||
|
f, err := newFileWoz(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return newDisquetteWoz(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("Diskette format not supported")
|
||||||
|
}
|
|
@ -11,6 +11,12 @@ type diskette16sector struct {
|
||||||
position int
|
position int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newDisquette16Sector(f *fileNib) *diskette16sector {
|
||||||
|
var d diskette16sector
|
||||||
|
d.nib = f
|
||||||
|
return &d
|
||||||
|
}
|
||||||
|
|
||||||
func (d *diskette16sector) powerOn(cycle uint64) {
|
func (d *diskette16sector) powerOn(cycle uint64) {
|
||||||
// Not used
|
// Not used
|
||||||
}
|
}
|
||||||
|
@ -31,14 +37,3 @@ func (d *diskette16sector) write(quarterTrack int, value uint8, _ uint64) {
|
||||||
d.nib.track[track][d.position] = value
|
d.nib.track[track][d.position] = value
|
||||||
d.position = (d.position + 1) % nibBytesPerTrack
|
d.position = (d.position + 1) % nibBytesPerTrack
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDisquette(filename string) (*diskette16sectorTimed, error) {
|
|
||||||
var d diskette16sectorTimed
|
|
||||||
|
|
||||||
f, err := loadNibOrDsk(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
d.nib = f
|
|
||||||
return &d, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,6 +5,12 @@ type diskette16sectorTimed struct {
|
||||||
cycleOn uint64 // Cycle when the disk was last turned on
|
cycleOn uint64 // Cycle when the disk was last turned on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newDisquette16SectorTimed(f *fileNib) *diskette16sectorTimed {
|
||||||
|
var d diskette16sectorTimed
|
||||||
|
d.nib = f
|
||||||
|
return &d
|
||||||
|
}
|
||||||
|
|
||||||
func (d *diskette16sectorTimed) powerOn(cycle uint64) {
|
func (d *diskette16sectorTimed) powerOn(cycle uint64) {
|
||||||
d.cycleOn = cycle
|
d.cycleOn = cycle
|
||||||
}
|
}
|
||||||
|
@ -38,15 +44,3 @@ func (d *diskette16sectorTimed) read(quarterTrack int, cycle uint64) uint8 {
|
||||||
func (d *diskette16sectorTimed) write(quarterTrack int, value uint8, _ uint64) {
|
func (d *diskette16sectorTimed) write(quarterTrack int, value uint8, _ uint64) {
|
||||||
panic("Write not implemented on time based disk implementation")
|
panic("Write not implemented on time based disk implementation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDisquetteTimed(filename string) (*diskette16sectorTimed, error) {
|
|
||||||
var d diskette16sectorTimed
|
|
||||||
|
|
||||||
f, err := loadNibOrDsk(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
d.nib = f
|
|
||||||
|
|
||||||
return &d, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package apple2
|
package apple2
|
||||||
|
|
||||||
import "math/rand"
|
import (
|
||||||
|
"errors"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
See:
|
See:
|
||||||
|
@ -32,7 +35,10 @@ Emulation status for the disk used on the reference:
|
||||||
- What is the lifespan of the data latch?
|
- What is the lifespan of the data latch?
|
||||||
- *** First Math Adventures - Understanding Word Problems
|
- *** First Math Adventures - Understanding Word Problems
|
||||||
- Reading Offset Data Streams
|
- Reading Offset Data Streams
|
||||||
- Border Zone: Unknown, there is no UI to swap disks
|
- *** Wings of Fury: Not working
|
||||||
|
- Stickybear Town Builder: Working
|
||||||
|
- Optimal bit timing of WOZ 2,0
|
||||||
|
- * Border Zone: Unknown, there is no UI to swap disks
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -52,6 +58,20 @@ type disketteWoz struct {
|
||||||
visibleLatchCountDown int8 // The visible latch stores a valid latch reading for 2 bit timings
|
visibleLatchCountDown int8 // The visible latch stores a valid latch reading for 2 bit timings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newDisquetteWoz(f *fileWoz) (*disketteWoz, error) {
|
||||||
|
// Discard not supported features
|
||||||
|
if f.info.DiskType != 1 {
|
||||||
|
return nil, errors.New("Only 5.25 disks are supported")
|
||||||
|
}
|
||||||
|
if f.info.BootSectorFormat == 2 { // Info not available in WOZ 1.0
|
||||||
|
return nil, errors.New("Woz 13 sector disks are not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
var d disketteWoz
|
||||||
|
d.data = f
|
||||||
|
return &d, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *disketteWoz) powerOn(cycle uint64) {
|
func (d *disketteWoz) powerOn(cycle uint64) {
|
||||||
d.turning = true
|
d.turning = true
|
||||||
d.cycleOn = cycle
|
d.cycleOn = cycle
|
||||||
|
@ -107,15 +127,3 @@ func (d *disketteWoz) read(quarterTrack int, cycle uint64) uint8 {
|
||||||
func (d *disketteWoz) write(quarterTrack int, value uint8, _ uint64) {
|
func (d *disketteWoz) write(quarterTrack int, value uint8, _ uint64) {
|
||||||
panic("Write not implemented on woz disk implementation")
|
panic("Write not implemented on woz disk implementation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDisquetteWoz(filename string) (*disketteWoz, error) {
|
|
||||||
var d disketteWoz
|
|
||||||
|
|
||||||
f, err := loadFileWoz(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
d.data = f
|
|
||||||
|
|
||||||
return &d, nil
|
|
||||||
}
|
|
||||||
|
|
16
fileNib.go
16
fileNib.go
|
@ -27,13 +27,23 @@ type fileNib struct {
|
||||||
track [numberOfTracks][]byte
|
track [numberOfTracks][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadNibOrDsk(filename string) (*fileNib, error) {
|
func loadFileNibOrDsk(filename string) (*fileNib, error) {
|
||||||
var f fileNib
|
|
||||||
|
|
||||||
data, err := loadResource(filename)
|
data, err := loadResource(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newFileNibOrDsk(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFileNibOrDsk(data []uint8) bool {
|
||||||
|
size := len(data)
|
||||||
|
return size == nibImageSize || size == dskImageSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFileNibOrDsk(data []uint8) (*fileNib, error) {
|
||||||
|
var f fileNib
|
||||||
|
|
||||||
size := len(data)
|
size := len(data)
|
||||||
|
|
||||||
if size == nibImageSize {
|
if size == nibImageSize {
|
||||||
|
|
27
fileWoz.go
27
fileWoz.go
|
@ -87,13 +87,28 @@ func (f *fileWoz) getBit(position uint32, quarterTrack int) uint8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadFileWoz(filename string) (*fileWoz, error) {
|
func loadFileWoz(filename string) (*fileWoz, error) {
|
||||||
var f fileWoz
|
|
||||||
|
|
||||||
data, err := loadResource(filename)
|
data, err := loadResource(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newFileWoz(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFileWoz(data []uint8) bool {
|
||||||
|
header := data[:len(headerWoz2)]
|
||||||
|
if bytes.Equal(headerWoz1, header) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if bytes.Equal(headerWoz2, header) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFileWoz(data []uint8) (*fileWoz, error) {
|
||||||
|
var f fileWoz
|
||||||
|
|
||||||
// Verify header. Note, the CRC is not verified
|
// Verify header. Note, the CRC is not verified
|
||||||
header := data[:len(headerWoz2)]
|
header := data[:len(headerWoz2)]
|
||||||
if bytes.Equal(headerWoz1, header) {
|
if bytes.Equal(headerWoz1, header) {
|
||||||
|
@ -192,14 +207,6 @@ func loadFileWoz(filename string) (*fileWoz, error) {
|
||||||
return nil, errors.New("Woz version not supported")
|
return nil, errors.New("Woz version not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard not supported features
|
|
||||||
if f.info.DiskType != 1 {
|
|
||||||
return nil, errors.New("Only 5.25 disks are supported")
|
|
||||||
}
|
|
||||||
if f.info.BootSectorFormat == 2 { // Info not available in WOZ 1.0
|
|
||||||
return nil, errors.New("Woz 13 sector disks are not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &f, nil
|
return &f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue