]> Shamusworld >> Repos - apple2/blobdiff - src/floppydrive.cpp
Miscellaneous bugfixes.
[apple2] / src / floppydrive.cpp
index 056ca2b7c5a5b3578eccfba4579c8d85cbfe405a..92917191dd10e16c5bb9a57c3a96fae444f3e437 100644 (file)
@@ -2,7 +2,7 @@
 // Apple 2 floppy disk support
 //
 // by James Hammons
-// (c) 2005-2018 Underground Software
+// (c) 2005-2019 Underground Software
 //
 // JLH = James Hammons <jlhamm@acm.org>
 //
 #include <string.h>
 #include "apple2.h"
 #include "crc32.h"
-#include "firmware.h"
+#include "fileio.h"
+#include "firmware/firmware.h"
 #include "log.h"
 #include "mmu.h"
 #include "video.h"             // For message spawning... Though there's probably a
                                                // better approach than this!
 
+// For testing 13-sector disk FW
+//#define TEST13
+
 // Useful enums
 
 enum { IO_MODE_READ, IO_MODE_WRITE };
 
-// FloppyDrive class variable initialization
-
-uint8_t FloppyDrive::doSector[16] = {
-       0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4, 0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF };
-uint8_t FloppyDrive::poSector[16] = {
-       0x0, 0x8, 0x1, 0x9, 0x2, 0xA, 0x3, 0xB, 0x4, 0xC, 0x5, 0xD, 0x6, 0xE, 0x7, 0xF };
-uint8_t FloppyDrive::wozHeader[9] = "WOZ1\xFF\x0A\x0D\x0A";
-uint8_t FloppyDrive::wozHeader2[9] = "WOZ2\xFF\x0A\x0D\x0A";
-uint8_t FloppyDrive::standardTMAP[141] = {
-       0, 0, 0xFF, 1, 1, 1, 0xFF, 2, 2, 2, 0xFF, 3, 3, 3, 0xFF, 4, 4, 4, 0xFF,
-       5, 5, 5, 0xFF, 6, 6, 6, 0xFF, 7, 7, 7, 0xFF, 8, 8, 8, 0xFF, 9, 9, 9, 0xFF,
-       10, 10, 10, 0xFF, 11, 11, 11, 0xFF, 12, 12, 12, 0xFF, 13, 13, 13, 0xFF,
-       14, 14, 14, 0xFF, 15, 15, 15, 0xFF, 16, 16, 16, 0xFF, 17, 17, 17, 0xFF,
-       18, 18, 18, 0xFF, 19, 19, 19, 0xFF, 20, 20, 20, 0xFF, 21, 21, 21, 0xFF,
-       22, 22, 22, 0xFF, 23, 23, 23, 0xFF, 24, 24, 24, 0xFF, 25, 25, 25, 0xFF,
-       26, 26, 26, 0xFF, 27, 27, 27, 0xFF, 28, 28, 28, 0xFF, 29, 29, 29, 0xFF,
-       30, 30, 30, 0xFF, 31, 31, 31, 0xFF, 32, 32, 32, 0xFF, 33, 33, 33, 0xFF,
-       34, 34, 34, 0xFF, 0xFF, 0xFF
-};
-uint8_t FloppyDrive::bitMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
-uint8_t FloppyDrive::sequencerROM[256] = {
-0x18, 0x18, 0x18, 0x18, 0x0A, 0x0A, 0x0A, 0x0A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x2D, 0x38, 0x2D, 0x38, 0x0A, 0x0A, 0x0A, 0x0A, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-0x38, 0x28, 0xD8, 0x08, 0x0A, 0x0A, 0x0A, 0x0A, 0x39, 0x39, 0x39, 0x39, 0x3B, 0x3B, 0x3B, 0x3B,
-0x48, 0x48, 0xD8, 0x48, 0x0A, 0x0A, 0x0A, 0x0A, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
-0x58, 0x58, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
-0x68, 0x68, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
-0x78, 0x78, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
-0x88, 0x88, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88,
-0x98, 0x98, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
-0x29, 0xA8, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
-0xBD, 0xB8, 0xCD, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0xB9, 0xB9, 0xB9, 0xB9, 0xBB, 0xBB, 0xBB, 0xBB,
-0x59, 0xC8, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
-0xD9, 0xA0, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
-0x08, 0xE8, 0xD8, 0xE8, 0x0A, 0x0A, 0x0A, 0x0A, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
-0xFD, 0xF8, 0xFD, 0xF8, 0x0A, 0x0A, 0x0A, 0x0A, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
-0x4D, 0xE0, 0xDD, 0xE0, 0x0A, 0x0A, 0x0A, 0x0A, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08
+// Misc. arrays (read only) that are needed
+
+static const uint8_t bitMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+static const uint8_t sequencerROM[256] = {
+       0x18, 0x18, 0x18, 0x18, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // $00
+       0x2D, 0x38, 0x2D, 0x38, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, // $10
+       0x38, 0x28, 0xD8, 0x08, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x39, 0x39, 0x39, 0x39, 0x3B, 0x3B, 0x3B, 0x3B, // $20
+       0x48, 0x48, 0xD8, 0x48, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, // $30
+       0x58, 0x58, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, // $40
+       0x68, 0x68, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, // $50
+       0x78, 0x78, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, // $60
+       0x88, 0x88, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, // $70
+       0x98, 0x98, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, // $80
+       0x29, 0xA8, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, // $90
+       0xBD, 0xB8, 0xCD, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xB9, 0xB9, 0xB9, 0xB9, 0xBB, 0xBB, 0xBB, 0xBB, // $A0
+       0x59, 0xC8, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, // $B0
+       0xD9, 0xA0, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, // $C0
+       0x08, 0xE8, 0xD8, 0xE8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, // $D0
+       0xFD, 0xF8, 0xFD, 0xF8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, // $E0
+       0x4D, 0xE0, 0xDD, 0xE0, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08  // $F0
 };
 
-char FloppyDrive::nameBuf[MAX_PATH];
-
-
-// Static in-line functions, for clarity & speed, mostly for reading values out
-// of the WOZ struct, which stores its data in LE; some for swapping variables
-static inline uint16_t Uint16LE(uint16_t v)
-{
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-       return ((v & 0xFF) << 8) | ((v & 0xFF00) >> 8);
-#else
-       return v;
+#if 1 // From UTA2E, but need to double check...
+static const uint8_t sequencerROM13[256] = {
+//                    vvvv (2, 4, 1, 3)
+       0x18, 0x08, 0xD8, 0x18, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // $00
+       0x28, 0x28, 0xD8, 0x28, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, // $10
+       0x38, 0x38, 0xD8, 0x38, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x39, 0x39, 0x39, 0x39, 0x3B, 0x3B, 0x3B, 0x3B, // $20
+       0x48, 0x48, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, // $30
+       0x58, 0x58, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, // $40
+       0x68, 0x68, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, // $50
+       0x78, 0x78, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, // $60
+       0x88, 0x88, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, // $70
+       0x98, 0x98, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, // $80
+       0x09, 0xA8, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, // $90
+       0xBD, 0xB8, 0xCD, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xB9, 0xB9, 0xB9, 0xB9, 0xBB, 0xBB, 0xBB, 0xBB, // $A0
+       0x39, 0xC8, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, // $B0
+       0xD9, 0xA0, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, // $C0
+       0x0D, 0xE8, 0x1D, 0xE8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, // $D0
+       0xFD, 0xF8, 0xFD, 0xF8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, // $E0
+       0x4D, 0xE0, 0xDD, 0xE0, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08  // $F0
+};
 #endif
-}
-
-
-static inline uint32_t Uint32LE(uint32_t v)
-{
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-       return ((v & 0xFF) << 24) | ((v & 0xFF00) << 8)
-               | ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24);
-#else
-       return v;
+#if 0
+static const uint8_t sequencerROM13[256] = {
+       0x18, 0x08, 0xD8, 0x18, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x98, 0x98, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+       0x38, 0x38, 0xD8, 0x38, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x39, 0x39, 0x39, 0x39, 0x3B, 0x3B, 0x3B, 0x3B,
+       0xBD, 0xB8, 0xCD, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xB9, 0xB9, 0xB9, 0xB9, 0xBB, 0xBB, 0xBB, 0xBB,
+       0x58, 0x58, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
+       0xD9, 0xA0, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+       0x78, 0x78, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+       0xFD, 0xF8, 0xFD, 0xF8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+       0x28, 0x28, 0xD8, 0x28, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+       0x09, 0xA8, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+       0x48, 0x48, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
+       0x39, 0xC8, 0xD9, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+       0x68, 0x68, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
+       0x0D, 0xE8, 0x1D, 0xE8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+       0x88, 0x88, 0xD8, 0xD8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88,
+       0x4D, 0xE0, 0xDD, 0xE0, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08
+};
 #endif
-}
-
+#if 0
+static const uint8_t sequencerROM13[256] = {
+       0x88, 0x08, 0xB8, 0x88, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, // $00
+       0x98, 0x98, 0xB8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, // $10
+       0xC8, 0xC8, 0xB8, 0xC8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xC9, 0xC9, 0xC9, 0xC9, 0xCB, 0xCB, 0xCB, 0xCB, // $20
+       0xDD, 0xD8, 0x3D, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xD9, 0xD9, 0xD9, 0xD9, 0xDB, 0xDB, 0xDB, 0xDB, // $30
+       0xA8, 0xA8, 0xB8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, // $40
+       0xB9, 0x50, 0xB9, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, // $50
+       0xE8, 0xE8, 0xB8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, // $60
+       0xFD, 0xF8, 0xFD, 0xF8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, // $70
+       0x48, 0x48, 0xB8, 0x48, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, // $80
+       0x09, 0x58, 0xB8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, // $90
+       0x28, 0x28, 0xB8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, // $A0
+       0xC9, 0x38, 0xB9, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, // $B0
+       0x68, 0x68, 0xB8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, // $C0
+       0x0D, 0x78, 0x8D, 0x78, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, // $D0
+       0x18, 0x18, 0xB8, 0xB8, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x08, 0x18, 0x08, 0x18, 0x08, 0x18, 0x08, 0x18, // $E0
+       0x2D, 0x70, 0xBD, 0x70, 0x0A, 0x0A, 0x0A, 0x0A,
+       0x18, 0x08, 0x18, 0x08, 0x18, 0x08, 0x18, 0x08  // $F0
+};
+#endif
+static char nameBuf[MAX_PATH];
 
