From ee420e1c0257c62d1f0cc228a95af77dfc1c238a Mon Sep 17 00:00:00 2001 From: Christopher Mosher Date: Thu, 27 Dec 2018 15:03:46 -0500 Subject: [PATCH] fix drive motor on cancels pending off; fix LSS timing during switch changes; fix GUI disk dirty flag --- src/apple2.cpp | 18 ++++++------ src/diskcontroller.cpp | 28 ++++++++++++------ src/diskcontroller.h | 1 + src/drivemotor.cpp | 4 +++ src/wozfile.cpp | 67 ++++++++++++++++++++++++++++++++---------- src/wozfile.h | 4 ++- 6 files changed, 87 insertions(+), 35 deletions(-) diff --git a/src/apple2.cpp b/src/apple2.cpp index a8c0104..8cf75ba 100644 --- a/src/apple2.cpp +++ b/src/apple2.cpp @@ -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() diff --git a/src/diskcontroller.cpp b/src/diskcontroller.cpp index b6fae26..fa8c6af 100644 --- a/src/diskcontroller.cpp +++ b/src/diskcontroller.cpp @@ -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(); diff --git a/src/diskcontroller.h b/src/diskcontroller.h index 45fc65b..6cf22be 100644 --- a/src/diskcontroller.h +++ b/src/diskcontroller.h @@ -42,6 +42,7 @@ private: bool load; // Q6 bool write; // Q7 + bool ioStepped; /* * Only one drive's motor can be on at a time, diff --git a/src/drivemotor.cpp b/src/drivemotor.cpp index 559a544..d7c5a6d 100644 --- a/src/drivemotor.cpp +++ b/src/drivemotor.cpp @@ -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) diff --git a/src/wozfile.cpp b/src/wozfile.cpp index bab5d56..27303b5 100644 --- a/src/wozfile.cpp +++ b/src/wozfile.cpp @@ -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(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 { diff --git a/src/wozfile.h b/src/wozfile.h index 679e41e..446a859 100644 --- a/src/wozfile.h +++ b/src/wozfile.h @@ -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.