#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 };
// 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)
{
b = t;
}
-
static inline void Swap(uint32_t & a, uint32_t & b)
{
uint32_t t = a;
b = t;
}
-
static inline void Swap(bool & a, bool & b)
{
bool t = a;
b = t;
}
-
static inline void Swap(uint8_t * & a, uint8_t * & b)
{
uint8_t * t = a;
b = t;
}
-
+//
// FloppyDrive class implementation...
-
+//
FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ), ioHappened(false), diskImageReady(false)
{
phase[0] = phase[1] = 0;
imageName[0][0] = imageName[1][0] = 0; // Zero out filenames
}
-
FloppyDrive::~FloppyDrive()
{
if (disk[0])
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);
return true;
}
-
bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/)
{
// Various sanity checks...
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);
return SaveImage(driveNum);
}
-
void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/)
{
if (disk[driveNum] != NULL)
SpawnMessage("New blank image inserted in drive %u...", driveNum);
}
-
void FloppyDrive::SwapImages(void)
{
char imageNameTmp[MAX_PATH];
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)
*/
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)
"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',
}
}
-
void FloppyDrive::WOZifyImage(uint8_t driveNum)
{
// hdr (21) + nybbles (343) + footer (48) = 412 bytes per sector
free(tmpDisk);
}
-
const char * FloppyDrive::ImageName(uint8_t driveNum/*= 0*/)
{
// Set up a zero-length string for return value
return nameBuf;
}
-
void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/)
{
// Sanity check
imageName[driveNum][0] = 0; // Zero out filenames
}
-
bool FloppyDrive::IsEmpty(uint8_t driveNum/*= 0*/)
{
if (driveNum > 1)
return (diskType[driveNum] == DT_EMPTY ? true : false);
}
-
bool FloppyDrive::IsWriteProtected(uint8_t driveNum/*= 0*/)
{
if (driveNum > 1)
return (bool)woz.writeProtected;
}
-
void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/)
{
if (driveNum > 1)
woz.writeProtected = (uint8_t)state;
}
-
int FloppyDrive::DriveLightStatus(uint8_t driveNum/*= 0*/)
{
int retval = DLS_OFF;
return retval;
}
-
void FloppyDrive::SaveState(FILE * file)
{
// Internal state vars
WriteLong(file, 0);
}
-
void FloppyDrive::LoadState(FILE * file)
{
// Eject images if they're loaded
}
}
-
uint32_t FloppyDrive::ReadLong(FILE * file)
{
uint32_t r = 0;
return r;
}
-
void FloppyDrive::WriteLong(FILE * file, uint32_t l)
{
for(int i=0; i<4; i++)
}
}
-
// Memory mapped I/O functions + Logic State Sequencer
/*
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;
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) [%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
WriteLog("FLOPPY: Turning drive motor %s\n", (motorOn ? "ON" : "off"));
}
-
void FloppyDrive::DriveEnable(uint8_t addr)
{
// $C0EA - B
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).
*/
-
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)
{
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)
{
ioHappened = true;
}
-
/*
OFF switches ON switches
Switch Addr Func Addr Func
// 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
//
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;
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;
{
uint16_t bytePos = currentPos[activeDrive] / 8;
uint8_t bitPos = currentPos[activeDrive] % 8;
+ window <<= 1;
if (tIdx != 0xFF)
{
{
// 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
/*
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;
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:
}
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)
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)
WriteLog("\n");
}
-
FloppyDrive floppyDrive[2];
static uint8_t SlotIOR(uint16_t address)
return (address & 0x01 ? ReadFloatingBus(0) : floppyDrive[0].DataRegister());
}
-
static void SlotIOW(uint16_t address, uint8_t byte)
{
uint8_t state = address & 0x0F;
// 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);
}
-