+// Static in-line functions, for clarity & speed, for swapping variables
 static inline void Swap(uint8_t & a, uint8_t & b)
 {
        uint8_t t = a;
@@ -101,7 +191,6 @@ static inline void Swap(uint8_t & a, uint8_t & b)
        b = t;
 }
 
-
 static inline void Swap(uint32_t & a, uint32_t & b)
 {
        uint32_t t = a;
@@ -109,7 +198,6 @@ static inline void Swap(uint32_t & a, uint32_t & b)
        b = t;
 }
 
-
 static inline void Swap(bool & a, bool & b)
 {
        bool t = a;
@@ -117,7 +205,6 @@ static inline void Swap(bool & a, bool & b)
        b = t;
 }
 
-
 static inline void Swap(uint8_t * & a, uint8_t * & b)
 {
        uint8_t * t = a;
@@ -125,41 +212,30 @@ static inline void Swap(uint8_t * & a, uint8_t * & b)
        b = t;
 }
 
-
-static inline void Swap(WOZ * & a, WOZ * & b)
-{
-       WOZ * t = a;
-       a = b;
-       b = t;
-}
-
-
+//
 // FloppyDrive class implementation...
-
-FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ),  ioHappened(false)
+//
+FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ),  ioHappened(false), diskImageReady(false)
 {
        phase[0] = phase[1] = 0;
        headPos[0] = headPos[1] = 0;
        trackLength[0] = trackLength[1] = 51200;
        disk[0] = disk[1] = NULL;
-       woz[0] = woz[1] = NULL;
        diskSize[0] = diskSize[1] = 0;
        diskType[0] = diskType[1] = DT_EMPTY;
        imageDirty[0] = imageDirty[1] = false;
        imageName[0][0] = imageName[1][0] = 0;                  // Zero out filenames
 }
 
-
 FloppyDrive::~FloppyDrive()
 {
        if (disk[0])
-               delete[] disk[0];
+               free(disk[0]);
 
        if (disk[1])
-               delete[] disk[1];
+               free(disk[1]);
 }
 
-
 bool FloppyDrive::LoadImage(const char * filename, uint8_t driveNum/*= 0*/)
 {
        WriteLog("FLOPPY: Attempting to load image '%s' in drive #%u.\n", filename, driveNum);
@@ -172,40 +248,32 @@ bool FloppyDrive::LoadImage(const char * filename, uint8_t driveNum/*= 0*/)
 
        // Zero out filename, in case it doesn't load
        imageName[driveNum][0] = 0;
+//prolly should load EjectImage() first, so we don't have to dick around with crap
+       uint8_t * buffer = ReadFile(filename, &diskSize[driveNum]);
 
-       FILE * fp = fopen(filename, "rb");
-
-       if (fp == NULL)
+       if (buffer == NULL)
        {
                WriteLog("FLOPPY: Failed to open image file '%s' for reading...\n", filename);
                return false;
        }
 
        if (disk[driveNum])
-               delete[] disk[driveNum];
+               free(disk[driveNum]);
 
-       fseek(fp, 0, SEEK_END);
-       diskSize[driveNum] = ftell(fp);
-       fseek(fp, 0, SEEK_SET);
-       disk[driveNum] =  new uint8_t[diskSize[driveNum]];
-       woz[driveNum] = (WOZ *)disk[driveNum];
-       fread(disk[driveNum], 1, diskSize[driveNum], fp);
+       disk[driveNum] = buffer;
 
-       fclose(fp);
-//printf("Read disk image: %u bytes.\n", diskSize);
+       diskImageReady = false;
        DetectImageType(filename, driveNum);
        strcpy(imageName[driveNum], filename);
+       diskImageReady = true;
 
        WriteLog("FLOPPY: Loaded image '%s' for drive #%u.\n", filename, driveNum);
 
        return true;
 }
 
-
 bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/)
 {
-// comment out for now...
-#if 0
        // Various sanity checks...
        if (driveNum > 1)
        {
@@ -213,44 +281,26 @@ bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/)
                return false;
        }
 
-       if (!imageDirty[driveNum])
-       {
-               WriteLog("FLOPPY: No need to save unchanged image...\n");
-               return false;
-       }
-
-       if (imageName[driveNum][0] == 0)
+       if (diskType[driveNum] == DT_EMPTY)
        {
-               WriteLog("FLOPPY: Attempted to save non-existant image!\n");
+               WriteLog("FLOPPY: No image in drive #%u to save\n", driveNum);
                return false;
        }
 
-       // Finally, write the damn image
-       FILE * fp = fopen(imageName[driveNum], "wb");
-
-       if (fp == NULL)
+       if (!imageDirty[driveNum])
        {
-               WriteLog("FLOPPY: Failed to open image file '%s' for writing...\n", imageName[driveNum]);
+               WriteLog("FLOPPY: No need to save unchanged image in drive #%u...\n", driveNum);
                return false;
        }
 
-       fwrite(disk[driveNum], 1, diskSize[driveNum], fp);
-       fclose(fp);
-
-       WriteLog("FLOPPY: Successfully wrote image file '%s'...\n", imageName[driveNum]);
-
-       return true;
-#else
        char * ext = strrchr(imageName[driveNum], '.');
 
        if ((ext != NULL) && (diskType[driveNum] != DT_WOZ))
                memcpy(ext, ".woz", 4);
 
