fix position on track switch; small refactor; comments

This commit is contained in:
Christopher A. Mosher 2018-12-18 15:44:06 -05:00
parent 8a393af531
commit 745592a68c
9 changed files with 132 additions and 159 deletions

View File

@ -4,7 +4,7 @@ METASOURCES=AUTO
bin_PROGRAMS=epple2
AM_CXXFLAGS=-std=c++14 -Wall -O3
AM_CXXFLAGS=-std=c++11 -Wall -O3
AM_CPPFLAGS=$(all_includes)
epple2_LDFLAGS=$(all_libraries)

View File

@ -58,33 +58,14 @@ unsigned char DiskController::io(const unsigned short addr, const unsigned char
break;
case 6:
this->load = on;
// TODO use LSS
// if (on && this->write && writing) {
// set(data);
// this->gui.setIO(this->slot,getCurrentDriveNumber(),this->motorOn);
// this->gui.setDirty(this->slot,getCurrentDriveNumber(),true);
// } else if (!(on || this->write)) {
// data = get();
// }
// TODO when to do these GUI updates?
// this->gui.setIO(this->slot,getCurrentDriveNumber(),this->motorOn);
// this->gui.setDirty(this->slot,getCurrentDriveNumber(),true);
break;
case 7:
this->write = on;
// TODO use LSS
// if (this->currentDrive->isWriteProtected()) {
// data |= 0x80;
// } else {
// data &= 0x7F;
// }
break;
}
// if (this->motorOn) {
// if (this->dataRegister == 0xD5) {
// printf("\ndata register --> ");
// }
// if (this->dataRegister & 0x80) {
// printf("%02x", this->dataRegister);
// }
// }
return on ? d : this->dataRegister;
}
@ -108,10 +89,10 @@ void DiskController::tick() {
}
void DiskController::rotateCurrentDisk() {
++t;
if (t < 0 || 4 <= t) { // 4us interval between bits
++this->t;
if (4 <= this->t) { // 4us interval between bits
this->currentDrive->rotateDiskOneBit(); // (will also generate a read-pulse when it reads a 1-bit)
t = 0;
this->t = 0;
} else {
// clear the read pulse (to make it last only 1us)
this->currentDrive->clearPulse();
@ -121,7 +102,6 @@ void DiskController::rotateCurrentDisk() {
void DiskController::stepLss() {
std::uint8_t adr = this->write<<3 | this->load<<2 | (this->dataRegister>>7)<<1 | this->currentDrive->readPulse();
std::uint8_t cmd = this->lssp6rom.read(this->seq|adr);
// if (cmd & 3) printf("LSS ROM command byte: 0x%2x\n", cmd);
this->seq = cmd & 0xF0u;
// LSS command functions (UA2, 9-15, Table 9.3)

View File

@ -101,7 +101,6 @@ public:
// we see more than three (emulating the MC3470, see UA2, 9-11)
++cContiguousZeroBits;
if (3 < cContiguousZeroBits) {
// if (cContiguousZeroBits == 4) printf("\n<GENERATING RANDOM BIT(S).....>\n");
if (randomBit()) {
this->pulse = true;
}
@ -117,23 +116,8 @@ public:
}
void writeBit(bool on) {
this->disk.setBit(this->arm.getQuarterTrack());
this->disk.setBit(this->arm.getQuarterTrack(), on);
}
// unsigned char get() const
// {
// return this->disk.get(this->arm.getTrack());
// }
// void set(unsigned char value)
// {
// this->disk.put(this->arm.getTrack(),value);
// }
// const WozFile& getDiskBytes() {
// return this->disk;
// }
};
#endif

View File

@ -34,28 +34,28 @@ static void setbth(std::uint8_t lssrom[], std::uint8_t x, std::uint8_t both) {
lssrom[x] = both;
}
static void showua2seq(std::uint8_t lssrom[], std::uint8_t seq) {
printf("| %02x %02x %02x %02x | %02x %02x %02x %02x",
lssrom[seq|0x9],
lssrom[seq|0xB],
lssrom[seq|0xD],
lssrom[seq|0xF],
lssrom[seq|0x8],
lssrom[seq|0xA],
lssrom[seq|0xC],
lssrom[seq|0xE]
);
printf("| %02x %02x %02x %02x | %02x %02x %02x %02x |\n",
lssrom[seq|0x1],
lssrom[seq|0x0],
lssrom[seq|0x3],
lssrom[seq|0x2],
lssrom[seq|0x5],
lssrom[seq|0x4],
lssrom[seq|0x7],
lssrom[seq|0x6]
);
}
//static void showua2seq(std::uint8_t lssrom[], std::uint8_t seq) {
// printf("| %02x %02x %02x %02x | %02x %02x %02x %02x",
// lssrom[seq|0x9],
// lssrom[seq|0xB],
// lssrom[seq|0xD],
// lssrom[seq|0xF],
// lssrom[seq|0x8],
// lssrom[seq|0xA],
// lssrom[seq|0xC],
// lssrom[seq|0xE]
// );
// printf("| %02x %02x %02x %02x | %02x %02x %02x %02x |\n",
// lssrom[seq|0x1],
// lssrom[seq|0x0],
// lssrom[seq|0x3],
// lssrom[seq|0x2],
// lssrom[seq|0x5],
// lssrom[seq|0x4],
// lssrom[seq|0x7],
// lssrom[seq|0x6]
// );
//}
LSS::LSS(bool use13SectorDos32LSS):
use13SectorDos32LSS(use13SectorDos32LSS) {
@ -175,15 +175,15 @@ LSS::LSS(bool use13SectorDos32LSS):
setseq(lss13rom,0x23u,0x30u);
setseq(lss13rom,0x33u,0xD0u);
if (use13SectorDos32LSS) {
for (unsigned int seq = 0; seq < 0x100u; seq += 0x10u) {
showua2seq(lss13rom,seq);
}
} else {
for (unsigned int seq = 0; seq < 0x100u; seq += 0x10u) {
showua2seq(lssrom,seq);
}
}
// if (use13SectorDos32LSS) {
// for (unsigned int seq = 0; seq < 0x100u; seq += 0x10u) {
// showua2seq(lss13rom,seq);
// }
// } else {
// for (unsigned int seq = 0; seq < 0x100u; seq += 0x10u) {
// showua2seq(lssrom,seq);
// }
// }
}
LSS::~LSS() {

View File

@ -62,7 +62,7 @@ void RAMInitializer::putBytesUntilFull(int bit, int pat)
}
}
void RAMInitializer::ramPattern1(const int bit) throw (done)
void RAMInitializer::ramPattern1(const int bit)
{
for (int k = 0; k < 2; ++k)
{
@ -100,7 +100,7 @@ void RAMInitializer::ramPattern1(const int bit) throw (done)
}
}
void RAMInitializer::ramPattern2(const int bit) throw (done)
void RAMInitializer::ramPattern2(const int bit)
{
for (int i = 0; i < 0x40; ++i)
{
@ -111,7 +111,7 @@ void RAMInitializer::ramPattern2(const int bit) throw (done)
void RAMInitializer::putn(const int c, bool on, const int bit) throw (done)
void RAMInitializer::putn(const int c, bool on, const int bit)
{
if (((rand() >> 9) & 0x1F) == 5)
on = !on;

View File

@ -29,9 +29,9 @@ private:
unsigned short nextinit;
void putBytesUntilFull(int bit, int pat);
void ramPattern1(const int bit) throw (done);
void ramPattern2(const int bit) throw (done);
void putn(const int c, bool on, const int bit) throw (done);
void ramPattern1(const int bit);
void ramPattern2(const int bit);
void putn(const int c, bool on, const int bit);
public:
RAMInitializer(Memory& mem);

View File

@ -26,9 +26,15 @@
* @author Chris Mosher
*/
/*
mags ps magval
3210
---- -- ------
Each postition is a quarter track.
One complete cycle through the 4 phases will
move the arm 2 tracks. (UA2, 9-7.)
0001 0 1
0011 1 3
0010 2 2
@ -38,17 +44,19 @@ mags ps magval
1000 6 8
1001 7 9
(strange, but defined)
strange, but still defined
1011 0 B
0111 2 7
1110 4 E
1101 6 D
(undefined, i.e., no movement)
all off (no movement)
0000 ? 0
undefined
0101 ? 5 // <-- TODO pick one at random?
1010 ? A // <-- TODO pick one at random?
1111 ? F
1111 ? F // TODO what to do here?
*/
#include "steppermotor.h"
#include "util.h"
@ -76,7 +84,7 @@ void StepperMotor::setMagnet(const unsigned char magnet, const bool on) {
}
const char newPos = mapMagPos[this->mags];
char d;
char d = 0;
if (newPos >= 0) {
d = calcDeltaPos(this->pos,newPos);
this->pos = newPos;
@ -87,19 +95,28 @@ void StepperMotor::setMagnet(const unsigned char magnet, const bool on) {
else if (this->quarterTrack > QTRACK_MAX)
this->quarterTrack = QTRACK_MAX;
}
std::cout << " ARM: magnet " << (unsigned int)magnet << " " << (on ? "on " : "off" );
std::cout << " [" <<
((mags&1)?"*":".") <<
((mags&2)?"*":".") <<
((mags&4)?"*":".") <<
((mags&8)?"*":".") <<
"]";
if (d != 0) {
std::cout << " track " << std::hex << (unsigned int)(this->quarterTrack >> 2);
int fract = this->quarterTrack & 3;
if (fract != 0) {
std::cout << (fract == 1 ? " +.25" : fract == 2 ? " +.5" : " +.75");
}
}
std::cout << std::endl;
// std::cout << " ARM: magnet " << (unsigned int)magnet << " " << (on ? "on " : "off" );
// std::cout << " [" <<
// ((mags&1)?"*":".") <<
// ((mags&2)?"*":".") <<
// ((mags&4)?"*":".") <<
// ((mags&8)?"*":".") <<
// "]";
// if (d != 0) {
// std::cout << " track " << std::hex << (unsigned int)(this->quarterTrack >> 2);
// int fract = this->quarterTrack & 3;
// if (fract != 0) {
// std::cout << (fract == 1 ? " +.25" : fract == 2 ? " +.5" : " +.75");
// }
// }
// std::cout << std::endl;
}
//static void dumpQTrack(std::uint8_t currentQuarterTrack) {
// if (currentQuarterTrack % 4) {
// const std::uint8_t hundredths((currentQuarterTrack%4) * 25);
// printf("track 0x%02X +.%02d\n", currentQuarterTrack/4, hundredths);
// } else {
// printf("track 0x%02X\n", currentQuarterTrack/4);
// }
//}

View File

@ -22,6 +22,7 @@
#include <istream>
#include <ostream>
#include <fstream>
#include <cmath>
WozFile::WozFile() : lastQuarterTrack(0) {
unload();
@ -73,8 +74,8 @@ bool WozFile::load(const std::string& filePath) {
printf("INFO version %d\n", *buf);
five_25 = (buf[1]==1);
printf("Disk type: %s\n", five_25 ? "5.25" : buf[1]==2 ? "3.5" : "?");
writable = !(buf[2]==1);
printf("Write protected?: %s\n", writable ? "No" : "Yes");
this->writable = !(buf[2]==1);
printf("Write protected?: %s\n", this->writable ? "No" : "Yes");
printf("Imaged with cross-track sync?: %s\n", buf[3]==1 ? "Yes" : "No");
printf("MC3470 fake bits removed?: %s\n", buf[4]==1 ? "Yes" : "No");
printf("Creator: \"%.32s\"\n", buf+5);
@ -103,7 +104,7 @@ bool WozFile::load(const std::string& filePath) {
}
printf("\x1b[31;47m-------------------------------------------\x1b[0m\n");
for (std::uint8_t qt(0); qt <= 140; ++qt) {
tmap[qt] = buf[qt];
this->tmap[qt] = buf[qt];
}
}
delete[] buf;
@ -115,18 +116,18 @@ bool WozFile::load(const std::string& filePath) {
if (chunk_size % 6656) {
printf("chunk size is not an even multiple of 6656.");
}
c_trks = chunk_size / 6656;
printf("Count of tracks: 0x%02X\n", c_trks);
if (c_trks > 141) {
this->c_trks = chunk_size / 6656;
printf("Count of tracks: 0x%02X\n", this->c_trks);
if (this->c_trks > 141) {
printf("Error: cannot handle more than 141 tracks.");
throw "Error: cannot handle more than 141 tracks";
}
for (std::uint8_t t(0); t < c_trks; ++t) {
for (std::uint8_t t(0); t < this->c_trks; ++t) {
printf("track 0x%02X:\n", t);
std::uint16_t usedBytes = *(std::uint16_t*)&buf[t*6656+6646+0];
printf(" used bytes: 0x%0X\n", usedBytes);
trk_bits[t] = *(std::uint16_t*)&buf[t*6656+6646+2];
printf(" count of bits: 0x%0X\n", trk_bits[t]);
this->trk_bits[t] = *(std::uint16_t*)&buf[t*6656+6646+2];
printf(" count of bits: 0x%0X\n", this->trk_bits[t]);
std::uint16_t spliceBit = *(std::uint16_t*)&buf[t*6656+6646+4];
if (spliceBit == 0xFFFFu) {
printf(" no splice information exists\n");
@ -146,7 +147,7 @@ bool WozFile::load(const std::string& filePath) {
}
printf("\n");
for (int i(0); i < 6646; ++i) {
trks[t][i] = *base++;
this->trks[t][i] = *base++;
}
}
delete[] buf;
@ -251,15 +252,6 @@ static std::uint8_t cb(std::uint8_t bit) {
return 255u; // should never happen
}
static void dumpQTrack(std::uint8_t currentQuarterTrack) {
if (currentQuarterTrack % 4) {
const std::uint8_t hundredths((currentQuarterTrack%4) * 25);
printf(" Reading from <---------- track 0x%02X +.%02d\n", currentQuarterTrack/4, hundredths);
} else {
printf(" Reading from <---------- track 0x%02X\n", currentQuarterTrack/4);
}
}
/*
* Rotate the floppy disk by one bit.
* In real life we don't care what track we're one, but for the
@ -274,14 +266,7 @@ void WozFile::rotateOneBit(std::uint8_t currentQuarterTrack) {
return; // there's no disk to rotate
}
// In WOZ track image, bits (i.e., magnetic field reversal on disk,
// or lack thereof) are packed into bytes, high bit to low bit.
// Really, it's the stream of bits returned by the MC3470 (but also
// possibly with random bits zeroed out).
// std::uint16_t before = (this->byt*8+bc(this->bit));
// printf("disk at bit: %d\n", this->byt*8+bc(this->bit));
// Move to next bit:
// Move to next bit
this->bit >>= 1;
// If we hit end of this byte, move on to beginning of next byte
@ -290,78 +275,81 @@ void WozFile::rotateOneBit(std::uint8_t currentQuarterTrack) {
this->bit = 0x80u;
}
// this is an empty track, so any of the following byte/bit
// adjustments don't apply now (they will be handled the
// next time we hit a non-empty track)
if (this->tmap[currentQuarterTrack] == 0xFFu) {
return;
}
// If we changed tracks since the last time we were called,
// we may need to adjust the rotational position. The new
// position will be at the same relative position as the
// previous, based on each track's length (tracks can be of
// different lengths in the WOZ image).
if (currentQuarterTrack != this->lastQuarterTrack) {
double oldLen = this->trk_bits[this->tmap[this->lastQuarterTrack]];
double newLen = this->trk_bits[this->tmap[currentQuarterTrack]];
double dif = newLen/oldLen;
if (dif < -0.000001 || 0.000001 < dif) {
// dumpQTrack(currentQuarterTrack);
// printf(" new track: bit pos: %d ", this->byt*8+bc(this->bit));
std::uint16_t newBit = (this->byt*8+bc(this->bit)) * dif;
double ratio = newLen/oldLen;
if (!(fabs(1-ratio) < 0.0001f)) {
std::uint16_t newBit = (this->byt*8+bc(this->bit)) * ratio;
this->byt = newBit / 8;
this->bit = cb(newBit % 8);
// printf("--> %d\n\n", this->byt*8+bc(this->bit));
}
this->lastQuarterTrack = currentQuarterTrack;
}
// Check for hitting the end of our track image,
// Check for hitting the end of our track,
// and if so, move back to the beginning.
// This is how we emulate a circular track on the floppy.
if (this->trk_bits[this->tmap[currentQuarterTrack]] <= this->byt*8+bc(this->bit)) {
// printf("\n<rewinding track here>\n");
this->byt = 0;
this->bit = 0x80u;
}
// std::uint16_t after = (this->byt*8+bc(this->bit));
// if (!(after % 0x100u)) {
// printf("\nnow at bit %04x\n", after);
// }
// if (after != before+1) {
// printf("\nbit changing from %04x to %04x\n", before, after);
// }
}
bool WozFile::getBit(std::uint8_t currentQuarterTrack) {
if (!isLoaded()) {
printf("\nNO DISK TO READ FROM (will generate random data)\n");
printf("No disk to read from; will generate random data.\n");
return false; // there's no disk, so no pulse
}
if (this->tmap[currentQuarterTrack] == 0xFFu) {
// printf("\nreading (random) from empty q-track: %d\n", currentQuarterTrack);
return false; // track doesn't exist
}
if (this->c_trks <= this->tmap[currentQuarterTrack]) { // shouldn't happen
printf("\nBAD TRACK quarterTrack %d mapped to TRKS index %d (count of tracks: %d)\n", currentQuarterTrack, this->tmap[currentQuarterTrack], this->c_trks);
return false; // track doesn't exist
return false; // empty track
}
if (this->c_trks <= this->tmap[currentQuarterTrack]) { // shouldn't happen
printf("INVALID quarterTrack %d mapped to TRKS index %d (count of tracks: %d)\n", currentQuarterTrack, this->tmap[currentQuarterTrack], this->c_trks);
return false;
}
// if (!(this->byt % 128) && this->bit == 0x01) {
// printf("\ngetBit--> ");
// }
// printf("%02x", this->byt*8+bc(this->bit));
return this->trks[this->tmap[currentQuarterTrack]][this->byt] & this->bit;
}
void WozFile::setBit(std::uint8_t currentQuarterTrack) {
void WozFile::setBit(std::uint8_t currentQuarterTrack, bool on) {
if (!isLoaded()) {
return; // there's no disk to write data to
}
if (!this->writable) {
return; // write-protected
}
if (this->c_trks <= this->tmap[currentQuarterTrack]) { // shouldn't happen
if (this->c_trks <= this->tmap[currentQuarterTrack]) {
return; // TODO track doesn't exist: create a new one
}
if (this->tmap[currentQuarterTrack] == 0xFFu) {
// track does not exist, create new one
}
// TODO extend track length if needed
this->trks[this->tmap[currentQuarterTrack]][this->byt] |= this->bit;
// TODO extend track length if needed????
if (on) {
this->trks[this->tmap[currentQuarterTrack]][this->byt] |= this->bit;
} else {
this->trks[this->tmap[currentQuarterTrack]][this->byt] &= ~this->bit;
}
}

View File

@ -59,6 +59,10 @@ class WozFile {
std::uint8_t bit;
std::uint16_t byt;
// We need to store which track were on, only so we can detect
// a change in tracks, and if so adjust our current byt/bit
// to be proportional with the new track. This is discussed
// in the WOZ file spec.
std::uint8_t lastQuarterTrack;
void checkForWriteProtection();
@ -89,7 +93,7 @@ public:
void rotateOneBit(std::uint8_t currentQuarterTrack);
bool getBit(std::uint8_t currentQuarterTrack);
void setBit(std::uint8_t currentQuarterTrack);
void setBit(std::uint8_t currentQuarterTrack, bool on);
};
#endif // WOZFILE_H