NIB to DSK

This commit is contained in:
Ivan Izaguirre 2020-08-29 18:45:51 +02:00
parent 06704ed1e3
commit 9935510445
5 changed files with 140 additions and 16 deletions

View File

@ -44,7 +44,6 @@ func (c *cardBase) assign(a *Apple2, slot int) {
if slot != 0 {
if c.romCsxx != nil {
// Relocate to the assigned slot
//c.romCsxx.base = uint16(0xc000 + slot*0x100)
c.romCsxx.setBase(uint16(0xc000 + slot*0x100))
a.mmu.setCardROM(slot, c.romCsxx)
}

View File

@ -11,12 +11,6 @@ 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
}

View File

@ -5,12 +5,6 @@ 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
}

View File

@ -1,6 +1,8 @@
package apple2
import (
"errors"
"fmt"
"os"
)
@ -100,6 +102,25 @@ var sixAndTwoTranslateTable = [0x40]byte{
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
}
var sixAndTwoUntranslateTable = [256]int16{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 0, 1, -1, -1, 2, 3, -1, 4, 5, 6,
-1, -1, -1, -1, -1, -1, 7, 8, -1, -1, -1, 9, 10, 11, 12, 13,
-1, -1, 14, 15, 16, 17, 18, 19, -1, 20, 21, 22, 23, 24, 25, 26,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, 28, 29, 30,
-1, -1, -1, 31, -1, -1, 32, 33, -1, 34, 35, 36, 37, 38, 39, 40,
-1, -1, -1, -1, -1, 41, 42, 43, -1, 44, 45, 46, 47, 48, 49, 50,
-1, -1, 51, 52, 53, 54, 55, 56, -1, 57, 58, 59, 60, 61, 62, 63,
}
const (
gap1Len = 48
gap2Len = 5
@ -112,8 +133,8 @@ func oddEvenEncodeByte(b byte) []byte {
A byte is encoded in two bytes to make sure the bytes start with 1 and
does not have two consecutive zeros.
Data byte: D7-D6-D5-D4-D3-D2-D1-D0
resutl[0]: 1-D7- 1-D5- 1-D3-1 -D1
resutl[1]: 1-D6- 1-D4- 1-D2-1 -D0
result[0]: 1-D7- 1-D5- 1-D3- 1-D1
result[1]: 1-D6- 1-D4- 1-D2- 1-D0
*/
e := make([]byte, 2)
e[0] = ((b >> 1) & 0x55) | 0xaa
@ -121,6 +142,24 @@ func oddEvenEncodeByte(b byte) []byte {
return e
}
func oddEvenDecodeByte(b0, b1 byte) byte {
/*
A byte is encoded in two bytes to make sure the bytes start with 1 and
does not have two consecutive zeros.
b0: 1-D7- 1-D5- 1-D3- 1-D1
b1: 1-D6- 1-D4- 1-D2- 1-D0
result: D7-D6-D5-D4-D3-D2-D1-D0
*/
return ((b0 & 0x55) << 1) | (b1 & 0x55)
}
const (
diskPrologByte1 = uint8(0xd5)
diskPrologByte2 = uint8(0xaa)
diskPrologByte3Address = uint8(0x96)
diskPrologByte3Data = uint8(0xad)
)
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
@ -135,7 +174,7 @@ func nibEncodeTrack(data []byte, volume byte, track byte, logicalOrder *[16]int)
for physicalSector := byte(0); physicalSector < numberOfSectors; physicalSector++ {
/* On the DSK file the sectors are in DOS3.3 logical order
but on the physical encoded track as well as in the nib
files they are in phisical order.
files they are in physical order.
*/
logicalSector := logicalOrder[physicalSector]
sectorData := data[logicalSector*bytesPerSector : (logicalSector+1)*bytesPerSector]
@ -181,3 +220,76 @@ func nibEncodeTrack(data []byte, volume byte, track byte, logicalOrder *[16]int)
return b
}
func findProlog(diskPrologByte3 uint8, data []byte, position int) int {
l := len(data)
for i := position; i < l; i++ {
if (data[i] == diskPrologByte1) &&
(data[(i+1)%l] == diskPrologByte2) &&
(data[(i+2)%l] == diskPrologByte3) {
return (i + 3) % l
}
}
return -1
}
func nibDecodeTrack(data []byte, track byte, logicalOrder *[16]int) ([]byte, error) {
b := make([]byte, bytesPerTrack) // Buffer slice with enough capacity
i := int(0)
l := len(data)
for {
// Find address field prolog
i = findProlog(diskPrologByte3Address, data, i)
if i == -1 {
break
}
// We just want the sector from the address field, we ignore the rest, no error detection
sector := oddEvenDecodeByte(data[(i+4)%l], data[(i+5)%l])
logicalSector := logicalOrder[sector]
dst := int(logicalSector) * bytesPerSector
fmt.Printf("Processing sector %v (%v), destination: %v\n", sector, logicalSector, dst)
i = (i + 8 + 3) % l // We skip the four two byte fields and the epilog
// Find data prolog
i = findProlog(diskPrologByte3Data, data, i)
// Read secondary buffer
prevV := byte(0)
for j := 0; j < secondaryBufferSize; j++ {
w := sixAndTwoUntranslateTable[data[i%l]]
if w == -1 {
return nil, errors.New("Invalid byte from nib data")
}
v := byte(w) ^ prevV
prevV = v
for k := 0; k < 3; k++ {
// The elements of the secondary buffer add two bits to three bytes
offset := j + k*secondaryBufferSize
if offset < bytesPerSector {
b[dst+offset] |= ((v & 0x02) >> 1) | ((v & 0x01) << 1)
}
v >>= 2
}
i++
}
// Read primary buffer
for j := 0; j < primaryBufferSize; j++ {
w := sixAndTwoUntranslateTable[data[i%l]]
if w == -1 {
return nil, errors.New("Invalid byte from nib data")
}
v := byte(w) ^ prevV
b[dst+j] |= v << 2 // The elements of the secondary buffer are the 6 MSB bits
prevV = v
i++
}
}
return b, nil
}

25
fileNib_test.go Normal file
View File

@ -0,0 +1,25 @@
package apple2
import (
"testing"
)
func TestNibBackAndForth(t *testing.T) {
// Init data
data := make([]byte, bytesPerTrack)
for i := 0; i < bytesPerTrack; i++ {
data[i] = byte(i % 100)
}
nib := nibEncodeTrack(data, 255, 0, &dos33SectorsLogicalOrder)
data2, err := nibDecodeTrack(nib, 0, &dos33SectorsLogicalOrder)
if err != nil {
t.Error(err)
}
for i := 0; i < bytesPerTrack; i++ {
if data[i] != data2[i] {
t.Errorf("Mismatch in %v: %02x -> %02x", i, data[i], data2[i])
}
}
}