-       return SaveWOZ(driveNum);
-#endif
+       return SaveWOZ(imageName[driveNum], (WOZ2 *)disk[driveNum], diskSize[driveNum]);
 }
 
-
 bool FloppyDrive::SaveImageAs(const char * filename, uint8_t driveNum/*= 0*/)
 {
        strncpy(imageName[driveNum], filename, MAX_PATH);
@@ -260,32 +310,19 @@ bool FloppyDrive::SaveImageAs(const char * filename, uint8_t driveNum/*= 0*/)
        return SaveImage(driveNum);
 }
 
-
 void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/)
 {
        if (disk[driveNum] != NULL)
-               delete disk[driveNum];
+               free(disk[driveNum]);
 
-       InitWOZ(driveNum);
+       disk[driveNum] = InitWOZ(&diskSize[driveNum]);
        diskType[driveNum] = DT_WOZ;
        strcpy(imageName[driveNum], "newblank.woz");
        SpawnMessage("New blank image inserted in drive %u...", driveNum);
 }
 
-
 void FloppyDrive::SwapImages(void)
 {
-#if 0
-WriteLog("SwapImages BEFORE:\n");
-WriteLog("\tdisk[0]=%X, disk[1]=%X\n", disk[0], disk[1]);
-WriteLog("\twoz[0]=%X, woz[1]=%X\n", woz[0], woz[1]);
-WriteLog("\tdiskSize[0]=%X, diskSize[1]=%X\n", diskSize[0], diskSize[1]);
-WriteLog("\tdiskType[0]=%X, diskType[1]=%X\n", diskType[0], diskType[1]);
-WriteLog("\timageDirty[0]=%X, imageDirty[1]=%X\n", imageDirty[0], imageDirty[1]);
-WriteLog("\tphase[0]=%X, phase[1]=%X\n", phase[0], phase[1]);
-WriteLog("\theadPos[0]=%X, headPos[1]=%X\n", headPos[0], headPos[1]);
-WriteLog("\tcurrentPos[0]=%X, currentPos[1]=%X\n", currentPos[0], currentPos[1]);
-#endif
        char imageNameTmp[MAX_PATH];
 
        memcpy(imageNameTmp, imageName[0], MAX_PATH);
@@ -293,7 +330,6 @@ WriteLog("\tcurrentPos[0]=%X, currentPos[1]=%X\n", currentPos[0], currentPos[1])
        memcpy(imageName[1], imageNameTmp, MAX_PATH);
 
        Swap(disk[0], disk[1]);
-       Swap(woz[0], woz[1]);
        Swap(diskSize[0], diskSize[1]);
        Swap(diskType[0], diskType[1]);
        Swap(imageDirty[0], imageDirty[1]);
@@ -302,31 +338,36 @@ WriteLog("\tcurrentPos[0]=%X, currentPos[1]=%X\n", currentPos[0], currentPos[1])
        Swap(headPos[0], headPos[1]);
        Swap(currentPos[0], currentPos[1]);
 SpawnMessage("Drive 0: %s...", imageName[0]);
-#if 0
-WriteLog("SwapImages AFTER:\n");
-WriteLog("\tdisk[0]=%X, disk[1]=%X\n", disk[0], disk[1]);
-WriteLog("\twoz[0]=%X, woz[1]=%X\n", woz[0], woz[1]);
-WriteLog("\tdiskSize[0]=%X, diskSize[1]=%X\n", diskSize[0], diskSize[1]);
-WriteLog("\tdiskType[0]=%X, diskType[1]=%X\n", diskType[0], diskType[1]);
-WriteLog("\timageDirty[0]=%X, imageDirty[1]=%X\n", imageDirty[0], imageDirty[1]);
-WriteLog("\tphase[0]=%X, phase[1]=%X\n", phase[0], phase[1]);
-WriteLog("\theadPos[0]=%X, headPos[1]=%X\n", headPos[0], headPos[1]);
-WriteLog("\tcurrentPos[0]=%X, currentPos[1]=%X\n", currentPos[0], currentPos[1]);
-#endif
 }
 
-
 /*
-Need to add some type of error checking here, so we can report back on bad images, etc.
+Need to add some type of error checking here, so we can report back on bad images, etc. (basically, it does by returning DFT_UNKNOWN, but we could do better)
 */
 void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum)
 {
        diskType[driveNum] = DFT_UNKNOWN;
 
-       if (memcmp(disk[driveNum], wozHeader, 8) == 0)
+       uint8_t wozType = CheckWOZType(disk[driveNum], diskSize[driveNum]);
+
+       if (wozType > 0)
        {
+               // Check WOZ integrity...
+               CheckWOZIntegrity(disk[driveNum], diskSize[driveNum]);
+
+               // If it's a WOZ type 1 file, upconvert it to type 2
+               if (wozType == 1)
+               {
+                       uint32_t size;
+                       uint8_t * buffer = UpconvertWOZ1ToWOZ2(disk[driveNum], diskSize[driveNum], &size);
+
+                       free(disk[driveNum]);
+                       disk[driveNum] = buffer;
+                       diskSize[driveNum] = size;
+                       WriteLog("FLOPPY: Upconverted WOZ type 1 to type 2...\n");
+               }
+
+               WriteLog("FLOPPY: OBT is %d\n", ((WOZ2 *)disk[driveNum])->optimalBitTmg);
                diskType[driveNum] = DT_WOZ;
-               /*bool r =*/ CheckWOZ(disk[driveNum], diskSize[driveNum], driveNum);
        }
        else if (diskSize[driveNum] == 143360)
        {
@@ -341,8 +382,8 @@ void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum)
                        diskType[driveNum] = DT_PRODOS;
                else if ((strcasecmp(ext, ".do") == 0) || (strcasecmp(ext, ".dsk") == 0))
                {
-                       // We assume this, but check for a PRODOS fingerprint. Trust, but
-                       // verify. ;-)
+                       // We assume this, but check for a PRODOS fingerprint.  Trust, but
+                       // verify.  ;-)
                        diskType[driveNum] = DT_DOS33;
 
                        uint8_t fingerprint[4][4] = {
@@ -384,17 +425,16 @@ void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum)
 // No, we don't nybblize anymore.  But we should tell the user that the loading failed with a return value
 
        WriteLog("FLOPPY: Detected image type %s...\n", (diskType[driveNum] == DT_DOS33 ?
-               "DOS 3.3 image" : (diskType[driveNum] == DT_DOS33_HDR ?
-               "DOS 3.3 image (headered)" : (diskType[driveNum] == DT_PRODOS ? "ProDOS image" : (diskType[driveNum] == DT_WOZ ? "WOZ image" : "unknown")))));
+               "DOS 3.3" : (diskType[driveNum] == DT_DOS33_HDR ?
+               "DOS 3.3 (headered)" : (diskType[driveNum] == DT_PRODOS ? "ProDOS" : (diskType[driveNum] == DT_WOZ ? "WOZ" : "unknown")))));
 }
 
-
 //
 // Write a bitstream (source left justified to bit 7) to destination buffer.
 // Writes 'bits' number of bits to 'dest', starting at bit position 'dstPtr',
 // updating 'dstPtr' for the caller.
 //
