fix drive motor on cancels pending off; fix LSS timing during switch changes; fix GUI disk dirty flag

This commit is contained in:
Christopher Mosher 2018-12-27 15:03:46 -05:00
parent 117d4af8ef
commit ee420e1c02
6 changed files with 87 additions and 35 deletions

View File

@ -63,17 +63,17 @@ Apple2::~Apple2()
}
void Apple2::tick()
{
this->slts.tick();
void Apple2::tick() {
this->cpu.tick();
this->video.tick();
this->paddles.tick();
this->speaker.tick();
this->cassette.tick();
this->slts.tick();
this->video.tick();
this->paddles.tick();
this->speaker.tick();
this->cassette.tick();
if (this->revision > 0)
this->powerUpReset.tick();
if (this->revision > 0) {
this->powerUpReset.tick();
}
}
void Apple2::powerOn()

View File

@ -25,6 +25,7 @@ DiskController::DiskController(ScreenImage& gui, int slot, bool lss13):
currentDrive(&this->drive1),
load(false),
write(false),
ioStepped(false),
lssp6rom(lss13),
seq(0x20), // gotta start somewhere
t(0) {
@ -39,6 +40,8 @@ unsigned char DiskController::io(const unsigned short addr, const unsigned char
const unsigned char q = (addr & 0x000E) >> 1;
const bool on = (addr & 0x0001);
// printf("Q%d<--%s\n", q, on?"ON":"OFF");
switch (q) {
case 0:
case 1: // TODO if phase-1 is on, it also acts as write-protect (UA2, 9-8)
@ -57,19 +60,22 @@ unsigned char DiskController::io(const unsigned short addr, const unsigned char
break;
case 6:
this->load = on;
// TODO when to do these GUI updates?
// this->gui.setDirty(this->slot,getCurrentDriveNumber(),true);
break;
case 7:
this->write = on;
break;
}
// if (this->dataRegister == 0xD5u) {
// printf("\n");
// }
// if (this->dataRegister & 0x80u) {
// printf("%02X ", this->dataRegister);
// }
if (this->write && !this->load) {
this->gui.setDirty(this->slot,getCurrentDriveNumber(),true);
}
// UA2, 9-23, Figure 9.12
// 2 LSS cycles need to happen AFTER setting the Qx switch, and
// BEFORE reading LSS's update of the data register
this->ioStepped = false;
tick();
this->ioStepped = true; // flag that we ran it already
return on ? d : this->dataRegister;
}
@ -81,8 +87,13 @@ unsigned char DiskController::io(const unsigned short addr, const unsigned char
* (When the motor is on, that is.)
*/
void DiskController::tick() {
if (this->ioStepped) { // if we already ran it, above in io(), skip here
this->ioStepped = false;
return;
}
this->gui.setIO(this->slot, getCurrentDriveNumber(), this->motor.isOn());
if (!this->motor.isOn()) {
this->ioStepped = false;
return;
}
this->motor.tick(); // only need to send tick when motor is powered on
@ -90,7 +101,6 @@ void DiskController::tick() {
rotateCurrentDisk();
// run two LSS cycles = 2MHz
stepLss();
// pulse lasts only 500 nanoseconds (1 LSS clock cycle), so clear it now:
this->currentDrive->clearPulse();

View File

@ -42,6 +42,7 @@ private:
bool load; // Q6
bool write; // Q7
bool ioStepped;
/*
* Only one drive's motor can be on at a time,

View File

@ -35,6 +35,10 @@ bool DriveMotor::isOn() const {
void DriveMotor::power(bool on) {
if (on) {
this->on = true;
if (this->pendingTicks > 0) {
this->pendingTicks = 0;
// printf("MOTOR: cancel pending power off\n");
}
// printf("MOTOR: power on\n");
} else {
// delay power-off by about one second (a little longer, for momentum)

View File

@ -51,6 +51,12 @@ WozFile::WozFile() : tmap(0) {
WozFile::~WozFile() {
}
static void print_compat(std::uint16_t compat, std::uint16_t mask, const char *name) {
if (compat & mask) {
printf(" Apple %s\n", name);
}
}
bool WozFile::load(const std::string& filePath) {
std::ifstream in(filePath.c_str(),std::ios::binary|std::ios::in);
if (!in.is_open()) {
@ -111,6 +117,23 @@ bool WozFile::load(const std::string& filePath) {
this->creator = std::string((char*)buf+5, 32);
printf("Creator: \"%.32s\"\n", buf+5);
this->timing = buf[39];
printf("Timing: %d/8 microseconds per bit\n", this->timing);
std::uint16_t compat = *((std::uint16_t*)buf+40);
printf("Campatible hardware: ");
if (!compat) {
printf("unknown\n");
} else {
printf("\n");
print_compat(compat, 0x0001, "][");
print_compat(compat, 0x0002, "][ plus");
print_compat(compat, 0x0004, "//e");
print_compat(compat, 0x0008, "//c");
print_compat(compat, 0x0010, "//e (enhanced)");
print_compat(compat, 0x0020, "IIGS");
print_compat(compat, 0x0040, "IIc Plus");
print_compat(compat, 0x0080, "///");
print_compat(compat, 0x0100, "/// plus");
}
delete[] buf;
}
break;
@ -118,13 +141,13 @@ bool WozFile::load(const std::string& filePath) {
this->tmap = new std::uint8_t[chunk_size];
in.read((char*)this->tmap, chunk_size);
this->initalQtrack = 0;
while (this->initalQtrack < chunk_size && this->tmap[this->initalQtrack] == 0xFFu) {
++this->initalQtrack;
this->initialQtrack = 0;
while (this->initialQtrack < chunk_size && this->tmap[this->initialQtrack] == 0xFFu) {
++this->initialQtrack;
}
if (this->initalQtrack == chunk_size) {
this->initalQtrack = 0xFFu;
printf("Could not find any initial track (%02X).\n", this->initalQtrack);
if (this->initialQtrack == chunk_size) {
this->initialQtrack = 0xFFu;
printf("Could not find any initial track (%02X).\n", this->initialQtrack);
}
this->finalQtrack = chunk_size-1;
@ -147,10 +170,10 @@ bool WozFile::load(const std::string& filePath) {
printf("TMAP track 0x%02X : TRKS track index 0x%02X", t/100, tmap[qt]);
}
printf("\x1b[0m");
if (qt == this->initalQtrack && qt == this->finalQtrack) {
if (qt == this->initialQtrack && qt == this->finalQtrack) {
printf(" <-- lone track");
} else if (qt == this->initalQtrack) {
printf(" <-- inital track");
} else if (qt == this->initialQtrack) {
printf(" <-- initial track");
} else if (qt == this->finalQtrack) {
printf(" <-- final track");
}
@ -177,8 +200,9 @@ bool WozFile::load(const std::string& filePath) {
if (ts.blockCount) {
printf("TRK index %02X: start byte in BITS %08x; %08x bytes; %08x bits ", qt, ts.blockFirst<<9, ts.blockCount<<9, ts.bitCount);
this->trk_bits[qt] = ts.bitCount;
this->trk[qt] = new std::uint8_t[ts.blockCount<<9];
memcpy(this->trk[qt], buf+C_QTRACK*8+(ts.blockFirst<<9), ts.blockCount<<9);
this->trk_byts[qt] = ts.blockCount<<9;
this->trk[qt] = new std::uint8_t[this->trk_byts[qt]];
memcpy(this->trk[qt], buf+C_QTRACK*8+(ts.blockFirst<<9), this->trk_byts[qt]);
printf("("
BYTE_TO_BINARY_PATTERN
BYTE_TO_BINARY_PATTERN
@ -272,12 +296,22 @@ void WozFile::save() {
if (isWriteProtected() || !isLoaded()) {
return;
}
// std::ofstream out(filePath.c_str(),std::ios::binary);
// TODO SAVE FILE!
// out.flush();
// out.close();
std::ofstream out(filePath.c_str(), std::ios::binary);
// this->modified = false;
// TODO: SAVE WOZ 2.0 format FILE PROPERLY!
for (std::uint8_t qt(0); qt < C_QTRACK; ++qt) {
// staight dump of track FOR DEBUGGING ONLY
if (this->trk[qt]) {
printf("dumping q-track: %02X, %08X bytes\n", qt, this->trk_byts[qt]);
out.write(reinterpret_cast<char*>(this->trk[qt]), this->trk_byts[qt]);
}
}
out.flush();
out.close();
// TODO: this->modified = false;
}
void WozFile::unload() {
@ -413,6 +447,7 @@ void WozFile::setBit(std::uint8_t currentQuarterTrack, bool on) {
return; // write-protected
}
// printf("%c",(on?'1':'0')); fflush(stdout);
if (on) {
this->trk[this->tmap[currentQuarterTrack]][this->byt] |= this->bit;
} else {

View File

@ -59,7 +59,7 @@ class WozFile {
// map of quarter-tracks from T00.00 through T39.75, values are indexes into trk
std::uint8_t* tmap;
// first actual quarter-track (e.g., 0 for normal 35-track disk), or 0xFF if no tracks
std::uint8_t initalQtrack;
std::uint8_t initialQtrack;
// last actual quarter-track (e.g., 136 for normal 35-track disk), or 0xFF if no tracks
std::uint8_t finalQtrack;
@ -67,6 +67,8 @@ class WozFile {
std::uint8_t* trk[C_QTRACK];
// count of bits in each track
std::uint32_t trk_bits[C_QTRACK];
// count of allocated bytes
std::uint16_t trk_byts[C_QTRACK];
// bit and byt together represent the rotational position
// of the floppy disk.