Support PO ProDOS ordered disk files

This commit is contained in:
Ivan Izaguirre 2020-06-06 14:10:27 +02:00
parent 6e25111224
commit 48afaa471b
3 changed files with 51 additions and 42 deletions

View File

@ -12,8 +12,7 @@ Portable emulator of an Apple II+ or //e. Written in Go.
- Apple //e enhanced with 128Kb of RAM
- Base64A clone with 48Kb of base RAM and paginated ROM
- Storage
- 16 Sector diskettes in NIB format
- 16 Sector diskettes in DSK format
- 16 Sector diskettes in NIB, DSK or PO format
- 16 Sector diskettes in WOZ 1.0 or 2.0 format (read only)
- Hard disk with ProDOS and SmartPort support
- Emulated extension cards:
@ -46,6 +45,7 @@ Portable emulator of an Apple II+ or //e. Written in Go.
- Adjustable speed.
- Fast disk mode to set max speed while using the disks.
- Single file executable with embedded ROMs and DOS 3.3
- Pause (thanks a2geek)
## Running the emulator

View File

@ -1,6 +1,9 @@
package apple2
import "errors"
import (
"errors"
"strings"
)
type diskette interface {
powerOn(cycle uint64)
@ -15,13 +18,16 @@ func loadDisquette(filename string) (diskette, error) {
return nil, err
}
if isFileNibOrDsk(data) {
f, err := newFileNibOrDsk(data)
if err != nil {
return nil, err
}
if isFileNib(data) {
var d diskette16sector
d.nib = f
d.nib = newFileNib(data)
return &d, nil
}
if isFileDsk(data) {
isPO := strings.HasSuffix(strings.ToLower(filename), "po")
var d diskette16sector
d.nib = newFileDsk(data, isPO)
return &d, nil
}

View File

@ -1,7 +1,6 @@
package apple2
import (
"errors"
"os"
)
@ -27,41 +26,38 @@ type fileNib struct {
track [numberOfTracks][]byte
}
func loadFileNibOrDsk(filename string) (*fileNib, error) {
data, err := loadResource(filename)
if err != nil {
return nil, err
}
return newFileNibOrDsk(data)
func isFileNib(data []uint8) bool {
return len(data) == nibImageSize
}
func isFileNibOrDsk(data []uint8) bool {
size := len(data)
return size == nibImageSize || size == dskImageSize
}
func newFileNibOrDsk(data []uint8) (*fileNib, error) {
func newFileNib(data []uint8) *fileNib {
var f fileNib
size := len(data)
if size == nibImageSize {
// Load file already in nib format
for i := 0; i < numberOfTracks; i++ {
f.track[i] = data[nibBytesPerTrack*i : nibBytesPerTrack*(i+1)]
}
} else if size == dskImageSize {
// Convert to nib
for i := 0; i < numberOfTracks; i++ {
trackData := data[i*bytesPerTrack : (i+1)*bytesPerTrack]
f.track[i] = nibEncodeTrack(trackData, defaultVolumeTag, byte(i))
}
} else {
return nil, errors.New("Invalid disk size")
for i := 0; i < numberOfTracks; i++ {
f.track[i] = data[nibBytesPerTrack*i : nibBytesPerTrack*(i+1)]
}
return &f, nil
return &f
}
func isFileDsk(data []uint8) bool {
return len(data) == dskImageSize
}
func newFileDsk(data []uint8, isPO bool) *fileNib {
var f fileNib
logicalOrder := dos33SectorsLogicalOrder
if isPO {
logicalOrder = prodosSectorsLogicalOrder
}
for i := 0; i < numberOfTracks; i++ {
trackData := data[i*bytesPerTrack : (i+1)*bytesPerTrack]
f.track[i] = nibEncodeTrack(trackData, defaultVolumeTag, byte(i), &logicalOrder)
}
return &f
}
func (f *fileNib) saveNib(filename string) error {
@ -81,11 +77,18 @@ func (f *fileNib) saveNib(filename string) error {
return nil
}
var dos33SectorsLogicOrder = [16]int{
// See Beneath Apple DOS, figure 3.24
var dos33SectorsLogicalOrder = [16]int{
0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4,
0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF,
}
// See Beneath Apple ProDOS, figure 3.1
var prodosSectorsLogicalOrder = [16]int{
0x0, 0x8, 0x1, 0x9, 0x2, 0xA, 0x3, 0xB,
0x4, 0xC, 0x5, 0xD, 0x6, 0xE, 0x7, 0xF,
}
var sixAndTwoTranslateTable = [0x40]byte{
0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6,
0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3,
@ -118,7 +121,7 @@ func oddEvenEncodeByte(b byte) []byte {
return e
}
func nibEncodeTrack(data []byte, volume byte, track byte) []byte {
func nibEncodeTrack(data []byte, volume byte, track byte, logicalOrder *[16]int) []byte {
b := make([]byte, 0, nibBytesPerTrack) // Buffer slice with enough capacity
// Initialize gaps to be copied for each sector
gap1 := make([]byte, gap1Len)
@ -134,7 +137,7 @@ func nibEncodeTrack(data []byte, volume byte, track byte) []byte {
but on the physical encoded track as well as in the nib
files they are in phisical order.
*/
logicalSector := dos33SectorsLogicOrder[physicalSector]
logicalSector := logicalOrder[physicalSector]
sectorData := data[logicalSector*bytesPerSector : (logicalSector+1)*bytesPerSector]
// 6and2 prenibbilizing.