-void FloppyDrive::WriteBits(uint8_t * dest, uint8_t * src, uint16_t bits, uint16_t * dstPtr)
+void FloppyDrive::WriteBits(uint8_t * dest, const uint8_t * src, uint16_t bits, uint16_t * dstPtr)
 {
        for(uint16_t i=0; i<bits; i++)
        {
@@ -412,7 +452,6 @@ void FloppyDrive::WriteBits(uint8_t * dest, uint8_t * src, uint16_t bits, uint16
        }
 }
 
-
 void FloppyDrive::WOZifyImage(uint8_t driveNum)
 {
        // hdr (21) + nybbles (343) + footer (48) = 412 bytes per sector
@@ -421,13 +460,13 @@ void FloppyDrive::WOZifyImage(uint8_t driveNum)
 // let's go back to what we had, and see what happens  :-)
 // [still need to expand them back to what they were]
 
-       uint8_t ff10[2] = { 0xFF, 0x00 };
+       const uint8_t ff10[2] = { 0xFF, 0x00 };
        uint8_t addressHeader[14] = {
                0xD5, 0xAA, 0x96, 0xFF, 0xFE, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0xDE, 0xAA, 0xEB };
-       uint8_t sectorHeader[3] = { 0xD5, 0xAA, 0xAD };
-       uint8_t footer[3] = { 0xDE, 0xAA, 0xEB };
-       uint8_t diskbyte[0x40] = {
+       const uint8_t sectorHeader[3] = { 0xD5, 0xAA, 0xAD };
+       const uint8_t footer[3] = { 0xDE, 0xAA, 0xEB };
+       const uint8_t diskbyte[0x40] = {
                0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6,
                0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3,
                0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC,
@@ -436,24 +475,25 @@ void FloppyDrive::WOZifyImage(uint8_t driveNum)
                0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC,
                0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
                0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF };
+       const uint8_t doSector[16] = {
+               0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4, 0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF };
+       const uint8_t poSector[16] = {
+               0x0, 0x8, 0x1, 0x9, 0x2, 0xA, 0x3, 0xB, 0x4, 0xC, 0x5, 0xD, 0x6, 0xE, 0x7, 0xF };
 
        uint8_t tmpNib[343];
-//     memcpy(tmpDisk, disk[driveNum], diskSize[driveNum]);
-//     delete[] disk[driveNum];
+       // Save current image until we're done converting
        uint8_t * tmpDisk = disk[driveNum];
-       disk[driveNum] = NULL;//new uint8_t[diskSize[driveNum]];
 
        // Set up track index...
-//     memcpy(woz[driveNum]->tmap, standardTMAP, 141);
-       InitWOZ(driveNum);
+       disk[driveNum] = InitWOZ(&diskSize[driveNum]);
+       WOZ2 & woz = *((WOZ2 *)disk[driveNum]);
 
        // Upconvert data from DSK & friends format to WOZ tracks  :-)
        for(uint8_t trk=0; trk<35; trk++)
        {
                uint16_t dstBitPtr = 0;
-               uint8_t * img = woz[driveNum]->track[trk].bits;
-//already done
-//             memset(img, 0, 6646);
+               uint8_t * img = disk[driveNum] + (Uint16LE(woz.track[trk].startingBlock) * 512);
+//printf("Converting track %u: startingBlock=%u, %u blocks, img=%X\n", trk, Uint16LE(woz.track[trk].startingBlock), Uint16LE(woz.track[trk].blockCount), img);
 
                // Write self-sync header bytes (16, should it be 64? Dunno.)
                for(int i=0; i<64; i++)
@@ -478,7 +518,6 @@ void FloppyDrive::WOZifyImage(uint8_t driveNum)
 
                        // Write sector header (D5 AA AD)
                        WriteBits(img, sectorHeader, 3 * 8, &dstBitPtr);
-//                     uint8_t * bytes = disk[driveNum];
                        uint8_t * bytes = tmpDisk;
 
 //Need to fix this so it writes the correct sector in the correct place *and* put the correct sector # into the header above as well.  !!! FIX !!!
@@ -529,14 +568,13 @@ void FloppyDrive::WOZifyImage(uint8_t driveNum)
                }
 
                // Set the proper bit/byte lengths in the WOZ for this track
-               woz[driveNum]->track[trk].bitCount = Uint16LE(dstBitPtr);
-               woz[driveNum]->track[trk].byteCount = Uint16LE((dstBitPtr + 7) / 8);
+               woz.track[trk].bitCount = Uint16LE(dstBitPtr);
        }
 
-       delete[] tmpDisk;
+       // Finally, free the non-WOZ image now that we're done converting
+       free(tmpDisk);
 }
 
-
 const char * FloppyDrive::ImageName(uint8_t driveNum/*= 0*/)
 {
        // Set up a zero-length string for return value
@@ -573,7 +611,6 @@ const char * FloppyDrive::ImageName(uint8_t driveNum/*= 0*/)
        return nameBuf;
 }
 
-
 void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/)
 {
        // Sanity check
@@ -585,17 +622,15 @@ void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/)
                WriteLog("FLOPPY: Ejected image file '%s' from drive %u...\n", imageName[driveNum], driveNum);
 
        if (disk[driveNum])
-               delete[] disk[driveNum];
+               free(disk[driveNum]);
 
        disk[driveNum] = NULL;
-       woz[driveNum] = NULL;
        diskSize[driveNum] = 0;
        diskType[driveNum] = DT_EMPTY;
        imageDirty[driveNum] = false;
        imageName[driveNum][0] = 0;                     // Zero out filenames
 }
 
-
 bool FloppyDrive::IsEmpty(uint8_t driveNum/*= 0*/)
 {
        if (driveNum > 1)
@@ -607,7 +642,6 @@ bool FloppyDrive::IsEmpty(uint8_t driveNum/*= 0*/)
        return (diskType[driveNum] == DT_EMPTY ? true : false);
 }
 
-
 bool FloppyDrive::IsWriteProtected(uint8_t driveNum/*= 0*/)
 {
        if (driveNum > 1)
@@ -616,10 +650,10 @@ bool FloppyDrive::IsWriteProtected(uint8_t driveNum/*= 0*/)
                return true;
        }
 
-       return (bool)woz[driveNum]->writeProtected;
+       WOZ2 & woz = *((WOZ2 *)disk[driveNum]);
+       return (bool)woz.writeProtected;
 }
 
-
 void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/)
 {
        if (driveNum > 1)
@@ -628,10 +662,10 @@ void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/)
                return;
        }
 
-       woz[driveNum]->writeProtected = (uint8_t)state;
+       WOZ2 & woz = *((WOZ2 *)disk[driveNum]);
+       woz.writeProtected = (uint8_t)state;
 }
 
-
 int FloppyDrive::DriveLightStatus(uint8_t driveNum/*= 0*/)
 {
        int retval = DLS_OFF;
@@ -646,7 +680,6 @@ int FloppyDrive::DriveLightStatus(uint8_t driveNum/*= 0*/)
        return retval;
 }
 
-
 void FloppyDrive::SaveState(FILE * file)
 {
        // Internal state vars
@@ -687,7 +720,6 @@ void FloppyDrive::SaveState(FILE * file)
                WriteLong(file, 0);
 }
 
-
 void FloppyDrive::LoadState(FILE * file)
 {
        // Eject images if they're loaded
@@ -713,7 +745,6 @@ void FloppyDrive::LoadState(FILE * file)
                imageDirty[0] = (fgetc(file) == 1 ? true : false);
                fread(disk[0], 1, diskSize[0], file);
                fread(imageName[0], 1, MAX_PATH, file);
-               woz[0] = (WOZ *)disk[0];
        }
 
        diskSize[1] = ReadLong(file);
@@ -728,11 +759,9 @@ void FloppyDrive::LoadState(FILE * file)
                imageDirty[1] = (fgetc(file) == 1 ? true : false);
                fread(disk[1], 1, diskSize[1], file);
                fread(imageName[1], 1, MAX_PATH, file);
-               woz[1] = (WOZ *)disk[1];
        }
 }
 
-
 uint32_t FloppyDrive::ReadLong(FILE * file)
 {
        uint32_t r = 0;
@@ -743,7 +772,6 @@ uint32_t FloppyDrive::ReadLong(FILE * file)
        return r;
 }
 
