Autodetect diskette file format

This commit is contained in:
Ivan Izaguirre 2019-12-22 14:15:19 +01:00 committed by Iván Izaguirre
parent b9f893f96b
commit 5847a0f8a5
8 changed files with 103 additions and 60 deletions

View File

@ -105,9 +105,7 @@ func (a *Apple2) AddDisk2(slot int, diskRomFile string, diskImage string) error
a.insertCard(&c, slot)
if diskImage != "" {
//diskette, err := loadDisquette(diskImage)
//diskette, err := loadDisquetteTimed(diskImage)
diskette, err := loadDisquetteWoz(diskImage)
diskette, err := loadDisquette(diskImage)
if err != nil {
return err
}

View File

@ -39,13 +39,6 @@ type cardDisk2Drive struct {
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 (
diskBitCycle = 4 // There is a dataLatch bit transferred every 4 cycles
diskLatchReadCycles = 7 // Loaded data is available for a little more than 7ns

38
diskette.go Normal file
View File

@ -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")
}

View File

@ -11,6 +11,12 @@ type diskette16sector struct {
position int
}
func newDisquette16Sector(f *fileNib) *diskette16sector {
var d diskette16sector
d.nib = f
return &d
}
func (d *diskette16sector) powerOn(cycle uint64) {
// Not used
}
@ -31,14 +37,3 @@ func (d *diskette16sector) write(quarterTrack int, value uint8, _ uint64) {
d.nib.track[track][d.position] = value
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
}

View File

@ -5,6 +5,12 @@ type diskette16sectorTimed struct {
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) {
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) {
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
}

View File

@ -1,6 +1,9 @@
package apple2
import "math/rand"
import (
"errors"
"math/rand"
)
/*
See:
@ -32,7 +35,10 @@ Emulation status for the disk used on the reference:
- What is the lifespan of the data latch?
- *** First Math Adventures - Understanding Word Problems
- 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
}
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) {
d.turning = true
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) {
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
}

View File

@ -27,13 +27,23 @@ type fileNib struct {
track [numberOfTracks][]byte
}
func loadNibOrDsk(filename string) (*fileNib, error) {
var f fileNib
func loadFileNibOrDsk(filename string) (*fileNib, error) {
data, err := loadResource(filename)
if err != nil {
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)
if size == nibImageSize {

View File

@ -87,13 +87,28 @@ func (f *fileWoz) getBit(position uint32, quarterTrack int) uint8 {
}
func loadFileWoz(filename string) (*fileWoz, error) {
var f fileWoz
data, err := loadResource(filename)
if err != nil {
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
header := data[:len(headerWoz2)]
if bytes.Equal(headerWoz1, header) {
@ -192,14 +207,6 @@ func loadFileWoz(filename string) (*fileWoz, error) {
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
}