#include "firmware.h"
+//
+// 16-sector bootstrap driver for disk controller
+//
+uint8_t diskROM[0x100] = {
+ 0xA2, 0x20, 0xA0, 0x00, 0xA2, 0x03, 0x86, 0x3C,
+ 0x8A, 0x0A, 0x24, 0x3C, 0xF0, 0x10, 0x05, 0x3C,
+ 0x49, 0xFF, 0x29, 0x7E, 0xB0, 0x08, 0x4A, 0xD0,
+ 0xFB, 0x98, 0x9D, 0x56, 0x03, 0xC8, 0xE8, 0x10,
+ 0xE5, 0x20, 0x58, 0xFF, 0xBA, 0xBD, 0x00, 0x01,
+ 0x0A, 0x0A, 0x0A, 0x0A, 0x85, 0x2B, 0xAA, 0xBD,
+ 0x8E, 0xC0, 0xBD, 0x8C, 0xC0, 0xBD, 0x8A, 0xC0,
+ 0xBD, 0x89, 0xC0, 0xA0, 0x50, 0xBD, 0x80, 0xC0,
+ 0x98, 0x29, 0x03, 0x0A, 0x05, 0x2B, 0xAA, 0xBD,
+ 0x81, 0xC0, 0xA9, 0x56, 0x20, 0xA8, 0xFC, 0x88,
+ 0x10, 0xEB, 0x85, 0x26, 0x85, 0x3D, 0x85, 0x41,
+ 0xA9, 0x08, 0x85, 0x27, 0x18, 0x08, 0xBD, 0x8C,
+ 0xC0, 0x10, 0xFB, 0x49, 0xD5, 0xD0, 0xF7, 0xBD,
+ 0x8C, 0xC0, 0x10, 0xFB, 0xC9, 0xAA, 0xD0, 0xF3,
+ 0xEA, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0xC9, 0x96,
+ 0xF0, 0x09, 0x28, 0x90, 0xDF, 0x49, 0xAD, 0xF0,
+ 0x25, 0xD0, 0xD9, 0xA0, 0x03, 0x85, 0x40, 0xBD,
+ 0x8C, 0xC0, 0x10, 0xFB, 0x2A, 0x85, 0x3C, 0xBD,
+ 0x8C, 0xC0, 0x10, 0xFB, 0x25, 0x3C, 0x88, 0xD0,
+ 0xEC, 0x28, 0xC5, 0x3D, 0xD0, 0xBE, 0xA5, 0x40,
+ 0xC5, 0x41, 0xD0, 0xB8, 0xB0, 0xB7, 0xA0, 0x56,
+ 0x84, 0x3C, 0xBC, 0x8C, 0xC0, 0x10, 0xFB, 0x59,
+ 0xD6, 0x02, 0xA4, 0x3C, 0x88, 0x99, 0x00, 0x03,
+ 0xD0, 0xEE, 0x84, 0x3C, 0xBC, 0x8C, 0xC0, 0x10,
+ 0xFB, 0x59, 0xD6, 0x02, 0xA4, 0x3C, 0x91, 0x26,
+ 0xC8, 0xD0, 0xEF, 0xBC, 0x8C, 0xC0, 0x10, 0xFB,
+ 0x59, 0xD6, 0x02, 0xD0, 0x87, 0xA0, 0x00, 0xA2,
+ 0x56, 0xCA, 0x30, 0xFB, 0xB1, 0x26, 0x5E, 0x00,
+ 0x03, 0x2A, 0x5E, 0x00, 0x03, 0x2A, 0x91, 0x26,
+ 0xC8, 0xD0, 0xEE, 0xE6, 0x27, 0xE6, 0x3D, 0xA5,
+ 0x3D, 0xCD, 0x00, 0x08, 0xA6, 0x2B, 0x90, 0xDB,
+ 0x4C, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+};
-uint8_t diskROM[0x100] = { // Loads at $C600 (slot 6)
- 0xA2, 0x20, 0xA0, 0x00, 0xA2, 0x03, 0x86, 0x3C, 0x8A, 0x0A, 0x24, 0x3C, 0xF0, 0x10, 0x05, 0x3C,
- 0x49, 0xFF, 0x29, 0x7E, 0xB0, 0x08, 0x4A, 0xD0, 0xFB, 0x98, 0x9D, 0x56, 0x03, 0xC8, 0xE8, 0x10,
- 0xE5, 0x20, 0x58, 0xFF, 0xBA, 0xBD, 0x00, 0x01, 0x0A, 0x0A, 0x0A, 0x0A, 0x85, 0x2B, 0xAA, 0xBD,
- 0x8E, 0xC0, 0xBD, 0x8C, 0xC0, 0xBD, 0x8A, 0xC0, 0xBD, 0x89, 0xC0, 0xA0, 0x50, 0xBD, 0x80, 0xC0,
- 0x98, 0x29, 0x03, 0x0A, 0x05, 0x2B, 0xAA, 0xBD, 0x81, 0xC0, 0xA9, 0x56, 0x20, 0xA8, 0xFC, 0x88,
- 0x10, 0xEB, 0x85, 0x26, 0x85, 0x3D, 0x85, 0x41, 0xA9, 0x08, 0x85, 0x27, 0x18, 0x08, 0xBD, 0x8C,
- 0xC0, 0x10, 0xFB, 0x49, 0xD5, 0xD0, 0xF7, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0xC9, 0xAA, 0xD0, 0xF3,
- 0xEA, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0xC9, 0x96, 0xF0, 0x09, 0x28, 0x90, 0xDF, 0x49, 0xAD, 0xF0,
- 0x25, 0xD0, 0xD9, 0xA0, 0x03, 0x85, 0x40, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0x2A, 0x85, 0x3C, 0xBD,
- 0x8C, 0xC0, 0x10, 0xFB, 0x25, 0x3C, 0x88, 0xD0, 0xEC, 0x28, 0xC5, 0x3D, 0xD0, 0xBE, 0xA5, 0x40,
- 0xC5, 0x41, 0xD0, 0xB8, 0xB0, 0xB7, 0xA0, 0x56, 0x84, 0x3C, 0xBC, 0x8C, 0xC0, 0x10, 0xFB, 0x59,
- 0xD6, 0x02, 0xA4, 0x3C, 0x88, 0x99, 0x00, 0x03, 0xD0, 0xEE, 0x84, 0x3C, 0xBC, 0x8C, 0xC0, 0x10,
- 0xFB, 0x59, 0xD6, 0x02, 0xA4, 0x3C, 0x91, 0x26, 0xC8, 0xD0, 0xEF, 0xBC, 0x8C, 0xC0, 0x10, 0xFB,
- 0x59, 0xD6, 0x02, 0xD0, 0x87, 0xA0, 0x00, 0xA2, 0x56, 0xCA, 0x30, 0xFB, 0xB1, 0x26, 0x5E, 0x00,
- 0x03, 0x2A, 0x5E, 0x00, 0x03, 0x2A, 0x91, 0x26, 0xC8, 0xD0, 0xEE, 0xE6, 0x27, 0xE6, 0x3D, 0xA5,
- 0x3D, 0xCD, 0x00, 0x08, 0xA6, 0x2B, 0x90, 0xDB, 0x4C, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+//
+// 13-sector bootstrap driver for disk controller
+//
+uint8_t diskROM13[0x100] = {
+ 0xA2, 0x20, 0xA0, 0x00, 0xA9, 0x03, 0x85, 0x3C,
+ 0x18, 0x88, 0x98, 0x24, 0x3C, 0xF0, 0xF5, 0x26,
+ 0x3C, 0x90, 0xF8, 0xC0, 0xD5, 0xF0, 0xED, 0xCA,
+ 0x8A, 0x99, 0x00, 0x08, 0xD0, 0xE6, 0x20, 0x58,
+ 0xFF, 0xBA, 0xBD, 0x00, 0x01, 0x48, 0x0A, 0x0A,
+ 0x0A, 0x0A, 0x85, 0x2B, 0xAA, 0xA9, 0xD0, 0x48,
+ 0xBD, 0x8E, 0xC0, 0xBD, 0x8C, 0xC0, 0xBD, 0x8A,
+ 0xC0, 0xBD, 0x89, 0xC0, 0xA0, 0x50, 0xBD, 0x80,
+ 0xC0, 0x98, 0x29, 0x03, 0x0A, 0x05, 0x2B, 0xAA,
+ 0xBD, 0x81, 0xC0, 0xA9, 0x56, 0x20, 0xA8, 0xFC,
+ 0x88, 0x10, 0xEB, 0xA9, 0x03, 0x85, 0x27, 0xA9,
+ 0x00, 0x85, 0x26, 0x85, 0x3D, 0x18, 0x08, 0xBD,
+ 0x8C, 0xC0, 0x10, 0xFB, 0x49, 0xD5, 0xD0, 0xF7,
+ 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0xC9, 0xAA, 0xD0,
+ 0xF3, 0xEA, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0xC9,
+ 0xB5, 0xF0, 0x09, 0x28, 0x90, 0xDF, 0x49, 0xAD,
+ 0xF0, 0x1F, 0xD0, 0xD9, 0xA0, 0x03, 0x84, 0x2A,
+ 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0x2A, 0x85, 0x3C,
+ 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0x25, 0x3C, 0x88,
+ 0xD0, 0xEE, 0x28, 0xC5, 0x3D, 0xD0, 0xBE, 0xB0,
+ 0xBD, 0xA0, 0x9A, 0x84, 0x3C, 0xBC, 0x8C, 0xC0,
+ 0x10, 0xFB, 0x59, 0x00, 0x08, 0xA4, 0x3C, 0x88,
+ 0x99, 0x00, 0x08, 0xD0, 0xEE, 0x84, 0x3C, 0xBC,
+ 0x8C, 0xC0, 0x10, 0xFB, 0x59, 0x00, 0x08, 0xA4,
+ 0x3C, 0x91, 0x26, 0xC8, 0xD0, 0xEF, 0xBC, 0x8C,
+ 0xC0, 0x10, 0xFB, 0x59, 0x00, 0x08, 0xD0, 0x8D,
+ 0x60, 0xA8, 0xA2, 0x00, 0xB9, 0x00, 0x08, 0x4A,
+ 0x3E, 0xCC, 0x03, 0x4A, 0x3E, 0x99, 0x03, 0x85,
+ 0x3C, 0xB1, 0x26, 0x0A, 0x0A, 0x0A, 0x05, 0x3C,
+ 0x91, 0x26, 0xC8, 0xE8, 0xE0, 0x33, 0xD0, 0xE4,
+ 0xC6, 0x2A, 0xD0, 0xDE, 0xCC, 0x00, 0x03, 0xD0,
+ 0x03, 0x4C, 0x01, 0x03, 0x4C, 0x2D, 0xFF, 0xFF
};
+// Looks like this is unused...
uint8_t hdROM[0x100] = { // Loads at $C700 (slot 7)
0xA9, 0x20, 0xA9, 0x00, 0xA9, 0x03, 0xA9, 0x3C, 0xA9, 0x00, 0x8D, 0xF2, 0xC0, 0xA9, 0x70, 0x8D,
0xF3, 0xC0, 0xAD, 0xF0, 0xC0, 0x48, 0xAD, 0xF1, 0xC0, 0x18, 0xC9, 0x01, 0xD0, 0x01, 0x38, 0x68,
#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);
}
-