-
 void FloppyDrive::WriteLong(FILE * file, uint32_t l)
 {
        for(int i=0; i<4; i++)
@@ -753,31 +781,6 @@ void FloppyDrive::WriteLong(FILE * file, uint32_t l)
        }
 }
 
-
-void FloppyDrive::WriteLongLE(FILE * file, uint32_t l)
-{
-       for(int i=0; i<4; i++)
-       {
-               fputc(l & 0xFF, file);
-               l >>= 8;
-       }
-}
-
-
-void FloppyDrive::WriteWordLE(FILE * file, uint16_t w)
-{
-       fputc(w & 0xFF, file);
-       fputc((w >> 8) & 0xFF, file);
-}
-
-
-void FloppyDrive::WriteZeroes(FILE * file, uint32_t num)
-{
-       for(uint32_t i=0; i<num; i++)
-               fputc(0, file);
-}
-
-
 // Memory mapped I/O functions + Logic State Sequencer
 
 /*
@@ -802,6 +805,9 @@ N.B.: Though the NIB format is *closer* to the representation of the disk's
 According to Beneath Apple DOS, DOS checks the data register to see if it changes when spinning up a drive: "A sufficient delay should be provided to allow the motor time to come up to speed.  Shugart recommends one second, but DOS is able to reduce this delay by watching the read latch until data starts to change."  Which means, we can simulate an empty/off drive by leaving the data register alone.
 */
 
+uint64_t stepperTime = 0;
+bool seenReadSinceStep = false;
+uint16_t iorAddr;
 void FloppyDrive::ControlStepper(uint8_t addr)
 {
        // $C0E0 - 7
@@ -811,12 +817,41 @@ How It Works
 The stepper motor has 4 phase solenoids (numbered 0-3) which corresponds to bits 1-2 of the address.  Bit 0 tells the phase solenoid to either energize (1) or de-energize (0).  By energizing the phase solenoids in ascending order, the stepper motor moves the head from a low numbered track to a higher numbered track; conversely, by energizing the solenoids in descending order, the stepper motor moves the head from a high numbered track to a lower one.  Given that this is a mechanical device, it takes a certain amount of time for the drum in the stepper motor to move from place to place--though pretty much all software written for the Disk II takes this into account.
 
 Tracks can apparently go from 0 to 79, though typically only 0 to 69 are usuable.  Further, because of the limitations of the read/write head of the drive, not every track can be written to, so typically (about 99.99% of the time in my guesstimation) only every *other* track is written to (phases 0 and 2); some disks exist that have tracks written on phase 1 or 3, but these tend to be the exception rather than the rule.
+
+Taking into account the head slew time: ATM nothing seems to look at it, though it could be problematic as how we emulate it is different from how it actually works; namely, the emulator zaps the head to a new track instantly when the write to the phase happens while in the real thing, obviously this takes a non-zero amount of time.  As such, none of the states where more than one phase solenoid is active at a time can be written so that they come on instantaneously; it would be fairly easy to write things that work on the real thing that don't on the emulator because of this.  But most software (pretty much everything that I've ever seen) is pretty well behaved and this isn't an issue.
+
+If it ever *does* become a problem, doing the physical modeling of the head moving at a real velocity shouldn't be that difficult to do.
 */
+
+       // This is an array of stub positions crossed with solenoid energize
+       // patterns.  The numbers represent how many quarter tracks the head will
+       // move given its current position and the pattern of energized solenoids.
+       // N.B.: Patterns for 11 & 13 haven't been filled in as I'm not sure how
+       //       the stub(s) would react to those patterns.  :-/
+       int16_t step[16][8] = {
+               {  0,  0,  0,  0,  0,  0,  0,  0 },  // [....]
+               {  0, -1, -2,  0,  0,  0, +2, +1 },  // [|...]
+               { +2, +1,  0, -1, -2,  0,  0,  0 },  // [.|..]
+               { +1,  0, -1, -2, -3,  0, +3, +2 },  // [||..]
+               {  0,  0, +2, +1,  0, -1, -2,  0 },  // [..|.]
+               {  0, -1,  0, +1,  0, -1,  0, +1 },  // [|.|.]
+               { +3, +2, +1,  0, -1, -2, -3,  0 },  // [.||.]
+               { +2, +1,  0, -1, -2, -3,  0, +3 },  // [|||.]
+               { -2,  0,  0,  0, +2, +1,  0, -1 },  // [...|]
+               { -1, -2, -3,  0, +3, +2, +1,  0 },  // [|..|]
+               {  0, +1,  0, -1,  0, +1,  0, -1 },  // [.|.|]
+               {  0,  0,  0,  0,  0,  0,  0,  0 },  // [||.|] ???
+               { -3,  0, +3, +2, +1,  0, -1, -2 },  // [..||]
+               {  0,  0,  0,  0,  0,  0,  0,  0 },  // [|.||] ???
+               {  0, +3, +2, +1,  0, -1, -2, -3 },  // [.|||]
+               { -1, +2, +1,  0, -1, -2, +1,  0 }   // [||||]
+       };
+
        // Sanity check
        if (diskType[activeDrive] == DT_EMPTY)
                return;
 
-       // Convert phase solenoid number into a bit from 1 through 8:
+       // Convert phase solenoid number into a bit from 1 through 8 [1, 2, 4, 8]:
        uint8_t phaseBit = 1 << ((addr >> 1) & 0x03);
 
        // Set the state of the phase solenoid accessed using the phase bit
@@ -825,39 +860,42 @@ Tracks can apparently go from 0 to 79, though typically only 0 to 69 are usuable
        else
                phase[activeDrive] &= ~phaseBit;
 
-       // See if the new phase solenoid is energized, & move the stepper/head
-       // appropriately.
-       // N.B.: The head stub is located by bits 1 & 2 of the headPos variable
-       uint8_t oldHeadPos = headPos[activeDrive];
-       uint8_t nextUp     = 1 << (((oldHeadPos >> 1) + 1) & 0x03);
-       uint8_t nextDown   = 1 << (((oldHeadPos >> 1) - 1) & 0x03);
+       int16_t oldHeadPos = headPos[activeDrive];
+       int16_t newStep = step[phase[activeDrive]][oldHeadPos & 0x07];
+       int16_t newHeadPos = (int16_t)headPos[activeDrive] + newStep;
+WriteLog("\nFLOPPY: oldHeadPos=%u, newHeadPos=%i, newStep=%i\n", oldHeadPos, newHeadPos, newStep);
 
-       // We simulate cogging here by seeing if there's a valid up and/or down
-       // position to go to.  If both are valid, the head goes nowhere.
-       if (phase[activeDrive] & nextUp)
-               headPos[activeDrive] += (headPos[activeDrive] < 140 ? 2 : 0);
-
-       if (phase[activeDrive] & nextDown)
-               headPos[activeDrive] -= (headPos[activeDrive] > 0 ? 2 : 0);
+       // Sanity check
+       // N.B.: This is wrong for 3.5" disks
+       if ((newHeadPos >= 0) && (newHeadPos <= 140))
+               headPos[activeDrive] = (uint8_t)newHeadPos;
 
        if (oldHeadPos != headPos[activeDrive])
        {
-               uint8_t newTIdx = woz[activeDrive]->tmap[headPos[activeDrive]];
-               float newBitLen = (newTIdx == 0xFF ? 51200.0f
-                       : Uint16LE(woz[activeDrive]->track[newTIdx].bitCount));
-
-               uint8_t oldTIdx = woz[activeDrive]->tmap[oldHeadPos];
-               float oldBitLen = (oldTIdx == 0xFF ? 51200.0f
-                       : Uint16LE(woz[activeDrive]->track[oldTIdx].bitCount));
+               WOZ2 & woz = *((WOZ2 *)disk[activeDrive]);
+               uint8_t newTIdx = woz.tmap[headPos[activeDrive]];
+               float newBitLen = (newTIdx == 0xFF
+                       ? 51200.0f : Uint16LE(woz.track[newTIdx].bitCount));
+
+               uint8_t oldTIdx = woz.tmap[oldHeadPos];
+               float oldBitLen = (oldTIdx == 0xFF
+                       ? 51200.0f : Uint16LE(woz.track[oldTIdx].bitCount));
+WriteLog("FLOPPY: Current pos pre: %u, ", currentPos[activeDrive]);
                currentPos[activeDrive] = (uint32_t)((float)currentPos[activeDrive] * (newBitLen / oldBitLen));
+WriteLog("post: %u; newBitLen/old = %.1f/%.1f\n", currentPos[activeDrive], newBitLen, oldBitLen);
 
                trackLength[activeDrive] = (uint16_t)newBitLen;
                SpawnMessage("Stepping to track %u...", headPos[activeDrive] >> 2);
        }
 
