mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-12-03 08:51:44 +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
|
||||
func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
|
||||
c := NewCardDisk2()
|
||||
func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string, trackTracer trackTracer) error {
|
||||
c := NewCardDisk2(trackTracer)
|
||||
a.insertCard(c, slot)
|
||||
|
||||
if diskImage != "" {
|
||||
@ -116,8 +116,8 @@ func (a *Apple2) AddDisk2(slot int, diskImage, diskBImage string) error {
|
||||
}
|
||||
|
||||
// AddDisk2 inserts a DiskII controller
|
||||
func (a *Apple2) AddDisk2Sequencer(slot int, diskImage, diskBImage string) error {
|
||||
c := NewCardDisk2Sequencer()
|
||||
func (a *Apple2) AddDisk2Sequencer(slot int, diskImage, diskBImage string, trackTracer trackTracer) error {
|
||||
c := NewCardDisk2Sequencer(trackTracer)
|
||||
a.insertCard(c, slot)
|
||||
|
||||
if diskImage != "" {
|
||||
|
@ -245,12 +245,12 @@ func MainApple() *Apple2 {
|
||||
}
|
||||
if *disk2Slot > 0 {
|
||||
if *sequencerDisk2 {
|
||||
err := a.AddDisk2Sequencer(*disk2Slot, diskImageFinal, *diskBImage)
|
||||
err := a.AddDisk2Sequencer(*disk2Slot, diskImageFinal, *diskBImage, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
err := a.AddDisk2(*disk2Slot, diskImageFinal, *diskBImage)
|
||||
err := a.AddDisk2(*disk2Slot, diskImageFinal, *diskBImage, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
33
cardDisk2.go
33
cardDisk2.go
@ -32,19 +32,22 @@ type CardDisk2 struct {
|
||||
dataLatch uint8
|
||||
q6 bool
|
||||
q7 bool
|
||||
|
||||
trackTracer trackTracer
|
||||
}
|
||||
|
||||
type cardDisk2Drive struct {
|
||||
name string
|
||||
diskette storage.Diskette
|
||||
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
|
||||
name string
|
||||
diskette storage.Diskette
|
||||
phases uint8 // q3, q2, q1 and q0 with q0 on the LSB. Magnets that are active on the stepper motor
|
||||
trackStep int // Stepmotor for tracks position. 4 steps per track
|
||||
}
|
||||
|
||||
// NewCardDisk2 creates a new CardDisk2
|
||||
func NewCardDisk2() *CardDisk2 {
|
||||
func NewCardDisk2(trackTracer trackTracer) *CardDisk2 {
|
||||
var c CardDisk2
|
||||
c.name = "Disk II"
|
||||
c.trackTracer = trackTracer
|
||||
c.loadRomFromResource("<internal>/DISK2.rom")
|
||||
return &c
|
||||
}
|
||||
@ -56,10 +59,10 @@ func (c *CardDisk2) GetInfo() map[string]string {
|
||||
info["power"] = strconv.FormatBool(c.power)
|
||||
|
||||
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 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
|
||||
}
|
||||
|
||||
@ -81,7 +84,11 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
|
||||
// Update magnets and position
|
||||
drive := &c.drive[c.selected]
|
||||
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
|
||||
}, fmt.Sprintf("PHASE%vOFF", phase))
|
||||
@ -90,7 +97,11 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
|
||||
// Update magnets and position
|
||||
drive := &c.drive[c.selected]
|
||||
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
|
||||
}, fmt.Sprintf("PHASE%vON", phase))
|
||||
@ -194,9 +205,9 @@ func (c *CardDisk2) processQ6Q7(in uint8) {
|
||||
}
|
||||
if !c.q6 { // shift
|
||||
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
|
||||
d.diskette.Write(d.tracksStep, c.dataLatch, c.a.cpu.GetCycles())
|
||||
d.diskette.Write(d.trackStep, c.dataLatch, c.a.cpu.GetCycles())
|
||||
}
|
||||
} else { // load
|
||||
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
|
||||
|
||||
lastCycle uint64 // 2 Mhz cycles
|
||||
|
||||
trackTracer trackTracer
|
||||
}
|
||||
|
||||
const (
|
||||
@ -48,9 +50,10 @@ const (
|
||||
)
|
||||
|
||||
// NewCardDisk2Sequencer creates a new CardDisk2Sequencer
|
||||
func NewCardDisk2Sequencer() *CardDisk2Sequencer {
|
||||
func NewCardDisk2Sequencer(trackTracer trackTracer) *CardDisk2Sequencer {
|
||||
var c CardDisk2Sequencer
|
||||
c.name = "Disk II"
|
||||
c.trackTracer = trackTracer
|
||||
c.loadRomFromResource("<internal>/DISK2.rom")
|
||||
|
||||
data, _, err := LoadResource("<internal>/DISK2P6.rom")
|
||||
@ -172,8 +175,8 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool {
|
||||
q1 := c.q[1]
|
||||
q2 := c.q[2]
|
||||
q3 := c.q[3]
|
||||
c.drive[0].moveHead(q0, q1, q2, q3)
|
||||
c.drive[1].moveHead(q0, q1, q2, q3)
|
||||
c.drive[0].moveHead(q0, q1, q2, q3, c.trackTracer)
|
||||
c.drive[1].moveHead(q0, q1, q2, q3, c.trackTracer)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -48,7 +48,7 @@ func (d *cardDisk2SequencerDrive) enable(enabled bool) {
|
||||
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 {
|
||||
return
|
||||
}
|
||||
@ -58,6 +58,10 @@ func (d *cardDisk2SequencerDrive) moveHead(q0, q1, q2, q3 bool) {
|
||||
false, false, false, false,
|
||||
})
|
||||
d.currentQuarterTrack = moveDriveStepper(phases, d.currentQuarterTrack)
|
||||
|
||||
if trackTracer != nil {
|
||||
trackTracer.traceTrack(d.currentQuarterTrack)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *cardDisk2SequencerDrive) readPulse() bool {
|
||||
|
@ -72,7 +72,7 @@ func TestBase64Boots(t *testing.T) {
|
||||
func TestPlusDOS33Boots(t *testing.T) {
|
||||
at := makeApple2Tester("2plus")
|
||||
|
||||
err := at.a.AddDisk2(6, "<internal>/dos33.dsk", "")
|
||||
err := at.a.AddDisk2(6, "<internal>/dos33.dsk", "", nil)
|
||||
if err != nil {
|
||||
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:
|
||||
|
||||
## 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:
|
||||
- How to begin
|
||||
- DOS 3.3: Works
|
||||
@ -73,6 +36,43 @@
|
||||
- Wavy Navy: Working
|
||||
- SAGA 6 Strange Odyssey: **Unknown, there is no UI to swap disks**
|
||||
- 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