mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-10-12 07:23:43 +00:00
incremental improvement for woz disk support
This commit is contained in:
parent
182c7649d8
commit
29542704bd
200
apple/diskii.cpp
200
apple/diskii.cpp
@ -40,6 +40,10 @@ DiskII::DiskII(AppleMMU *mmu)
|
|||||||
disk[0] = disk[1] = NULL;
|
disk[0] = disk[1] = NULL;
|
||||||
diskIsSpinningUntil[0] = diskIsSpinningUntil[1] = 0;
|
diskIsSpinningUntil[0] = diskIsSpinningUntil[1] = 0;
|
||||||
selectedDisk = 0;
|
selectedDisk = 0;
|
||||||
|
|
||||||
|
driveSpinupCycles = 0;
|
||||||
|
deliveredDiskBits = 0;
|
||||||
|
// debugDeliveredDiskBits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskII::~DiskII()
|
DiskII::~DiskII()
|
||||||
@ -163,6 +167,36 @@ void DiskII::Reset()
|
|||||||
ejectDisk(1);
|
ejectDisk(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiskII::driveOff()
|
||||||
|
{
|
||||||
|
diskIsSpinningUntil[selectedDisk] = g_cpu->cycles + SPINDOWNDELAY; // 1 second lag
|
||||||
|
if (diskIsSpinningUntil[selectedDisk] == -1 ||
|
||||||
|
diskIsSpinningUntil[selectedDisk] == 0)
|
||||||
|
diskIsSpinningUntil[selectedDisk] = 2; // fudge magic numbers; 0 is "off" and -1 is "forever".
|
||||||
|
|
||||||
|
// The drive-is-on-indicator is turned off later, when the disk
|
||||||
|
// actually spins down.
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiskII::driveOn()
|
||||||
|
{
|
||||||
|
if (diskIsSpinningUntil[selectedDisk] != -1) {
|
||||||
|
// If the drive isn't already spinning, then start keeping track of how
|
||||||
|
// many bits we've delivered (so we can honor the disk bit-delivery time
|
||||||
|
// that might be in the Woz disk image).
|
||||||
|
driveSpinupCycles = g_cpu->cycles;
|
||||||
|
//printf("driveOn @ cycle %d\n", driveSpinupCycles);
|
||||||
|
deliveredDiskBits = 0;
|
||||||
|
// debugDeliveredDiskBits = 0;
|
||||||
|
diskIsSpinningUntil[selectedDisk] = -1; // magic "forever"
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: do we really want to update the UI from inside this thread?
|
||||||
|
|
||||||
|
// Start the given disk drive spinning
|
||||||
|
lastDiskRead[selectedDisk] = g_cpu->cycles;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t DiskII::readSwitches(uint8_t s)
|
uint8_t DiskII::readSwitches(uint8_t s)
|
||||||
{
|
{
|
||||||
switch (s) {
|
switch (s) {
|
||||||
@ -188,17 +222,10 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08: // drive off
|
case 0x08: // drive off
|
||||||
diskIsSpinningUntil[selectedDisk] = g_cpu->cycles + SPINDOWNDELAY; // 1 second lag
|
driveOff();
|
||||||
if (diskIsSpinningUntil[selectedDisk] == -1 ||
|
|
||||||
diskIsSpinningUntil[selectedDisk] == 0)
|
|
||||||
diskIsSpinningUntil[selectedDisk] = 2; // fudge magic numbers; 0 is "off" and -1 is "forever".
|
|
||||||
break;
|
break;
|
||||||
case 0x09: // drive on
|
case 0x09: // drive on
|
||||||
diskIsSpinningUntil[selectedDisk] = -1; // magic "forever"
|
driveOn();
|
||||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: delay a bit? Queue for later drawing? ***
|
|
||||||
|
|
||||||
// Start the given disk drive spinning
|
|
||||||
lastDiskRead[selectedDisk] = g_cpu->cycles;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0A: // select drive 1
|
case 0x0A: // select drive 1
|
||||||
@ -210,8 +237,15 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
|||||||
|
|
||||||
case 0x0C: // shift one read or write byte
|
case 0x0C: // shift one read or write byte
|
||||||
readWriteLatch = readOrWriteByte();
|
readWriteLatch = readOrWriteByte();
|
||||||
if (readWriteLatch & 0x80)
|
if (readWriteLatch & 0x80) {
|
||||||
|
// static uint32_t lastC = 0;
|
||||||
|
// printf("%u: read data\n", g_cpu->cycles - lastC);
|
||||||
|
// lastC = g_cpu->cycles;
|
||||||
|
if (!(sequencer & 0x80)) {
|
||||||
|
printf("SEQ RESET EARLY [1]\n");
|
||||||
|
}
|
||||||
sequencer = 0;
|
sequencer = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0D: // load data register (latch)
|
case 0x0D: // load data register (latch)
|
||||||
@ -223,6 +257,10 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
|||||||
else
|
else
|
||||||
readWriteLatch &= 0x7F;
|
readWriteLatch &= 0x7F;
|
||||||
}
|
}
|
||||||
|
if (!(sequencer & 0x80)) {
|
||||||
|
printf("SEQ RESET EARLY [2]\n");
|
||||||
|
}
|
||||||
|
sequencer = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0E: // set read mode
|
case 0x0E: // set read mode
|
||||||
@ -263,17 +301,10 @@ void DiskII::writeSwitches(uint8_t s, uint8_t v)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08: // drive off
|
case 0x08: // drive off
|
||||||
diskIsSpinningUntil[selectedDisk] = g_cpu->cycles + SPINDOWNDELAY; // 1 second lag
|
driveOff();
|
||||||
if (diskIsSpinningUntil[selectedDisk] == -1 ||
|
|
||||||
diskIsSpinningUntil[selectedDisk] == 0)
|
|
||||||
diskIsSpinningUntil[selectedDisk] = 2; // fudge magic numbers; 0 is "off" and -1 is "forever".
|
|
||||||
break;
|
break;
|
||||||
case 0x09: // drive on
|
case 0x09: // drive on
|
||||||
diskIsSpinningUntil[selectedDisk] = -1; // magic "forever"
|
driveOn();
|
||||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: delay a bit? Queue for later drawing? ***
|
|
||||||
|
|
||||||
// Start the given disk drive spinning
|
|
||||||
lastDiskRead[selectedDisk] = g_cpu->cycles;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0A: // select drive 1
|
case 0x0A: // select drive 1
|
||||||
@ -284,8 +315,12 @@ void DiskII::writeSwitches(uint8_t s, uint8_t v)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0C: // shift one read or write byte
|
case 0x0C: // shift one read or write byte
|
||||||
if (readOrWriteByte() & 0x80)
|
if (readOrWriteByte() & 0x80) {
|
||||||
|
if (!(sequencer & 0x80)) {
|
||||||
|
printf("SEQ RESET EARLY [3]\n");
|
||||||
|
}
|
||||||
sequencer = 0;
|
sequencer = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0D: // drive write
|
case 0x0D: // drive write
|
||||||
@ -366,8 +401,9 @@ void DiskII::setPhase(uint8_t phase)
|
|||||||
|
|
||||||
if (curHalfTrack[selectedDisk] != prevHalfTrack) {
|
if (curHalfTrack[selectedDisk] != prevHalfTrack) {
|
||||||
// We're changing track - flush the old track back to disk
|
// We're changing track - flush the old track back to disk
|
||||||
|
// FIXME flush
|
||||||
curWozTrack[selectedDisk] = disk[selectedDisk]->trackNumberForQuarterTrack(curHalfTrack[selectedDisk]*2);
|
curWozTrack[selectedDisk] = disk[selectedDisk]->dataTrackNumberForQuarterTrack(curHalfTrack[selectedDisk]*2);
|
||||||
|
printf("track change => %d\n", curWozTrack[selectedDisk]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,9 +446,9 @@ void DiskII::insertDisk(int8_t driveNum, const char *filename, bool drawIt)
|
|||||||
ejectDisk(driveNum);
|
ejectDisk(driveNum);
|
||||||
|
|
||||||
disk[driveNum] = new WozSerializer();
|
disk[driveNum] = new WozSerializer();
|
||||||
disk[driveNum]->readFile(filename, false, T_AUTO); // FIXME error checking
|
disk[driveNum]->readFile(filename, true, T_AUTO); // FIXME error checking; also FIXME the true is 'preload all tracks' and that won't work on the teensy
|
||||||
|
|
||||||
curWozTrack[driveNum] = disk[driveNum]->trackNumberForQuarterTrack(curHalfTrack[driveNum]*2);
|
curWozTrack[driveNum] = disk[driveNum]->dataTrackNumberForQuarterTrack(curHalfTrack[driveNum]*2);
|
||||||
|
|
||||||
if (drawIt)
|
if (drawIt)
|
||||||
g_ui->drawOnOffUIElement(UIeDisk1_state + driveNum, false);
|
g_ui->drawOnOffUIElement(UIeDisk1_state + driveNum, false);
|
||||||
@ -444,8 +480,10 @@ void DiskII::select(int8_t which)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the current woz track for the given disk drive
|
// Update the current woz track for the given disk drive
|
||||||
|
if (disk[selectedDisk]) {
|
||||||
curWozTrack[selectedDisk] =
|
curWozTrack[selectedDisk] =
|
||||||
disk[selectedDisk]->trackNumberForQuarterTrack(curHalfTrack[selectedDisk]*2);
|
disk[selectedDisk]->dataTrackNumberForQuarterTrack(curHalfTrack[selectedDisk]*2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t DiskII::readOrWriteByte()
|
uint8_t DiskII::readOrWriteByte()
|
||||||
@ -455,18 +493,24 @@ uint8_t DiskII::readOrWriteByte()
|
|||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: not handling writes at all at the moment ***
|
|
||||||
if (writeMode && !writeProt) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t curCycles = g_cpu->cycles;
|
uint32_t curCycles = g_cpu->cycles;
|
||||||
bool updateCycles = false;
|
bool updateCycles = false;
|
||||||
|
|
||||||
|
// FIXME: for writes, we need to check s/t like ... if (diskIsSpinningUntil[selectedDisk] >= curCycles) { return } ...
|
||||||
|
|
||||||
|
if (writeMode && !writeProt) {
|
||||||
|
// It's a write request. Inject 'readWriteLatch'.
|
||||||
|
disk[selectedDisk]->writeNextWozByte(curWozTrack[selectedDisk], readWriteLatch);
|
||||||
|
|
||||||
|
updateCycles = true; // need to update when we last read, b/c disk is still spinning
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (diskIsSpinningUntil[selectedDisk] >= curCycles) {
|
if (diskIsSpinningUntil[selectedDisk] >= curCycles) {
|
||||||
|
|
||||||
if (lastDiskRead[selectedDisk] == 0) {
|
if (lastDiskRead[selectedDisk] == 0) {
|
||||||
// assume it's a first-read-after-spinup; return the first valid data
|
// assume it's a first-read-after-spinup; return the first valid data
|
||||||
|
printf("FIRST SPIN\n");
|
||||||
sequencer = disk[selectedDisk]->nextDiskBit(curWozTrack[selectedDisk]);
|
sequencer = disk[selectedDisk]->nextDiskBit(curWozTrack[selectedDisk]);
|
||||||
updateCycles = true;
|
updateCycles = true;
|
||||||
goto done;
|
goto done;
|
||||||
@ -474,16 +518,87 @@ uint8_t DiskII::readOrWriteByte()
|
|||||||
|
|
||||||
// Otherwise we figure out how many cycles we missed since the last
|
// Otherwise we figure out how many cycles we missed since the last
|
||||||
// disk read, and pop the right number of bits off the woz track
|
// disk read, and pop the right number of bits off the woz track
|
||||||
uint32_t missedCycles;
|
// uint32_t missedCycles;
|
||||||
missedCycles = curCycles - lastDiskRead[selectedDisk];
|
// missedCycles = curCycles - lastDiskRead[selectedDisk];
|
||||||
|
|
||||||
missedCycles >>= 2;
|
// The stock 4ms disk bit timing is just missedCycles >> 2. But we
|
||||||
if (missedCycles)
|
// want to support others, too. We can't simply base it on cycle
|
||||||
updateCycles = true;
|
// count any more at that point, because of fractional cycles
|
||||||
while (missedCycles) {
|
// being important.
|
||||||
|
// So instead of just "missedCycles >>= 2" here, we need to calculate
|
||||||
|
// how many *bits* should have been transited at time (x); and we need
|
||||||
|
// a floating counter of how long the drive has been spinning (b/c
|
||||||
|
// that's not a constant since startup!); and we need the counter of
|
||||||
|
// how many bits we actually did pull from the drive. Then we can
|
||||||
|
// calculate exactly how many bits we should pull this time, update the
|
||||||
|
// number that did transit, and be more or less where we're supposed
|
||||||
|
// to be for this clock cycle.
|
||||||
|
|
||||||
|
// Handle rollover, which is a mess.
|
||||||
|
if (driveSpinupCycles > g_cpu->cycles) {
|
||||||
|
printf("Cycle rollover\n");
|
||||||
|
driveSpinupCycles = g_cpu->cycles-1;
|
||||||
|
#ifndef TEENSYDUINO
|
||||||
|
exit(2); // for debugging, FIXME ***
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cyclesPassed = g_cpu->cycles - driveSpinupCycles;
|
||||||
|
// printf("cy: %d cp: %d ", g_cpu->cycles, cyclesPassed);
|
||||||
|
|
||||||
|
// bits = cycles * (us per cycle) * (bits/us)
|
||||||
|
//#define BITSPEED 4.0
|
||||||
|
// uint64_t expectedDiskBits = (float)cyclesPassed * (float)(1.0/(1.023*BITSPEED)); // clock speed*2 b/c the disk clock runs at twice the speed?
|
||||||
|
// uint64_t expectedDiskBits = (float)cyclesPassed / 8.0;
|
||||||
|
uint64_t expectedDiskBits = (float) cyclesPassed / 3.52;
|
||||||
|
int64_t bitsToDeliver = expectedDiskBits - deliveredDiskBits;
|
||||||
|
|
||||||
|
// printf("btd: %llu\n",bitsToDeliver);
|
||||||
|
// printf("mc>>2: %d; btd: %llu\n", missedCycles >> 2, bitsToDeliver);
|
||||||
|
//int64_t bitsToDeliver = missedCycles>>2;
|
||||||
|
// debugDeliveredDiskBits += (missedCycles >> 2);
|
||||||
|
|
||||||
|
if (bitsToDeliver > 0) {
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/* TESTING - try delivering a byte, if there's a simple request, and let it drift forward in time very slightly */
|
||||||
|
if (bitsToDeliver < 16) {
|
||||||
|
|
||||||
|
// if (bitsToDeliver >= 8) { sequencer = 0; }
|
||||||
|
while (bitsToDeliver > -16 && ((sequencer & 0x80) == 0)) {
|
||||||
sequencer <<= 1;
|
sequencer <<= 1;
|
||||||
sequencer |= disk[selectedDisk]->nextDiskBit(curWozTrack[selectedDisk]);
|
sequencer |= disk[selectedDisk]->nextDiskBit(curWozTrack[selectedDisk]);
|
||||||
missedCycles--;
|
bitsToDeliver--;
|
||||||
|
deliveredDiskBits++;
|
||||||
|
}
|
||||||
|
updateCycles = true;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* END TESTING */
|
||||||
|
|
||||||
|
// printf("WARNING: missed data [%lld]\n", bitsToDeliver);
|
||||||
|
#endif
|
||||||
|
updateCycles = true;
|
||||||
|
|
||||||
|
// Something is wrong here. I don't know why
|
||||||
|
// debugDeliveredDiskBits doesn't match bitsToDeliver. In
|
||||||
|
// theory, debugDDB is just missedCycles/4. deliveredDiskBits
|
||||||
|
// should be pretty much the same (1.023/4.0, so off by
|
||||||
|
// 2.3%). But in reality the drift is much greater.
|
||||||
|
//
|
||||||
|
// Is it related to the disk on/off timers? How does
|
||||||
|
// missedCycles differ? I could use missedCycles, except that it
|
||||||
|
// loses precision when we're talking about using a 3.5us bit
|
||||||
|
// timing, so that's a problem -- which is why I'm trying to
|
||||||
|
// base it on "real time" from when the disk drive starts
|
||||||
|
// spinning...
|
||||||
|
|
||||||
|
deliveredDiskBits += bitsToDeliver;
|
||||||
|
while (bitsToDeliver) {
|
||||||
|
sequencer <<= 1;
|
||||||
|
sequencer |= disk[selectedDisk]->nextDiskBit(curWozTrack[selectedDisk]);
|
||||||
|
bitsToDeliver--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,8 +615,12 @@ uint8_t DiskII::readOrWriteByte()
|
|||||||
|
|
||||||
const char *DiskII::DiskName(int8_t num)
|
const char *DiskII::DiskName(int8_t num)
|
||||||
{
|
{
|
||||||
// ***
|
if (disk[num]) {
|
||||||
|
// *** need to get name from disk image FIXME
|
||||||
|
return "[inserted]";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing inserted in that drive
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,6 +658,11 @@ void DiskII::maintenance(uint32_t cycle)
|
|||||||
// Stop the given disk drive spinning
|
// Stop the given disk drive spinning
|
||||||
lastDiskRead[i] = 0; // FIXME: magic value. We need a tristate for this. ***
|
lastDiskRead[i] = 0; // FIXME: magic value. We need a tristate for this. ***
|
||||||
diskIsSpinningUntil[i] = 0;
|
diskIsSpinningUntil[i] = 0;
|
||||||
|
|
||||||
|
if (disk[i]) {
|
||||||
|
disk[i]->flush();
|
||||||
|
}
|
||||||
|
|
||||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + i, false); // FIXME: queue for later drawing?
|
g_ui->drawOnOffUIElement(UIeDisk1_activity + i, false); // FIXME: queue for later drawing?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,18 +46,26 @@ class DiskII : public Slot {
|
|||||||
void select(int8_t which); // 0 or 1 for drives 1 and 2, respectively
|
void select(int8_t which); // 0 or 1 for drives 1 and 2, respectively
|
||||||
uint8_t readOrWriteByte();
|
uint8_t readOrWriteByte();
|
||||||
|
|
||||||
|
void driveOn();
|
||||||
|
void driveOff();
|
||||||
|
|
||||||
#ifndef TEENSYDUINO
|
#ifndef TEENSYDUINO
|
||||||
void convertDskToNib(const char *outFN);
|
void convertDskToNib(const char *outFN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
// debugging
|
||||||
|
WozSerializer *disk[2];
|
||||||
private:
|
private:
|
||||||
volatile int8_t curHalfTrack[2];
|
volatile int8_t curHalfTrack[2];
|
||||||
volatile uint8_t curWozTrack[2];
|
volatile uint8_t curWozTrack[2];
|
||||||
volatile int8_t curPhase[2];
|
volatile int8_t curPhase[2];
|
||||||
uint8_t readWriteLatch;
|
uint8_t readWriteLatch;
|
||||||
uint8_t sequencer, dataRegister; // diskII logic state sequencer vars
|
uint8_t sequencer, dataRegister; // diskII logic state sequencer vars
|
||||||
WozSerializer *disk[2];
|
|
||||||
uint32_t lastDiskRead[2];
|
uint32_t lastDiskRead[2];
|
||||||
|
uint64_t driveSpinupCycles;
|
||||||
|
uint64_t deliveredDiskBits;
|
||||||
|
uint64_t debugDeliveredDiskBits;
|
||||||
|
|
||||||
bool writeMode;
|
bool writeMode;
|
||||||
bool writeProt;
|
bool writeProt;
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#include "woz-serializer.h"
|
#include "woz-serializer.h"
|
||||||
|
|
||||||
|
WozSerializer::WozSerializer() : Woz(0,0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool WozSerializer::Serialize(int8_t fd)
|
bool WozSerializer::Serialize(int8_t fd)
|
||||||
{
|
{
|
||||||
// ***
|
// ***
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
#include "woz.h"
|
#include "woz.h"
|
||||||
class WozSerializer: public virtual Woz {
|
class WozSerializer: public virtual Woz {
|
||||||
|
public:
|
||||||
|
WozSerializer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Serialize(int8_t fd);
|
bool Serialize(int8_t fd);
|
||||||
bool Deserialize(int8_t fd);
|
bool Deserialize(int8_t fd);
|
||||||
|
1036
apple/woz.cpp
1036
apple/woz.cpp
File diff suppressed because it is too large
Load Diff
73
apple/woz.h
73
apple/woz.h
@ -8,6 +8,16 @@
|
|||||||
#include "nibutil.h"
|
#include "nibutil.h"
|
||||||
#include "disktypes.h"
|
#include "disktypes.h"
|
||||||
|
|
||||||
|
#define DUMP_TRACK 0x01
|
||||||
|
#define DUMP_QTMAP 0x02
|
||||||
|
#define DUMP_QTCRC 0x04
|
||||||
|
// these all require DUMP_TRACK:
|
||||||
|
#define DUMP_TOFILE 0x10
|
||||||
|
#define DUMP_SECTOR 0x20
|
||||||
|
#define DUMP_RAWTRACK 0x40
|
||||||
|
#define DUMP_ORDEREDSECTOR 0x80
|
||||||
|
|
||||||
|
|
||||||
typedef struct _diskInfo {
|
typedef struct _diskInfo {
|
||||||
uint8_t version; // Woz format version #
|
uint8_t version; // Woz format version #
|
||||||
uint8_t diskType; // 1 = 5.25"; 2 = 3.5"
|
uint8_t diskType; // 1 = 5.25"; 2 = 3.5"
|
||||||
@ -33,56 +43,71 @@ typedef struct _trackInfo {
|
|||||||
|
|
||||||
class Woz {
|
class Woz {
|
||||||
public:
|
public:
|
||||||
Woz();
|
Woz(bool verbose, uint8_t dumpflags);
|
||||||
~Woz();
|
~Woz();
|
||||||
|
|
||||||
bool readFile(const char *filename, bool preloadTracks, uint8_t forceType = T_AUTO);
|
bool readFile(const char *filename, bool preloadTracks, uint8_t forceType = T_AUTO);
|
||||||
bool writeFile(uint8_t version, const char *filename);
|
bool writeFile(const char *filename, uint8_t forceType = T_AUTO);
|
||||||
|
|
||||||
uint8_t getNextWozBit(uint8_t track);
|
uint8_t getNextWozBit(uint8_t datatrack);
|
||||||
uint8_t nextDiskBit(uint8_t track);
|
|
||||||
uint8_t nextDiskByte(uint8_t track);
|
|
||||||
|
|
||||||
bool decodeWozTrackToNib(uint8_t track, nibSector sectorData[16]);
|
|
||||||
bool decodeWozTrackToDsk(uint8_t track, uint8_t subtype, uint8_t sectorData[256*16]);
|
|
||||||
|
|
||||||
#ifndef TEENSYDUINO
|
|
||||||
void dumpInfo();
|
void dumpInfo();
|
||||||
#endif
|
|
||||||
|
|
||||||
bool isSynchronized();
|
bool isSynchronized();
|
||||||
|
|
||||||
uint8_t trackNumberForQuarterTrack(uint16_t qt);
|
uint8_t dataTrackNumberForQuarterTrack(uint16_t qt);
|
||||||
|
|
||||||
|
bool flush();
|
||||||
|
|
||||||
|
//protected:
|
||||||
|
// Interface for AiiE
|
||||||
|
bool writeNextWozBit(uint8_t datatrack, uint8_t bit);
|
||||||
|
bool writeNextWozByte(uint8_t datatrack, uint8_t b);
|
||||||
|
uint8_t nextDiskBit(uint8_t datatrack);
|
||||||
|
uint8_t nextDiskByte(uint8_t datatrack);
|
||||||
|
bool skipByte(uint8_t datatrack);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool readWozFile(const char *filename, bool preloadTracks);
|
bool readWozFile(const char *filename, bool preloadTracks);
|
||||||
bool readDskFile(const char *filename, bool preloadTracks, uint8_t subtype);
|
bool readDskFile(const char *filename, bool preloadTracks, uint8_t subtype);
|
||||||
bool readNibFile(const char *filename, bool preloadTracks);
|
bool readNibFile(const char *filename, bool preloadTracks);
|
||||||
|
|
||||||
|
bool decodeWozTrackToNib(uint8_t phystrack, nibSector sectorData[16]);
|
||||||
|
bool decodeWozTrackToDsk(uint8_t phystrack, uint8_t subtype, uint8_t sectorData[256*16]);
|
||||||
|
|
||||||
|
bool writeWozFile(const char *filename, uint8_t subtype);
|
||||||
|
bool writeDskFile(const char *filename, uint8_t subtype);
|
||||||
|
bool writeNibFile(const char *filename);
|
||||||
|
|
||||||
uint8_t fakeBit();
|
uint8_t fakeBit();
|
||||||
|
|
||||||
bool parseTRKSChunk(int8_t fh, uint32_t chunkSize);
|
bool parseTRKSChunk(uint32_t chunkSize);
|
||||||
bool parseTMAPChunk(int8_t fh, uint32_t chunkSize);
|
bool parseTMAPChunk(uint32_t chunkSize);
|
||||||
bool parseInfoChunk(int8_t fh, uint32_t chunkSize);
|
bool parseInfoChunk(uint32_t chunkSize);
|
||||||
bool parseMetaChunk(int8_t fh, uint32_t chunkSize);
|
bool parseMetaChunk(uint32_t chunkSize);
|
||||||
|
|
||||||
bool writeInfoChunk(uint8_t version, int8_t fh);
|
bool writeInfoChunk(uint8_t version, int fdout);
|
||||||
bool writeTMAPChunk(uint8_t version, int8_t fh);
|
bool writeTMAPChunk(uint8_t version, int fdout);
|
||||||
bool writeTRKSChunk(uint8_t version, int8_t fh);
|
bool writeTRKSChunk(uint8_t version, int fdout);
|
||||||
|
|
||||||
bool readQuarterTrackData(int8_t fh, uint8_t quartertrack);
|
bool readWozDataTrack(uint8_t datatrack);
|
||||||
bool readWozTrackData(int8_t fh, uint8_t wt);
|
bool readNibSectorData(uint8_t phystrack, uint8_t sector, nibSector *sectorData);
|
||||||
bool readSectorData(uint8_t track, uint8_t sector, nibSector *sectorData);
|
|
||||||
|
|
||||||
bool readAndDecodeTrack(uint8_t track, int8_t fh);
|
bool loadMissingTrackFromImage(uint8_t datatrack);
|
||||||
|
|
||||||
|
bool checksumWozDataTrack(uint8_t datatrack, uint32_t *retCRC);
|
||||||
|
|
||||||
void _initInfo();
|
void _initInfo();
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
int fd;
|
||||||
uint8_t imageType;
|
uint8_t imageType;
|
||||||
|
|
||||||
int8_t fh;
|
bool verbose;
|
||||||
|
uint8_t dumpflags;
|
||||||
|
|
||||||
bool autoFlushTrackData;
|
bool autoFlushTrackData;
|
||||||
|
bool trackDirty;
|
||||||
|
|
||||||
uint8_t quarterTrackMap[40*4];
|
uint8_t quarterTrackMap[40*4];
|
||||||
diskInfo di;
|
diskInfo di;
|
||||||
|
@ -96,6 +96,8 @@ class FileManager {
|
|||||||
virtual int8_t openFile(const char *name) = 0;
|
virtual int8_t openFile(const char *name) = 0;
|
||||||
virtual void closeFile(int8_t fd) = 0;
|
virtual void closeFile(int8_t fd) = 0;
|
||||||
|
|
||||||
|
virtual void truncate(int8_t fd) = 0;
|
||||||
|
|
||||||
virtual const char *fileName(int8_t fd) = 0;
|
virtual const char *fileName(int8_t fd) = 0;
|
||||||
|
|
||||||
virtual int8_t readDir(const char *where, const char *suffix, char *outputFN, int8_t startIdx, uint16_t maxlen) = 0;
|
virtual int8_t readDir(const char *where, const char *suffix, char *outputFN, int8_t startIdx, uint16_t maxlen) = 0;
|
||||||
|
@ -56,6 +56,12 @@ void NixFileManager::closeFile(int8_t fd)
|
|||||||
cachedNames[fd][0] = '\0';
|
cachedNames[fd][0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NixFileManager::truncate(int8_t fd)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(cachedNames[fd], "w+");
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
const char *NixFileManager::fileName(int8_t fd)
|
const char *NixFileManager::fileName(int8_t fd)
|
||||||
{
|
{
|
||||||
if (fd < 0 || fd >= numCached)
|
if (fd < 0 || fd >= numCached)
|
||||||
|
@ -12,6 +12,8 @@ class NixFileManager : public FileManager {
|
|||||||
virtual int8_t openFile(const char *name);
|
virtual int8_t openFile(const char *name);
|
||||||
virtual void closeFile(int8_t fd);
|
virtual void closeFile(int8_t fd);
|
||||||
|
|
||||||
|
virtual void truncate(int8_t fd);
|
||||||
|
|
||||||
virtual const char *fileName(int8_t fd);
|
virtual const char *fileName(int8_t fd);
|
||||||
|
|
||||||
virtual int8_t readDir(const char *where, const char *suffix, char *outputFN, int8_t startIdx, uint16_t maxlen);
|
virtual int8_t readDir(const char *where, const char *suffix, char *outputFN, int8_t startIdx, uint16_t maxlen);
|
||||||
|
@ -52,6 +52,8 @@ void sigint_handler(int n)
|
|||||||
{
|
{
|
||||||
// If we want control-C to reset the machine, then set this here...
|
// If we want control-C to reset the machine, then set this here...
|
||||||
// send_rst = 1;
|
// send_rst = 1;
|
||||||
|
|
||||||
|
((AppleVM*)g_vm)->disk6->disk[0]->dumpInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nonblock(int state)
|
void nonblock(int state)
|
||||||
|
@ -104,7 +104,7 @@ void SDLSpeaker::begin()
|
|||||||
audioDevice.userdata = NULL;
|
audioDevice.userdata = NULL;
|
||||||
|
|
||||||
memset(&soundBuf[0], 0, SDLSIZE);
|
memset(&soundBuf[0], 0, SDLSIZE);
|
||||||
bufIdx = SDLSIZE/2;
|
bufIdx = SDLSIZE/2; // FIXME: why? Shouldn't this just be 0?
|
||||||
|
|
||||||
SDL_OpenAudio(&audioDevice, &audioActual); // FIXME retval
|
SDL_OpenAudio(&audioDevice, &audioActual); // FIXME retval
|
||||||
printf("Actual: freq %d channels %d samples %d\n",
|
printf("Actual: freq %d channels %d samples %d\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user