-WriteLog("FLOPPY: Stepper phase %d set to %s [%c%c%c%c] (track=%2.2f)\n", (addr >> 1) & 0x03, (addr & 0x01 ? "ON " : "off"), (phase[activeDrive] & 0x08 ? '|' : '.'), (phase[activeDrive] & 0x04 ? '|' : '.'), (phase[activeDrive] & 0x02 ? '|' : '.'), (phase[activeDrive] & 0x01 ? '|' : '.'), (float)headPos[activeDrive] / 4.0f);
+// only check the time since the phase was first set ON
+if (addr & 0x01)
+{
+       stepperTime = mainCPU.clock;
+       seenReadSinceStep = false;
+}
+WriteLog("FLOPPY: Stepper phase %d set to %s [%c%c%c%c] (track=%2.2f) [%u]\n", (addr >> 1) & 0x03, (addr & 0x01 ? "ON " : "off"), (phase[activeDrive] & 0x08 ? '|' : '.'), (phase[activeDrive] & 0x04 ? '|' : '.'), (phase[activeDrive] & 0x02 ? '|' : '.'), (phase[activeDrive] & 0x01 ? '|' : '.'), (float)headPos[activeDrive] / 4.0f, mainCPU.clock & 0xFFFFFFFF);
 }
-
 
 void FloppyDrive::ControlMotor(uint8_t addr)
 {
@@ -872,7 +910,6 @@ void FloppyDrive::ControlMotor(uint8_t addr)
 WriteLog("FLOPPY: Turning drive motor %s\n", (motorOn ? "ON" : "off"));
 }
 
-
 void FloppyDrive::DriveEnable(uint8_t addr)
 {
        // $C0EA - B
@@ -880,7 +917,6 @@ void FloppyDrive::DriveEnable(uint8_t addr)
 WriteLog("FLOPPY: Selecting drive #%hhd\n", addr + 1);
 }
 
-
 /*
 So for $C08C-F, we have two switches (Q6 & Q7) which combine to make four states ($C-D is off/on for Q6, $E-F is off/on for Q7).
 
@@ -896,40 +932,44 @@ Looks like reads from even addresses in $C080-F block transfer data from the seq
 
 */
 
-
 void FloppyDrive::SetShiftLoadSwitch(uint8_t state)
 {
        // $C0EC - D
        slSwitch = state;
 }
 
-
 void FloppyDrive::SetReadWriteSwitch(uint8_t state)
 {
        // $C0EE - F
        rwSwitch = state;
 }
 
-
 // MMIO: Reads from $C08x to $C0XX on even addresses
 uint8_t FloppyDrive::DataRegister(void)
 {
        // Sanity check
        if (diskType[activeDrive] != DT_EMPTY)
        {
-               uint8_t tIdx = woz[activeDrive]->tmap[headPos[activeDrive]];
+               WOZ2 & woz = *((WOZ2 *)disk[activeDrive]);
+               uint8_t tIdx = woz.tmap[headPos[activeDrive]];
                uint32_t bitLen = (tIdx == 0xFF ? 51200
-                       : Uint16LE(woz[activeDrive]->track[tIdx].bitCount));
+                       : Uint16LE(woz.track[tIdx].bitCount));
                SpawnMessage("%u:Reading $%02X from track %u, sector %u...",
                        activeDrive, dataRegister, headPos[activeDrive] >> 2, (uint32_t)(((float)currentPos[activeDrive] / (float)bitLen) * 16.0f));
                ioMode = IO_MODE_READ;
                ioHappened = true;
+
+if ((seenReadSinceStep == false) && (slSwitch == false) && (rwSwitch == false) && ((iorAddr & 0x0F) == 0x0C))
+{
+       seenReadSinceStep = true;
+       WriteLog("%u:Reading $%02X from track %2.2f, sector %u (delta since seek: %lu cycles) [%u]...\n",
+               activeDrive, dataRegister, (float)headPos[activeDrive] / 4.0f, (uint32_t)(((float)currentPos[activeDrive] / (float)bitLen) * 16.0f), mainCPU.clock - stepperTime, mainCPU.clock & 0xFFFFFFFF);
+}
        }
 
        return dataRegister;
 }
 
-
 // MMIO: Writes from $C08x to $C0XX on odd addresses
 void FloppyDrive::DataRegister(uint8_t data)
 {
@@ -938,7 +978,6 @@ void FloppyDrive::DataRegister(uint8_t data)
        ioHappened = true;
 }
 
-
 /*
         OFF switches                ON switches
 Switch  Addr   Func                 Addr   Func
@@ -1003,194 +1042,6 @@ $57:    Duplicate volume
 $5A:    File structure damaged
 */
 
