From a27ab177662e0c0b29f136e156704edc03906e4a Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Mon, 2 Dec 2019 23:16:35 +0100 Subject: [PATCH] Use the diskette abstraction for no cycle dependant DSK, NIB disks --- README.md | 2 +- cardDisk2.go | 119 +++++++++++++++++++++----------------------- diskette16sector.go | 26 +++++++--- 3 files changed, 77 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index fce5b81..ec953e0 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Portable emulator of an Apple II+ or //e. Written in Go. - FASTChip, limited to what Total Replay needs to set and clear fast mode - Graphic modes: - Text 40 columns - - text 80 columns (Apple //e only) + - Text 80 columns (Apple //e only) - Low-Resolution graphics - Double-Width Low-Resolution graphics (Apple //e only) - High-Resolution graphics diff --git a/cardDisk2.go b/cardDisk2.go index 10ef6f4..ccd217d 100644 --- a/cardDisk2.go +++ b/cardDisk2.go @@ -33,9 +33,8 @@ type cardDisk2 struct { } type cardDisk2Drive struct { - diskette *diskette16sector - power bool // q4, not realy used for anything - position int + diskette diskette + power bool // q4 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 } @@ -43,8 +42,8 @@ type cardDisk2Drive struct { type diskette interface { powerOn(cycle uint64) powerOff(cycle uint64) - read(halfTrack int, cycle uint64) uint8 - write(halfTrack int, value uint8, cycle uint64) + read(quarterTrack int, cycle uint64) uint8 + write(quarterTrack int, value uint8, cycle uint64) } const ( @@ -81,16 +80,24 @@ func (c *cardDisk2) assign(a *Apple2, slot int) { // Q4, power switch c.addCardSoftSwitchR(0x8, func(_ *ioC0Page) uint8 { - if c.drive[c.selected].power { - c.drive[c.selected].power = false + drive := c.drive[c.selected] + if !drive.power { + drive.power = false c.a.releaseFastMode() + if drive.diskette != nil { + drive.diskette.powerOff(c.a.cpu.GetCycles()) + } } return c.dataLatch }, "Q4DRIVEOFF") c.addCardSoftSwitchR(0x9, func(_ *ioC0Page) uint8 { - if !c.drive[c.selected].power { - c.drive[c.selected].power = true + drive := c.drive[c.selected] + if !drive.power { + drive.power = true c.a.requestFastMode() + if drive.diskette != nil { + drive.diskette.powerOn(c.a.cpu.GetCycles()) + } } return 0 }, "") @@ -119,6 +126,47 @@ func (c *cardDisk2) assign(a *Apple2, slot int) { c.cardBase.assign(a, slot) } +func (c *cardDisk2) softSwitchQ6Q7(index uint8, in uint8) uint8 { + switch index { + case 0xC: // Q6L + c.q6 = false + case 0xD: // Q6H + c.q6 = true + case 0xE: // Q/L + c.q7 = false + case 0xF: // Q7H + c.q7 = true + } + + c.processQ6Q7(in) + if index&1 == 0 { + // All even addresses return the last dataLatch + return c.dataLatch + } + return 0 +} + +func (c *cardDisk2) processQ6Q7(in uint8) { + d := &c.drive[c.selected] + if d.diskette == nil { + return + } + if !c.q6 { + if !c.q7 { // Q6L-Q7L: Read + c.dataLatch = d.diskette.read(d.tracksStep, 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()) + } + } else { + if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state + // Bit 7 of the control status register means write protected + c.dataLatch = 0 // Never write protected + } else { // Q6H-Q7H: Load data into the controller + c.dataLatch = in + } + } +} + /* Stepper motor to position the track. @@ -197,50 +245,7 @@ func moveStep(phases uint8, prevStep int) int { return nextStep } -func (c *cardDisk2) softSwitchQ6Q7(index uint8, in uint8) uint8 { - switch index { - case 0xC: // Q6L - c.q6 = false - case 0xD: // Q6H - c.q6 = true - case 0xE: // Q/L - c.q7 = false - case 0xF: // Q7H - c.q7 = true - } - - c.processQ6Q7(in) - if index&1 == 0 { - // All even addresses return the last dataLatch - return c.dataLatch - } - return 0 -} - -func (c *cardDisk2) processQ6Q7(in uint8) { - d := &c.drive[c.selected] - if d.diskette == nil { - return - } - if !c.q6 { - if !c.q7 { // Q6L-Q7L: Read - track := d.tracksStep / stepsPerTrack - c.dataLatch, d.position = d.diskette.read(track, d.position) - } else { // Q6L-Q7H: Write the dataLatch value to disk. Shift data out - track := d.tracksStep / stepsPerTrack - d.position = d.diskette.write(track, d.position, c.dataLatch) - } - } else { - if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state - // Bit 7 of the control status register means write protected - c.dataLatch = 0 // Never write protected - } else { // Q6H-Q7H: Load data into the controller - c.dataLatch = in - } - } -} - -func (d *cardDisk2Drive) insertDiskette(dt *diskette16sector) { +func (d *cardDisk2Drive) insertDiskette(dt diskette) { d.diskette = dt } @@ -313,10 +318,6 @@ func (d *cardDisk2Drive) save(w io.Writer) error { if err != nil { return err } - err = binary.Write(w, binary.BigEndian, d.position) - if err != nil { - return err - } return nil } @@ -333,9 +334,5 @@ func (d *cardDisk2Drive) load(r io.Reader) error { if err != nil { return err } - err = binary.Read(r, binary.BigEndian, &d.position) - if err != nil { - return err - } return nil } diff --git a/diskette16sector.go b/diskette16sector.go index ff4494f..9c8e60d 100644 --- a/diskette16sector.go +++ b/diskette16sector.go @@ -23,18 +23,28 @@ const ( ) type diskette16sector struct { - track [numberOfTracks][]byte + track [numberOfTracks][]byte + position int } -func (d *diskette16sector) read(track int, position int) (value uint8, newPosition int) { - value = d.track[track][position] - newPosition = (position + 1) % nibBytesPerTrack - return +func (d *diskette16sector) powerOn(_ uint64) { + // Not needed +} +func (d *diskette16sector) powerOff(_ uint64) { + // Not needed } -func (d *diskette16sector) write(track int, position int, value uint8) int { - d.track[track][position] = value - return (position + 1) % nibBytesPerTrack +func (d *diskette16sector) read(quarterTrack int, _ uint64) uint8 { + track := quarterTrack / stepsPerTrack + value := d.track[track][d.position] + d.position = (d.position + 1) % nibBytesPerTrack + return value +} + +func (d *diskette16sector) write(quarterTrack int, value uint8, _ uint64) { + track := quarterTrack / stepsPerTrack + d.track[track][d.position] = value + d.position = (d.position + 1) % nibBytesPerTrack } func loadDisquette(filename string) (*diskette16sector, error) {