mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-12-26 20:29:50 +00:00
Woz protections automatic tests
This commit is contained in:
parent
cde673a552
commit
fe15ce8c93
@ -92,8 +92,8 @@ func (a *Apple2) LoadRom(filename string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddDisk2 inserts a DiskII controller
|
// AddDisk2 inserts a DiskII controller
|
||||||
func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
|
func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string, trackTracer trackTracer) error {
|
||||||
c := NewCardDisk2()
|
c := NewCardDisk2(trackTracer)
|
||||||
a.insertCard(c, slot)
|
a.insertCard(c, slot)
|
||||||
|
|
||||||
if diskImage != "" {
|
if diskImage != "" {
|
||||||
@ -116,8 +116,8 @@ func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddDisk2 inserts a DiskII controller
|
// AddDisk2 inserts a DiskII controller
|
||||||
func (a *Apple2) AddDisk2Sequencer(slot int, diskImage, diskBImage string) error {
|
func (a *Apple2) AddDisk2Sequencer(slot int, diskImage, diskBImage string, trackTracer trackTracer) error {
|
||||||
c := NewCardDisk2Sequencer()
|
c := NewCardDisk2Sequencer(trackTracer)
|
||||||
a.insertCard(c, slot)
|
a.insertCard(c, slot)
|
||||||
|
|
||||||
if diskImage != "" {
|
if diskImage != "" {
|
||||||
|
@ -245,12 +245,12 @@ func MainApple() *Apple2 {
|
|||||||
}
|
}
|
||||||
if *disk2Slot > 0 {
|
if *disk2Slot > 0 {
|
||||||
if *sequencerDisk2 {
|
if *sequencerDisk2 {
|
||||||
err := a.AddDisk2Sequencer(*disk2Slot, diskImageFinal, *diskBImage)
|
err := a.AddDisk2Sequencer(*disk2Slot, diskImageFinal, *diskBImage, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := a.AddDisk2(*disk2Slot, diskImageFinal, *diskBImage)
|
err := a.AddDisk2(*disk2Slot, diskImageFinal, *diskBImage, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
27
cardDisk2.go
27
cardDisk2.go
@ -32,19 +32,22 @@ type CardDisk2 struct {
|
|||||||
dataLatch uint8
|
dataLatch uint8
|
||||||
q6 bool
|
q6 bool
|
||||||
q7 bool
|
q7 bool
|
||||||
|
|
||||||
|
trackTracer trackTracer
|
||||||
}
|
}
|
||||||
|
|
||||||
type cardDisk2Drive struct {
|
type cardDisk2Drive struct {
|
||||||
name string
|
name string
|
||||||
diskette storage.Diskette
|
diskette storage.Diskette
|
||||||
phases uint8 // q3, q2, q1 and q0 with q0 on the LSB. Magnets that are active on the stepper motor
|
phases uint8 // q3, q2, q1 and q0 with q0 on the LSB. Magnets that are active on the stepper motor
|
||||||
tracksStep int // Stepmotor for tracks position. 4 steps per track
|
trackStep int // Stepmotor for tracks position. 4 steps per track
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCardDisk2 creates a new CardDisk2
|
// NewCardDisk2 creates a new CardDisk2
|
||||||
func NewCardDisk2() *CardDisk2 {
|
func NewCardDisk2(trackTracer trackTracer) *CardDisk2 {
|
||||||
var c CardDisk2
|
var c CardDisk2
|
||||||
c.name = "Disk II"
|
c.name = "Disk II"
|
||||||
|
c.trackTracer = trackTracer
|
||||||
c.loadRomFromResource("<internal>/DISK2.rom")
|
c.loadRomFromResource("<internal>/DISK2.rom")
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
@ -56,10 +59,10 @@ func (c *CardDisk2) GetInfo() map[string]string {
|
|||||||
info["power"] = strconv.FormatBool(c.power)
|
info["power"] = strconv.FormatBool(c.power)
|
||||||
|
|
||||||
info["D1 name"] = c.drive[0].name
|
info["D1 name"] = c.drive[0].name
|
||||||
info["D1 track"] = strconv.FormatFloat(float64(c.drive[0].tracksStep)/4, 'f', 2, 64)
|
info["D1 track"] = strconv.FormatFloat(float64(c.drive[0].trackStep)/4, 'f', 2, 64)
|
||||||
|
|
||||||
info["D2 name"] = c.drive[1].name
|
info["D2 name"] = c.drive[1].name
|
||||||
info["D2 track"] = strconv.FormatFloat(float64(c.drive[1].tracksStep)/4, 'f', 2, 64)
|
info["D2 track"] = strconv.FormatFloat(float64(c.drive[1].trackStep)/4, 'f', 2, 64)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +84,11 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
|
|||||||
// Update magnets and position
|
// Update magnets and position
|
||||||
drive := &c.drive[c.selected]
|
drive := &c.drive[c.selected]
|
||||||
drive.phases &^= (1 << phase)
|
drive.phases &^= (1 << phase)
|
||||||
drive.tracksStep = moveDriveStepper(drive.phases, drive.tracksStep)
|
drive.trackStep = moveDriveStepper(drive.phases, drive.trackStep)
|
||||||
|
|
||||||
|
if c.trackTracer != nil {
|
||||||
|
c.trackTracer.traceTrack(drive.trackStep)
|
||||||
|
}
|
||||||
|
|
||||||
return c.dataLatch // All even addresses return the last dataLatch
|
return c.dataLatch // All even addresses return the last dataLatch
|
||||||
}, fmt.Sprintf("PHASE%vOFF", phase))
|
}, fmt.Sprintf("PHASE%vOFF", phase))
|
||||||
@ -90,7 +97,11 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
|
|||||||
// Update magnets and position
|
// Update magnets and position
|
||||||
drive := &c.drive[c.selected]
|
drive := &c.drive[c.selected]
|
||||||
drive.phases |= (1 << phase)
|
drive.phases |= (1 << phase)
|
||||||
drive.tracksStep = moveDriveStepper(drive.phases, drive.tracksStep)
|
drive.trackStep = moveDriveStepper(drive.phases, drive.trackStep)
|
||||||
|
|
||||||
|
if c.trackTracer != nil {
|
||||||
|
c.trackTracer.traceTrack(drive.trackStep)
|
||||||
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}, fmt.Sprintf("PHASE%vON", phase))
|
}, fmt.Sprintf("PHASE%vON", phase))
|
||||||
@ -194,9 +205,9 @@ func (c *CardDisk2) processQ6Q7(in uint8) {
|
|||||||
}
|
}
|
||||||
if !c.q6 { // shift
|
if !c.q6 { // shift
|
||||||
if !c.q7 { // Q6L-Q7L: Read
|
if !c.q7 { // Q6L-Q7L: Read
|
||||||
c.dataLatch = d.diskette.Read(d.tracksStep, c.a.cpu.GetCycles())
|
c.dataLatch = d.diskette.Read(d.trackStep, c.a.cpu.GetCycles())
|
||||||
} else { // Q6L-Q7H: Write the dataLatch value to disk. Shift data out
|
} else { // Q6L-Q7H: Write the dataLatch value to disk. Shift data out
|
||||||
d.diskette.Write(d.tracksStep, c.dataLatch, c.a.cpu.GetCycles())
|
d.diskette.Write(d.trackStep, c.dataLatch, c.a.cpu.GetCycles())
|
||||||
}
|
}
|
||||||
} else { // load
|
} else { // load
|
||||||
if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state
|
if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state
|
||||||
|
@ -33,6 +33,8 @@ type CardDisk2Sequencer struct {
|
|||||||
lastPulseCycles uint8 // There is a new pulse every 4ms, that's 8 cycles of 2Mhz
|
lastPulseCycles uint8 // There is a new pulse every 4ms, that's 8 cycles of 2Mhz
|
||||||
|
|
||||||
lastCycle uint64 // 2 Mhz cycles
|
lastCycle uint64 // 2 Mhz cycles
|
||||||
|
|
||||||
|
trackTracer trackTracer
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -48,9 +50,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewCardDisk2Sequencer creates a new CardDisk2Sequencer
|
// NewCardDisk2Sequencer creates a new CardDisk2Sequencer
|
||||||
func NewCardDisk2Sequencer() *CardDisk2Sequencer {
|
func NewCardDisk2Sequencer(trackTracer trackTracer) *CardDisk2Sequencer {
|
||||||
var c CardDisk2Sequencer
|
var c CardDisk2Sequencer
|
||||||
c.name = "Disk II"
|
c.name = "Disk II"
|
||||||
|
c.trackTracer = trackTracer
|
||||||
c.loadRomFromResource("<internal>/DISK2.rom")
|
c.loadRomFromResource("<internal>/DISK2.rom")
|
||||||
|
|
||||||
data, _, err := LoadResource("<internal>/DISK2P6.rom")
|
data, _, err := LoadResource("<internal>/DISK2P6.rom")
|
||||||
@ -172,8 +175,8 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool {
|
|||||||
q1 := c.q[1]
|
q1 := c.q[1]
|
||||||
q2 := c.q[2]
|
q2 := c.q[2]
|
||||||
q3 := c.q[3]
|
q3 := c.q[3]
|
||||||
c.drive[0].moveHead(q0, q1, q2, q3)
|
c.drive[0].moveHead(q0, q1, q2, q3, c.trackTracer)
|
||||||
c.drive[1].moveHead(q0, q1, q2, q3)
|
c.drive[1].moveHead(q0, q1, q2, q3, c.trackTracer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -48,7 +48,7 @@ func (d *cardDisk2SequencerDrive) enable(enabled bool) {
|
|||||||
d.enabled = enabled
|
d.enabled = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cardDisk2SequencerDrive) moveHead(q0, q1, q2, q3 bool) {
|
func (d *cardDisk2SequencerDrive) moveHead(q0, q1, q2, q3 bool, trackTracer trackTracer) {
|
||||||
if !d.enabled {
|
if !d.enabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -58,6 +58,10 @@ func (d *cardDisk2SequencerDrive) moveHead(q0, q1, q2, q3 bool) {
|
|||||||
false, false, false, false,
|
false, false, false, false,
|
||||||
})
|
})
|
||||||
d.currentQuarterTrack = moveDriveStepper(phases, d.currentQuarterTrack)
|
d.currentQuarterTrack = moveDriveStepper(phases, d.currentQuarterTrack)
|
||||||
|
|
||||||
|
if trackTracer != nil {
|
||||||
|
trackTracer.traceTrack(d.currentQuarterTrack)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cardDisk2SequencerDrive) readPulse() bool {
|
func (d *cardDisk2SequencerDrive) readPulse() bool {
|
||||||
|
@ -72,7 +72,7 @@ func TestBase64Boots(t *testing.T) {
|
|||||||
func TestPlusDOS33Boots(t *testing.T) {
|
func TestPlusDOS33Boots(t *testing.T) {
|
||||||
at := makeApple2Tester("2plus")
|
at := makeApple2Tester("2plus")
|
||||||
|
|
||||||
err := at.a.AddDisk2(6, "<internal>/dos33.dsk", "")
|
err := at.a.AddDisk2(6, "<internal>/dos33.dsk", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
116
e2e_woz_test.go
Normal file
116
e2e_woz_test.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package izapple2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testWoz(t *testing.T, sequencer bool, file string, expectedTracks []int, cycleLimit uint64) {
|
||||||
|
at := makeApple2Tester("2enh")
|
||||||
|
tt := makeTrackTracerSummary()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if sequencer {
|
||||||
|
err = at.a.AddDisk2Sequencer(6, "woz_test_images/"+file, "", tt)
|
||||||
|
} else {
|
||||||
|
err = at.a.AddDisk2(6, "woz_test_images/"+file, "", tt)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedLen := len(expectedTracks)
|
||||||
|
|
||||||
|
at.terminateCondition = func(a *Apple2) bool {
|
||||||
|
tracksMayMatch := len(tt.quarterTracks) >= expectedLen &&
|
||||||
|
tt.quarterTracks[expectedLen-1] == expectedTracks[expectedLen-1]
|
||||||
|
|
||||||
|
return tracksMayMatch || a.cpu.GetCycles() > cycleLimit
|
||||||
|
}
|
||||||
|
at.run()
|
||||||
|
|
||||||
|
if !tt.isTraceAsExpected(expectedTracks) {
|
||||||
|
t.Errorf("Quarter tracks, expected %#v, got %#v", expectedTracks, tt.quarterTracks)
|
||||||
|
}
|
||||||
|
|
||||||
|
//t.Errorf("Cycles: %d vs %d", at.a.cpu.GetCycles(), cycleLimit)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
all = 0
|
||||||
|
seq = 1 // Passes only with the sequencer implementation
|
||||||
|
none = 2 // Fails also with the sequencer implementation
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWoz(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
skip int
|
||||||
|
disk string
|
||||||
|
cycleLimit uint64
|
||||||
|
expectedTracks []int
|
||||||
|
}{
|
||||||
|
// How to being
|
||||||
|
// DOS 3.2, requires 13 sector disks
|
||||||
|
{"DOS3.3", all, "DOS 3.3 System Master.woz", 11_000_000, []int{0, 8, 0, 76, 68, 84, 68, 84, 68, 92, 16, 24}},
|
||||||
|
|
||||||
|
// Next choices
|
||||||
|
{"Bouncing Kamungas", all, "Bouncing Kamungas - Disk 1, Side A.woz", 30_000_000, []int{0, 32, 0, 40, 0}},
|
||||||
|
{"Commando", seq, "Commando - Disk 1, Side A.woz", 14_000_000, []int{0, 136, 68, 128, 68, 128, 68, 124, 12, 116, 108}},
|
||||||
|
{"Planetfall", all, "Planetfall - Disk 1, Side A.woz", 4_000_000, []int{0, 8}},
|
||||||
|
{"Rescue Raiders", all, "Rescue Raiders - Disk 1, Side B.woz", 80_000_000, []int{
|
||||||
|
0, 84, 44, 46,
|
||||||
|
0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0,
|
||||||
|
84, 44, 116, 4, 8, 4, 12, 8, 84, 44, 132, 0, 120, 44, 84, 44, 124, 0, 120, 44}},
|
||||||
|
{"Sammy Lightfoot", all, "Sammy Lightfoot - Disk 1, Side A.woz", 80_000_000, []int{0, 64, 8, 20}},
|
||||||
|
{"Stargate", all, "Stargate - Disk 1, Side A.woz", 50_000_000, []int{0, 8, 0, 72, 68, 80, 68, 80, 12, 44}},
|
||||||
|
|
||||||
|
// Cross track sync
|
||||||
|
{"Blazing Paddles", all, "Blazing Paddles (Baudville).woz", 6_000_000, []int{0, 28, 0, 16, 12, 56, 52, 80}},
|
||||||
|
{"Take 1", all, "Take 1 (Baudville).woz", 8_000_000, []int{0, 28, 0, 4, 0, 72, 0, 20, 0}},
|
||||||
|
{"Hard Hat Mack", all, "Hard Hat Mack - Disk 1, Side A.woz", 10_000_000, []int{0, 134, 132}},
|
||||||
|
|
||||||
|
// Half tracks
|
||||||
|
{"The Bilestoad", all, "The Bilestoad - Disk 1, Side A.woz", 6_000_000, []int{0, 24}},
|
||||||
|
|
||||||
|
// Even more bit fiddling
|
||||||
|
{"Dino Eggs", all, "Dino Eggs - Disk 1, Side A.woz", 9_000_000, []int{0, 78, 60, 108, 32}},
|
||||||
|
{"Crisis Mountain", all, "Crisis Mountain - Disk 1, Side A.woz", 20_000_000, []int{0, 32, 8, 32, 20, 76, 20, 36, 32, 84, 52, 64}},
|
||||||
|
{"Miner 2049er II", all, "Miner 2049er II - Disk 1, Side A.woz", 11_000_000, []int{0, 12, 8, 32, 12, 136, 132}},
|
||||||
|
|
||||||
|
// When bits aren't really bits
|
||||||
|
{"The Print Shop Companion", all, "The Print Shop Companion - Disk 1, Side A.woz", 14_000_000, []int{0, 68, 44, 68, 40, 68, 40, 136, 60}},
|
||||||
|
|
||||||
|
// What is the lifepsan of the data latch?
|
||||||
|
{"First Math Adventures", seq, "First Math Adventures - Understanding Word Problems.woz", 6_000_000, []int{0, 8, 0, 68, 12, 20}},
|
||||||
|
|
||||||
|
// Reading Offset Data Streams
|
||||||
|
{"Wings of Fury", seq, "Wings of Fury - Disk 1, Side A.woz", 410_000_000, []int{0, 4, 0, 136, 124, 128, 24, 136, 124, 128, 24, 136, 124, 128, 24, 136, 124, 128, 24, 104}},
|
||||||
|
{"Stickybear Town Builder", all, "Stickybear Town Builder - Disk 1, Side A.woz", 8_000_000, []int{0, 16, 12, 112, 80, 100, 8}},
|
||||||
|
|
||||||
|
// Optimal bit timing
|
||||||
|
// Requires disk change {"Border Zone", "Border Zone - Disk 1, Side A.woz", 500_000_000, []int{1,1,1,1,1,1}},
|
||||||
|
|
||||||
|
// Extra
|
||||||
|
{"Mr. Do", seq, "Mr. Do.woz", 95_000_000, []int{0, 108, 48, 104, 72, 84, 0, 4}},
|
||||||
|
{"Wavy Navy", all, "Wavy Navy.woz", 9_000_000, []int{0, 136}},
|
||||||
|
// SAGA6 requires disk change,
|
||||||
|
// Note that Congo Bongo works with the non sequencer implementation but the test is unstable
|
||||||
|
{"Congo Bongo", seq, "Congo Bongo.woz", 8_000_000, []int{0, 4, 2, 40, 20, 40, 16, 124, 116}},
|
||||||
|
// Wizardry III requires disk change,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
if tc.skip == all {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
testWoz(t, false, tc.disk, tc.expectedTracks, tc.cycleLimit)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if tc.skip == all || tc.skip == seq {
|
||||||
|
t.Run(tc.name+" SEQ", func(t *testing.T) {
|
||||||
|
testWoz(t, true, tc.disk, tc.expectedTracks, tc.cycleLimit)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +1,6 @@
|
|||||||
|
|
||||||
# WOZ emulation status:
|
# WOZ emulation status:
|
||||||
|
|
||||||
## Using the behavioral implementation
|
|
||||||
- How to begin
|
|
||||||
- DOS 3.3: Works
|
|
||||||
- DOS 3.2: **Unknown, 13 sector disks boot not supported**
|
|
||||||
- Next choices
|
|
||||||
- Bouncing Kamungas: Works
|
|
||||||
- Commando: ***Not working***
|
|
||||||
- Planetfall: Working
|
|
||||||
- Rescue Raiders: Working
|
|
||||||
- Sammy Lightfoot: Working
|
|
||||||
- Stargate: Working
|
|
||||||
- Cross track sync
|
|
||||||
- Blazing Paddles: Working
|
|
||||||
- Take 1: Working
|
|
||||||
- Hard Hat Mack: Working
|
|
||||||
- Half tracks
|
|
||||||
- The Bilestoad: Working
|
|
||||||
- Even more bit fiddling
|
|
||||||
- Dino Eggs: Working
|
|
||||||
- Crisis Mountain: Working
|
|
||||||
- Miner 2049er II: Working
|
|
||||||
- When bits aren't really bits
|
|
||||||
- The Print Shop Companion: Working
|
|
||||||
- What is the lifespan of the data latch?
|
|
||||||
- First Math Adventures: ***Not working***
|
|
||||||
- Reading Offset Data Streams
|
|
||||||
- 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**
|
|
||||||
- 4am on Slack (2021-06-29)
|
|
||||||
- Mr Do: ***Not working***
|
|
||||||
- Wavy Navy: Working
|
|
||||||
- SAGA 6 Strange Odyssey: **Unknown, there is no UI to swap disks**
|
|
||||||
- Congo Bongo: Working
|
|
||||||
- Wizardry II: ***Not working***
|
|
||||||
|
|
||||||
## With the sequencer:
|
## With the sequencer:
|
||||||
- How to begin
|
- How to begin
|
||||||
- DOS 3.3: Works
|
- DOS 3.3: Works
|
||||||
@ -73,6 +36,43 @@
|
|||||||
- Wavy Navy: Working
|
- Wavy Navy: Working
|
||||||
- SAGA 6 Strange Odyssey: **Unknown, there is no UI to swap disks**
|
- SAGA 6 Strange Odyssey: **Unknown, there is no UI to swap disks**
|
||||||
- Congo Bongo: Working
|
- Congo Bongo: Working
|
||||||
- Wizardry II: Working
|
- Wizardry III: Working
|
||||||
|
|
||||||
|
|
||||||
|
## Using the behavioral implementation
|
||||||
|
- How to begin
|
||||||
|
- DOS 3.3: Works
|
||||||
|
- DOS 3.2: **Unknown, 13 sector disks boot not supported**
|
||||||
|
- Next choices
|
||||||
|
- Bouncing Kamungas: Works
|
||||||
|
- Commando: ***Not working***
|
||||||
|
- Planetfall: Working
|
||||||
|
- Rescue Raiders: Working
|
||||||
|
- Sammy Lightfoot: Working
|
||||||
|
- Stargate: Working
|
||||||
|
- Cross track sync
|
||||||
|
- Blazing Paddles: Working
|
||||||
|
- Take 1: Working
|
||||||
|
- Hard Hat Mack: Working
|
||||||
|
- Half tracks
|
||||||
|
- The Bilestoad: Working
|
||||||
|
- Even more bit fiddling
|
||||||
|
- Dino Eggs: Working
|
||||||
|
- Crisis Mountain: Working
|
||||||
|
- Miner 2049er II: Working
|
||||||
|
- When bits aren't really bits
|
||||||
|
- The Print Shop Companion: Working
|
||||||
|
- What is the lifespan of the data latch?
|
||||||
|
- First Math Adventures: ***Not working***
|
||||||
|
- Reading Offset Data Streams
|
||||||
|
- 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**
|
||||||
|
- 4am on Slack (2021-06-29)
|
||||||
|
- Mr Do: ***Not working***
|
||||||
|
- Wavy Navy: Working
|
||||||
|
- SAGA 6 Strange Odyssey: **Unknown, there is no UI to swap disks**
|
||||||
|
- Congo Bongo: Working
|
||||||
|
- Wizardry III: ***Not working***
|
||||||
|
|
||||||
|
71
trackTracer.go
Normal file
71
trackTracer.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package izapple2
|
||||||
|
|
||||||
|
type trackTracer interface {
|
||||||
|
traceTrack(quarterTrack int)
|
||||||
|
}
|
||||||
|
|
||||||
|
type trackTracerSummary struct {
|
||||||
|
quarterTracks []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTrackTracerSummary() *trackTracerSummary {
|
||||||
|
var tt trackTracerSummary
|
||||||
|
tt.quarterTracks = make([]int, 0, 100)
|
||||||
|
return &tt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tt *trackTracerSummary) traceTrack(quarterTrack int) {
|
||||||
|
if tt == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
length := len(tt.quarterTracks)
|
||||||
|
if length == 0 {
|
||||||
|
// Second change, just record
|
||||||
|
tt.quarterTracks = append(tt.quarterTracks, quarterTrack)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
last := tt.quarterTracks[length-1]
|
||||||
|
if quarterTrack == last {
|
||||||
|
// No changes
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if length == 1 {
|
||||||
|
// Second change, just record
|
||||||
|
tt.quarterTracks = append(tt.quarterTracks, quarterTrack)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to registers the initial jumps around 0 seen when initializing the disk to track 0
|
||||||
|
prevToLast := tt.quarterTracks[length-2]
|
||||||
|
if length == 2 && prevToLast == 0 && (last == 1 || last == 2) && quarterTrack == 0 {
|
||||||
|
tt.quarterTracks = tt.quarterTracks[0:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to track each increment. If tracks goes from 1 to 14, we just want 1 and 14.
|
||||||
|
wasGoingUp := last > prevToLast
|
||||||
|
isGoingUp := quarterTrack > last
|
||||||
|
if isGoingUp == wasGoingUp {
|
||||||
|
// Same direction, update the last registry
|
||||||
|
tt.quarterTracks[length-1] = quarterTrack
|
||||||
|
} else {
|
||||||
|
// Change direction, add a new registry
|
||||||
|
tt.quarterTracks = append(tt.quarterTracks, quarterTrack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tt *trackTracerSummary) isTraceAsExpected(expected []int) bool {
|
||||||
|
if len(tt.quarterTracks) != len(expected) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range tt.quarterTracks {
|
||||||
|
if v != expected[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
BIN
woz_test_images/Blazing Paddles (Baudville).woz
Normal file
BIN
woz_test_images/Blazing Paddles (Baudville).woz
Normal file
Binary file not shown.
BIN
woz_test_images/Border Zone - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Border Zone - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Border Zone - Disk 1, Side B.woz
Normal file
BIN
woz_test_images/Border Zone - Disk 1, Side B.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Bouncing Kamungas - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Bouncing Kamungas - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Commando - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Commando - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Congo Bongo.woz
Normal file
BIN
woz_test_images/Congo Bongo.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Crisis Mountain - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Crisis Mountain - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/DOS 3.2 System Master.woz
Normal file
BIN
woz_test_images/DOS 3.2 System Master.woz
Normal file
Binary file not shown.
BIN
woz_test_images/DOS 3.3 System Master.woz
Normal file
BIN
woz_test_images/DOS 3.3 System Master.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Dino Eggs - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Dino Eggs - Disk 1, Side A.woz
Normal file
Binary file not shown.
Binary file not shown.
BIN
woz_test_images/Hard Hat Mack - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Hard Hat Mack - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Miner 2049er II - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Miner 2049er II - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Mr. Do.woz
Normal file
BIN
woz_test_images/Mr. Do.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Planetfall - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Planetfall - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Rescue Raiders - Disk 1, Side B.woz
Normal file
BIN
woz_test_images/Rescue Raiders - Disk 1, Side B.woz
Normal file
Binary file not shown.
BIN
woz_test_images/S.A.G.A. 6 - Strange Odyssey side A.woz
Normal file
BIN
woz_test_images/S.A.G.A. 6 - Strange Odyssey side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/S.A.G.A. 6 - Strange Odyssey side B (boot).woz
Normal file
BIN
woz_test_images/S.A.G.A. 6 - Strange Odyssey side B (boot).woz
Normal file
Binary file not shown.
BIN
woz_test_images/Sammy Lightfoot - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Sammy Lightfoot - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Stargate - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Stargate - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Stickybear Town Builder - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Stickybear Town Builder - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Take 1 (Baudville).woz
Normal file
BIN
woz_test_images/Take 1 (Baudville).woz
Normal file
Binary file not shown.
BIN
woz_test_images/The Apple at Play.woz
Normal file
BIN
woz_test_images/The Apple at Play.woz
Normal file
Binary file not shown.
BIN
woz_test_images/The Bilestoad - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/The Bilestoad - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/The Print Shop Companion - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/The Print Shop Companion - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Wavy Navy.woz
Normal file
BIN
woz_test_images/Wavy Navy.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Wings of Fury - Disk 1, Side A.woz
Normal file
BIN
woz_test_images/Wings of Fury - Disk 1, Side A.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Wings of Fury - Disk 1, Side B.woz
Normal file
BIN
woz_test_images/Wings of Fury - Disk 1, Side B.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Wizardry III side A - master scenario disk.woz
Normal file
BIN
woz_test_images/Wizardry III side A - master scenario disk.woz
Normal file
Binary file not shown.
BIN
woz_test_images/Wizardry III side B - boot.woz
Normal file
BIN
woz_test_images/Wizardry III side B - boot.woz
Normal file
Binary file not shown.
21
woz_test_images/notes.txt
Normal file
21
woz_test_images/notes.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
[From Apple II Slack, 4am (2021-06-29)]
|
||||||
|
|
||||||
|
On the subject of "tricky woz images beyond the official test suite," I would recommend
|
||||||
|
|
||||||
|
https://archive.org/details/wozaday_Mr_Do (success = boot to joystick calibration)
|
||||||
|
https://archive.org/details/wozaday_Wavy_Navy (success = boot to game)
|
||||||
|
https://archive.org/details/wozaday_SAGA_6_Strange_Odyssey (success = begin game, climb down ladder, take shovel)
|
||||||
|
https://archive.org/details/wozaday_CongoBongo (success = boot to game)
|
||||||
|
https://archive.org/details/wozaday_Wizardry_III (success = boot to title screen, press a key, boot to main menu)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Mr. Do relies on weakbits on track 0. Also, the protection check uses LDA $C088,X to fetch nibbles and expects the entire check to complete before the drive motor turns off.
|
||||||
|
|
||||||
|
Wavy Navy relies on weakbits on track $22
|
||||||
|
|
||||||
|
Strange Odyssey relies on both track length and weakbits on track $22
|
||||||
|
|
||||||
|
Congo Bongo relies on weakbits on track 1, to a much greater degree than others. There is only one small sequence of valid nibbles, surrounded by an entire track of weakbits. This has flummoxed many emulators.
|
||||||
|
|
||||||
|
Wizardry III relies on track length, and it is extremely sensitive to the precise timing of when the data latch "sees" bits and how long it holds on to a full nibble before resetting itself.
|
Loading…
Reference in New Issue
Block a user