-
-//
-// This is used mainly to initialize blank disks and upconvert non-WOZ disks
-//
-void FloppyDrive::InitWOZ(uint8_t driveNum/*= 0*/)
-{
-       // Sanity check
-       if (disk[driveNum] != NULL)
-       {
-               WriteLog("FLOPPY: Attempted to initialize non-NULL WOZ structure\n");
-               return;
-       }
-
-       diskSize[driveNum] = 256 + (35 * sizeof(WOZTrack));
-       disk[driveNum] = new uint8_t[diskSize[driveNum]];
-       woz[driveNum] = (WOZ *)disk[driveNum];
-
-       // Zero out WOZ image in memory
-       memset(woz[driveNum], 0, diskSize[driveNum]);
-
-       // Set up header (leave CRC as 0 for now)
-       memcpy(woz[driveNum]->magic, wozHeader, 8);
-
-       // INFO header
-       memcpy(woz[driveNum]->infoTag, "INFO", 4);
-       woz[driveNum]->infoSize = Uint32LE(60);
-       woz[driveNum]->infoVersion = 1;
-       woz[driveNum]->diskType = 1;
-       woz[driveNum]->writeProtected = 0;
-       woz[driveNum]->synchronized = 0;
-       woz[driveNum]->cleaned = 1;
-       memset(woz[driveNum]->creator, ' ', 32);
-       memcpy(woz[driveNum]->creator, "Apple2 emulator v1.0.0", 22);
-
-       // TMAP header
-       memcpy(woz[driveNum]->tmapTag, "TMAP", 4);
-       woz[driveNum]->tmapSize = Uint32LE(160);
-       memcpy(woz[driveNum]->tmap, standardTMAP, 141);
-
-       // TRKS header
-       memcpy(woz[driveNum]->trksTag, "TRKS", 4);
-       woz[driveNum]->trksSize = Uint32LE(35 * sizeof(WOZTrack));
-
-       for(int i=0; i<35; i++)
-       {
-               woz[driveNum]->track[i].bitCount = Uint16LE(51200);
-               woz[driveNum]->track[i].byteCount = Uint16LE((51200 + 7) / 8);
-       }
-
-       // META header (how to handle? prolly with a separate pointer)
-}
-
-
-//
-// Do basic sanity checks on the passed in contents (file loaded elsewhere).
-// Returns true if successful, false on failure.
-//
-bool FloppyDrive::CheckWOZ(const uint8_t * wozData, uint32_t wozSize, uint8_t driveNum/*= 0*/)
-{
-       // Hey!  This reference works!!  :-D
-       WOZ & woz1 = *((WOZ *)wozData);
-       woz[driveNum] = (WOZ *)wozData;
-
-       // Basic sanity checking
-       if (wozData == NULL)
-       {
-               WriteLog("FLOPPY: NULL pointer passed in to CheckWOZ()...\n");
-               return false;
-       }
-
-       if (memcmp(woz1.magic, wozHeader, 8) != 0)
-       {
-               WriteLog("FLOPPY: Invalid WOZ header in file\n");
-               return false;
-       }
-
-       uint32_t crc = CRC32(&wozData[12], wozSize - 12);
-       uint32_t wozCRC = Uint32LE(woz1.crc32);
-
-       if ((wozCRC != 0) && (wozCRC != crc))
-       {
-               WriteLog("FLOPPY: Corrupted data found in WOZ. CRC32: %08X, computed: %08X\n", wozCRC, crc);
-               return false;
-       }
-       else if (wozCRC == 0)
-               WriteLog("FLOPPY: Warning--WOZ file has no CRC...\n");
-
-#if 1
-       WriteLog("Track map:\n");
-       WriteLog("                                        1   1   1   1   1   1   1   1\n");
-       WriteLog("0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.\n");
-       WriteLog("------------------------------------------------------------------------\n");
-
-       for(uint8_t j=0; j<2; j++)
-       {
-               for(uint8_t i=0; i<72; i++)
-               {
-                       char buf[64] = "..";
-                       buf[0] = buf[1] = '.';
-
-                       if (woz1.tmap[i] != 0xFF)
-                               sprintf(buf, "%02d", woz1.tmap[i]);
-
-                       WriteLog("%c", buf[j]);
-               }
-
-               WriteLog("\n");
-       }
-
-       WriteLog("\n1   1   2   2   2   2   2   2   2   2   2   2   3   3   3   3   3   3\n");
-       WriteLog("8.,.9.,.0.,.1.,.2.,.3.,.4.,.5.,.6.,.7.,.8.,.9.,.0.,.1.,.2.,.3.,.4.,.5\n");
-       WriteLog("---------------------------------------------------------------------\n");
-
-       for(uint8_t j=0; j<2; j++)
-       {
-               for(uint8_t i=72; i<141; i++)
-               {
-                       char buf[64] = "..";
-
-                       if (woz1.tmap[i] != 0xFF)
-                               sprintf(buf, "%02d", woz1.tmap[i]);
-
-                       WriteLog("%c", buf[j]);
-               }
-
-               WriteLog("\n");
-       }
-
-       WriteLog("\n");
-
-       uint8_t numTracks = woz1.trksSize / sizeof(WOZTrack);
-
-       // N.B.: Need to check the track[] to have this tell the correct track...  Right now, it doesn't
-       for(uint8_t i=0; i<numTracks; i++)
-       {
-               WriteLog("WOZ: Track %2.2f: %d bits (packed into %d bytes)\n", (float)i / 4.0f, woz1.track[i].bitCount, woz1.track[i].byteCount);
-       }
-#endif
-
-       WriteLog("FLOPPY: Well formed WOZ file found\n");
-       return true;
-}
-
-
-bool FloppyDrive::SaveWOZ(uint8_t driveNum)
-{
-       // Various sanity checks...
-       if (driveNum > 1)
-       {
-               WriteLog("FLOPPY: Attempted to save image to drive #%u!\n", driveNum);
-               return false;
-       }
-
-       if (diskType[driveNum] == DT_EMPTY)
-       {
-               WriteLog("FLOPPY: No image in drive #%u to save\n", driveNum);
-               return false;
-       }
-
-       if (!imageDirty[driveNum])
-       {
-               WriteLog("FLOPPY: No need to save unchanged image in drive #%u...\n", driveNum);
-               return false;
-       }
-
-       // Set up CRC32 before writing
-       woz[driveNum]->crc32 = Uint32LE(CRC32(&disk[driveNum][12], diskSize[driveNum] - 12));
-
-       // META header (skip for now) (actually, should be in the disk[] image already)
-
-       // Finally, write the damn image
-       FILE * fp = fopen(imageName[driveNum], "wb");
-
-       if (fp == NULL)
-       {
-               WriteLog("FLOPPY: Failed to open image file '%s' for writing...\n", imageName[driveNum]);
-               return false;
-       }
-
-       fwrite(disk[driveNum], 1, diskSize[driveNum], fp);
-       fclose(fp);
-
-       WriteLog("FLOPPY: Successfully wrote image file '%s'...\n", imageName[driveNum]);
-
-       return true;
-}
-
-
 // N.B.: The WOZ documentation says that the bitstream is normalized to 4µs.
 //       Which means on the //e that you would have to run it at that clock
 //       rate (instead of the //e clock rate 0.9799µs/cycle) to get the
@@ -1199,9 +1050,11 @@ bool FloppyDrive::SaveWOZ(uint8_t driveNum)
 //       which will make the simulated drive run in the neighborhood of around
 //       306 RPM.  Should be close enough to get away with it.  :-)  (And it
 //       seems to run OK, for the most part.)
-
+//
+//       According to EDD 4 the drive is running at 299.1 RPM...  :-/
 
 static bool logSeq = false;
+char sequence[1024];
 //
 // Logic State Sequencer & Data Register
 //
@@ -1210,16 +1063,25 @@ void FloppyDrive::RunSequencer(uint32_t cyclesToRun)
        static uint32_t prng = 1;
 
        // Sanity checks
-       if (diskType[activeDrive] == DT_EMPTY)
+       if (!diskImageReady)
+               return;
+       else if (diskType[activeDrive] == DT_EMPTY)
                return;
        else if (motorOn == false)
        {
                if (driveOffTimeout == 0)
                        return;
-               else
-                       driveOffTimeout--;
+
+               driveOffTimeout--;
        }
 
+       WOZ2 & woz = *((WOZ2 *)disk[activeDrive]);
+       uint8_t tIdx = woz.tmap[headPos[activeDrive]];
+       uint8_t * tdata = disk[activeDrive] + (Uint16LE(woz.track[tIdx].startingBlock) * 512);
+       // We have to divide the optimal bit timing by 4 because we only have a 0.5µs granularity here (with the doubling of the "cyclesToRun").  The OBT has a granularity of 0.125µs.  Not sure how to fix that--have to separate the pulse handling from the sequencer?
+       // N.B.: Border Zone has an OBT of 28, when divides evenly by 4, but it still fails...
+       uint8_t pulseTiming = woz.optimalBitTmg / 4;
+
        // It's x2 because the sequencer clock runs twice as fast as the CPU clock.
        cyclesToRun *= 2;
 
