X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffloppydrive.cpp;h=92917191dd10e16c5bb9a57c3a96fae444f3e437;hb=695e6c22a404fc7e4141a5c8e5ceda10d48c7fd3;hp=ffae0634bdb405cfd86181aeb4439843ea0e4fe4;hpb=e4b94bfc1e03e2c2848ab34e5f0cd8790e10f4b3;p=apple2 diff --git a/src/floppydrive.cpp b/src/floppydrive.cpp index ffae063..9291719 100644 --- a/src/floppydrive.cpp +++ b/src/floppydrive.cpp @@ -26,6 +26,9 @@ #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 }; @@ -33,28 +36,153 @@ enum { IO_MODE_READ, IO_MODE_WRITE }; // 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, - 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 + 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 }; +#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 +#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) { @@ -63,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; @@ -71,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; @@ -79,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; @@ -87,9 +212,9 @@ static inline void Swap(uint8_t * & a, uint8_t * & b) b = t; } - +// // FloppyDrive class implementation... - +// FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ), ioHappened(false), diskImageReady(false) { phase[0] = phase[1] = 0; @@ -102,7 +227,6 @@ FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ), i imageName[0][0] = imageName[1][0] = 0; // Zero out filenames } - FloppyDrive::~FloppyDrive() { if (disk[0]) @@ -112,7 +236,6 @@ FloppyDrive::~FloppyDrive() 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); @@ -149,7 +272,6 @@ bool FloppyDrive::LoadImage(const char * filename, uint8_t driveNum/*= 0*/) return true; } - bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/) { // Various sanity checks... @@ -179,7 +301,6 @@ bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/) 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); @@ -189,7 +310,6 @@ bool FloppyDrive::SaveImageAs(const char * filename, uint8_t driveNum/*= 0*/) return SaveImage(driveNum); } - void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/) { if (disk[driveNum] != NULL) @@ -201,7 +321,6 @@ void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/) SpawnMessage("New blank image inserted in drive %u...", driveNum); } - void FloppyDrive::SwapImages(void) { char imageNameTmp[MAX_PATH]; @@ -221,7 +340,6 @@ void FloppyDrive::SwapImages(void) SpawnMessage("Drive 0: %s...", imageName[0]); } - /* 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) */ @@ -248,6 +366,7 @@ void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum) WriteLog("FLOPPY: Upconverted WOZ type 1 to type 2...\n"); } + WriteLog("FLOPPY: OBT is %d\n", ((WOZ2 *)disk[driveNum])->optimalBitTmg); diskType[driveNum] = DT_WOZ; } else if (diskSize[driveNum] == 143360) @@ -310,7 +429,6 @@ void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum) "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', @@ -334,7 +452,6 @@ void FloppyDrive::WriteBits(uint8_t * dest, const uint8_t * src, uint16_t bits, } } - void FloppyDrive::WOZifyImage(uint8_t driveNum) { // hdr (21) + nybbles (343) + footer (48) = 412 bytes per sector @@ -458,7 +575,6 @@ void FloppyDrive::WOZifyImage(uint8_t driveNum) free(tmpDisk); } - const char * FloppyDrive::ImageName(uint8_t driveNum/*= 0*/) { // Set up a zero-length string for return value @@ -495,7 +611,6 @@ const char * FloppyDrive::ImageName(uint8_t driveNum/*= 0*/) return nameBuf; } - void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/) { // Sanity check @@ -516,7 +631,6 @@ void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/) imageName[driveNum][0] = 0; // Zero out filenames } - bool FloppyDrive::IsEmpty(uint8_t driveNum/*= 0*/) { if (driveNum > 1) @@ -528,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) @@ -541,7 +654,6 @@ bool FloppyDrive::IsWriteProtected(uint8_t driveNum/*= 0*/) return (bool)woz.writeProtected; } - void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/) { if (driveNum > 1) @@ -554,7 +666,6 @@ void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/) woz.writeProtected = (uint8_t)state; } - int FloppyDrive::DriveLightStatus(uint8_t driveNum/*= 0*/) { int retval = DLS_OFF; @@ -569,7 +680,6 @@ int FloppyDrive::DriveLightStatus(uint8_t driveNum/*= 0*/) return retval; } - void FloppyDrive::SaveState(FILE * file) { // Internal state vars @@ -610,7 +720,6 @@ void FloppyDrive::SaveState(FILE * file) WriteLong(file, 0); } - void FloppyDrive::LoadState(FILE * file) { // Eject images if they're loaded @@ -653,7 +762,6 @@ void FloppyDrive::LoadState(FILE * file) } } - uint32_t FloppyDrive::ReadLong(FILE * file) { uint32_t r = 0; @@ -664,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++) @@ -674,7 +781,6 @@ void FloppyDrive::WriteLong(FILE * file, uint32_t l) } } - // Memory mapped I/O functions + Logic State Sequencer /* @@ -754,11 +860,13 @@ If it ever *does* become a problem, doing the physical modeling of the head movi else phase[activeDrive] &= ~phaseBit; - uint8_t oldHeadPos = headPos[activeDrive] & 0x07; - int16_t newStep = step[phase[activeDrive]][oldHeadPos]; + 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); // Sanity check + // N.B.: This is wrong for 3.5" disks if ((newHeadPos >= 0) && (newHeadPos <= 140)) headPos[activeDrive] = (uint8_t)newHeadPos; @@ -772,7 +880,9 @@ If it ever *does* become a problem, doing the physical modeling of the head movi 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); @@ -787,7 +897,6 @@ if (addr & 0x01) 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) { // $C0E8 - 9 @@ -801,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 @@ -809,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). @@ -825,21 +932,18 @@ 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) { @@ -858,15 +962,14 @@ uint8_t FloppyDrive::DataRegister(void) if ((seenReadSinceStep == false) && (slSwitch == false) && (rwSwitch == false) && ((iorAddr & 0x0F) == 0x0C)) { seenReadSinceStep = true; - WriteLog("%u:Reading $%02X from track %u, sector %u (delta since seek: %lu cycles) [%u]...\n", - activeDrive, dataRegister, headPos[activeDrive] >> 2, (uint32_t)(((float)currentPos[activeDrive] / (float)bitLen) * 16.0f), mainCPU.clock - stepperTime, mainCPU.clock & 0xFFFFFFFF); + 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) { @@ -875,7 +978,6 @@ void FloppyDrive::DataRegister(uint8_t data) ioHappened = true; } - /* OFF switches ON switches Switch Addr Func Addr Func @@ -948,9 +1050,11 @@ $5A: File structure damaged // 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 // @@ -974,6 +1078,9 @@ void FloppyDrive::RunSequencer(uint32_t cyclesToRun) 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; @@ -990,7 +1097,8 @@ if (logSeq) while (cyclesToRun-- > 0) { // pulseClock = (pulseClock + 1) & 0x07; - pulseClock = (pulseClock + 1) % 8; +// 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; @@ -998,6 +1106,7 @@ if (logSeq) { uint16_t bytePos = currentPos[activeDrive] / 8; uint8_t bitPos = currentPos[activeDrive] % 8; + window <<= 1; if (tIdx != 0xFF) { @@ -1005,14 +1114,17 @@ if (logSeq) { // 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++; +//WriteLog("[%d]", tdata[bytePos] & bitMask[bitPos] ? 1 : 0); } + readPulse = (window >> 1) & 0x01; // Read pulse delayed by about 5µs currentPos[activeDrive] = (currentPos[activeDrive] + 1) % trackLength[activeDrive]; // If we hit more than 2 zero bits in a row, simulate the disk head @@ -1022,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; @@ -1042,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: @@ -1096,13 +1226,13 @@ lastPos = currentPos[activeDrive]; } break; case 0x0A: - case 0x0E: +// case 0x0E: // SR (shift right write protect bit) dataRegister >>= 1; dataRegister |= (woz.writeProtected ? 0x80 : 0x00); break; case 0x0B: - case 0x0F: +// case 0x0F: // LD (load data register from data bus) dataRegister = cpuDataBus; //if (!stopWriting) @@ -1133,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) @@ -1143,7 +1276,6 @@ if (logSeq) WriteLog("\n"); } - FloppyDrive floppyDrive[2]; static uint8_t SlotIOR(uint16_t address) @@ -1187,7 +1319,6 @@ iorAddr = address; return (address & 0x01 ? ReadFloatingBus(0) : floppyDrive[0].DataRegister()); } - static void SlotIOW(uint16_t address, uint8_t byte) { uint8_t state = address & 0x0F; @@ -1233,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); } -