@@ -1234,38 +1096,36 @@ if (logSeq)
 
        while (cyclesToRun-- > 0)
        {
-               pulseClock = (pulseClock + 1) & 0x07;
+//             pulseClock = (pulseClock + 1) & 0x07;
+//             pulseClock = (pulseClock + 1) % 8;
+               pulseClock = (pulseClock + 1) % pulseTiming;
+// 7 doesn't work...  Is that 3.5µs?  Seems to be.  Which means to get a 0.25µs granularity here, we need to double the # of cycles to run...
+//             pulseClock = (pulseClock + 1) % 7;
 
                if (pulseClock == 0)
                {
                        uint16_t bytePos = currentPos[activeDrive] / 8;
                        uint8_t bitPos = currentPos[activeDrive] % 8;
-                       uint8_t tIdx = woz[activeDrive]->tmap[headPos[activeDrive]];
+                       window <<= 1;
 
                        if (tIdx != 0xFF)
                        {
-                               if (woz[activeDrive]->track[tIdx].bits[bytePos] & bitMask[bitPos])
+                               if (tdata[bytePos] & bitMask[bitPos])
                                {
                                        // According to Jim Sather (Understanding the Apple II),
                                        // the Read Pulse, when it happens, is 1µs long, which is 2
-                                       // sequencer clock pulses long.
-                                       readPulse = 2;
+                                       // sequencer clock pulses long.  (Not sure where, elsewhere, on pg. 9-29 it says it lasts one *sequencer* clock pulse.)
+                                       readPulse = 1;//2;
                                        zeroBitCount = 0;
+                                       window |= 0x01;
                                }
                                else
                                        zeroBitCount++;
-#if 0
-                               currentPos[activeDrive] = (currentPos[activeDrive] + 1) % Uint16LE(woz[activeDrive]->track[tIdx].bitCount);
-                       }
-                       else
-                               currentPos[activeDrive] = (currentPos[activeDrive] + 1) % 51200;
-#else
+//WriteLog("[%d]", tdata[bytePos] & bitMask[bitPos] ? 1 : 0);
                        }
 
-//this doesn't work reliably for some reason...
-//seems to work OK now...
+                       readPulse = (window >> 1) & 0x01; // Read pulse delayed by about 5µs
                        currentPos[activeDrive] = (currentPos[activeDrive] + 1) % trackLength[activeDrive];
-#endif
 
                        // If we hit more than 2 zero bits in a row, simulate the disk head
                        // reader's Automatic Gain Control (AGC) turning itself up too high
@@ -1274,13 +1134,14 @@ if (logSeq)
 /*
 N.B.: Had to up this to 3 because Up N' Down had some weird sync bytes (FE10).  May have to up it some more.
 */
-                       if ((zeroBitCount > 3) || (tIdx == 0xFF))
+//                     if ((zeroBitCount > 3) || (tIdx == 0xFF))
+                       if (((window & 0x0F) == 0) || (tIdx == 0xFF))
                        {
                                if (prng & 0x00001)
                                {
                                        // This PRNG is called the "Galois configuration".
                                        prng ^= 0x24000;
-                                       readPulse = 2;
+                                       readPulse = 1;//2;
                                }
 
                                prng >>= 1;
@@ -1294,23 +1155,40 @@ N.B.: Had to up this to 3 because Up N' Down had some weird sync bytes (FE10).
 if (logSeq)
        WriteLog("[%02X:%02X]%s", sequencerState, nextState, (chop == 15 ? "\n" : ""));
 chop = (chop + 1) % 20;
+#ifndef TEST13
                sequencerState = sequencerROM[nextState];
+#else
+//             sequencerState = sequencerROM13[nextState];
+               sequencerState = sequencerROM[nextState];
+#endif
+
+#if 0
+uint32_t seqLen = strlen(sequence);
+
+if (seqLen + 7 > 1023)
+{
+       sequence[0] = 0;
+       seqLen = 0;
+}
+
+sprintf(&sequence[seqLen], "(%02X)%02X ", nextState, sequencerState);
+#endif
 
                switch (sequencerState & 0x0F)
                {
                case 0x00:
-               case 0x01:
-               case 0x02:
-               case 0x03:
-               case 0x04:
-               case 0x05:
-               case 0x06:
-               case 0x07:
-                       // CLR (clear data register)
+//             case 0x01:
+//             case 0x02:
+//             case 0x03:
+//             case 0x04:
+//             case 0x05:
+//             case 0x06:
+//             case 0x07:
+                       // CLR (clear data register; 0)
                        dataRegister = 0;
                        break;
                case 0x08:
-               case 0x0C:
+//             case 0x0C:
                        // NOP (no operation)
                        break;
                case 0x09:
@@ -1318,10 +1196,8 @@ chop = (chop + 1) % 20;
                        dataRegister <<= 1;
 //if (!stopWriting)
 {
-                       uint8_t tIdx = woz[activeDrive]->tmap[headPos[activeDrive]];
-
                        if (rwSwitch && (tIdx != 0xFF)
-                               && !woz[activeDrive]->writeProtected)
+                               && !woz.writeProtected)
                        {
                                imageDirty[activeDrive] = true;
                                uint16_t bytePos = currentPos[activeDrive] / 8;
@@ -1329,10 +1205,10 @@ chop = (chop + 1) % 20;
 
                                if (dataRegister & 0x80)
                                        // Fill in the one, if necessary
-                                       woz[activeDrive]->track[tIdx].bits[bytePos] |= bitMask[bitPos];
+                                       tdata[bytePos] |= bitMask[bitPos];
                                else
                                        // Otherwise, punch in the zero
-                                       woz[activeDrive]->track[tIdx].bits[bytePos] &= ~bitMask[bitPos];
+                                       tdata[bytePos] &= ~bitMask[bitPos];
 
 #if 0
 if (dumpDis || tripwire)
@@ -1350,26 +1226,23 @@ lastPos = currentPos[activeDrive];
 }
                        break;
                case 0x0A:
-               case 0x0E:
+//             case 0x0E:
                        // SR (shift right write protect bit)
                        dataRegister >>= 1;
-                       dataRegister |= (woz[activeDrive]->writeProtected ? 0x80 : 0x00);
+                       dataRegister |= (woz.writeProtected ? 0x80 : 0x00);
                        break;
                case 0x0B:
-               case 0x0F:
+//             case 0x0F:
                        // LD (load data register from data bus)
                        dataRegister = cpuDataBus;
 //if (!stopWriting)
 {
-                       uint8_t tIdx = woz[activeDrive]->tmap[headPos[activeDrive]];
-
-                       if (rwSwitch && (tIdx != 0xFF)
-                               && !woz[activeDrive]->writeProtected)
+                       if (rwSwitch && (tIdx != 0xFF) && !woz.writeProtected)
                        {
                                imageDirty[activeDrive] = true;
                                uint16_t bytePos = currentPos[activeDrive] / 8;
                                uint8_t bitPos = currentPos[activeDrive] % 8;
-                               woz[activeDrive]->track[tIdx].bits[bytePos] |= bitMask[bitPos];
+                               tdata[bytePos] |= bitMask[bitPos];
 #if 0
 if (dumpDis || tripwire)
 {
@@ -1390,6 +1263,9 @@ lastPos = currentPos[activeDrive];
                        dataRegister <<= 1;
                        dataRegister |= 0x01;
                        break;
+               default:
+                       // 1-7, $C, $E, & $F are all invalid opcodes
+                       WriteLog("Invalid LSS state encountered! (opcode: $%X [full state: $%02X])\n", sequencerState & 0x0F, sequencerState);
                }
 
                if (readPulse > 0)
@@ -1400,7 +1276,6 @@ if (logSeq)
        WriteLog("\n");
 }
 
-
 FloppyDrive floppyDrive[2];
 
 static uint8_t SlotIOR(uint16_t address)
@@ -1437,12 +1312,13 @@ static uint8_t SlotIOR(uint16_t address)
                break;
        }
 
+//temp, for debugging
+iorAddr = address;
        // Even addresses return the data register, odd (we suppose) returns a
        // floating bus read...
        return (address & 0x01 ? ReadFloatingBus(0) : floppyDrive[0].DataRegister());
 }
 
-
 static void SlotIOW(uint16_t address, uint8_t byte)
 {
        uint8_t state = address & 0x0F;
@@ -1488,13 +1364,15 @@ static void SlotIOW(uint16_t address, uint8_t byte)
 // of FloppyDrive
 static uint8_t SlotROM(uint16_t address)
 {
+#ifndef TEST13
        return diskROM[address];
+#else
+       return diskROM13[address];
+#endif
 }
 
-
 void InstallFloppy(uint8_t slot)
 {
        SlotData disk = { SlotIOR, SlotIOW, SlotROM, 0, 0, 0 };
        InstallSlotHandler(slot, &disk);
 }
-