diff --git a/Analyser/Static/StaticAnalyser.cpp b/Analyser/Static/StaticAnalyser.cpp index bfb103d3a..e544ab2e7 100644 --- a/Analyser/Static/StaticAnalyser.cpp +++ b/Analyser/Static/StaticAnalyser.cpp @@ -92,7 +92,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform:: Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81 Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26 Format("adf", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn) // ADF - Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN (cartridge dump) +// Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN (cartridge dump) Format("bin", result.disks, Disk::DiskImageHolder, TargetPlatform::Macintosh) // BIN (PlusToo disk image) Format("cas", result.tapes, Tape::CAS, TargetPlatform::MSX) // CAS Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT diff --git a/Components/DiskII/IWM.cpp b/Components/DiskII/IWM.cpp index 9e7f29555..6164d45b0 100644 --- a/Components/DiskII/IWM.cpp +++ b/Components/DiskII/IWM.cpp @@ -54,10 +54,10 @@ uint8_t IWM::read(int address) { return 0xff; // "Read all 1s". - case 0: - printf("Reading all 1s\n"); - return 0xff; +// printf("Reading all 1s\n"); +// return 0xff; + case 0: case ENABLE: /* Read data register. */ if(data_register_ & 0x80) { printf("[%02x] ", data_register_); @@ -78,30 +78,37 @@ uint8_t IWM::read(int address) { (/ENBL1 is low when the first drive's motor is on; /ENBL2 is low when the second drive's motor is on. If the 1-second timer is enabled, motors remain on for one second after being programmatically disabled.) */ - printf("Reading status (including [%d] ", active_drive_); + printf("Reading status (including [%d][%c%c%c%c] ", active_drive_, (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-'); // Determine the SENSE input. uint8_t sense = 0x00; switch(state_ & (CA2 | CA1 | CA0 | SEL)) { default: - printf("unknown [%c%c%c%c])\n", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-'); + printf("unknown)\n"); break; - case 0: // Head step direction. - printf("head step direction)\n"); - break; + // 4 = step finished (0 = done) + // B = ready (0 = ready) + // 8 = motor on + // + // {CA1,CA0,SEL,CA2} + +// case 0: // Head step direction. +// printf("head step direction)\n"); +// break; case SEL: // Disk in place. printf("disk in place)\n"); sense = drives_[active_drive_] && drives_[active_drive_]->has_disk() ? 0x00 : 0x80; break; - case CA0: // Disk head stepping. - printf("head stepping)\n"); - break; - +// case CA0: // Disk head step completed (1 = still stepping?). +// printf("head stepping)\n"); +// break; +// case CA0|SEL: // Disk locked (i.e. write-protect tab). printf("disk locked)\n"); + sense = drives_[active_drive_] && drives_[active_drive_]->get_is_read_only() ? 0x00 : 0x80; break; case CA1: // Disk motor running. @@ -116,21 +123,24 @@ uint8_t IWM::read(int address) { case CA1|CA0|SEL: // Tachometer (?) printf("tachometer)\n"); + sense = drives_[active_drive_] && drives_[active_drive_]->get_tachometer() ? 0x00 : 0x80; break; - case CA2: // Read data, lower head. - printf("data, lower head)\n"); - break; - - case CA2|SEL: // Read data, upper head. - printf("data, upper head)\n"); - break; - +// case CA2: // Read data, lower head. +// printf("data, lower head)\n"); +// break; +// +// case CA2|SEL: // Read data, upper head. +// printf("data, upper head)\n"); +// break; +// case CA2|CA1: // Single- or double-sided drive. printf("single- or double-sided drive)\n"); + sense = drives_[active_drive_] && (drives_[active_drive_]->get_head_count() == 1) ? 0x00 : 0x80; break; - case CA2|CA1|CA0|SEL: // Drive installed. + case CA2|CA1|CA0: // Drive installed. (per the Mac Plus ROM) + case CA2|CA1|CA0|SEL: // Drive installed. (per Inside Macintosh) printf("drive installed)\n"); sense = drives_[active_drive_] ? 0x00 : 0x80; break; @@ -151,7 +161,7 @@ uint8_t IWM::read(int address) { bit 7: 1 = write data buffer ready for data. */ printf("Reading write handshake\n"); - return 0x1f; + return 0x1f | 0x80 | 0x40; } return 0xff; @@ -203,11 +213,13 @@ void IWM::access(int address) { address &= 0xf; const auto mask = 1 << (address >> 1); +// printf("[(%02x) %c%c%c%c ", mask, (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-'); if(address & 1) { state_ |= mask; } else { state_ &= ~mask; } +// printf("-> %c%c%c%c] ", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-'); // React appropriately to motor requests. switch(address >> 1) { @@ -229,7 +241,7 @@ void IWM::access(int address) { break; case 5: { - const int new_drive = address & 1; + const int new_drive = (address & 1)^1; if(new_drive != active_drive_) { if(drives_[active_drive_]) drives_[active_drive_]->set_motor_on(false); active_drive_ = new_drive; @@ -240,11 +252,11 @@ void IWM::access(int address) { } void IWM::set_select(bool enabled) { - // Augment switch state with the value of the SEL line; - // it's active low, which is implicitly inverted here for - // consistency in the meaning of state_ bits. - if(!enabled) state_ |= 0x100; - else state_ &= ~0x100; + // Store SEL as an extra state bit. +// printf("[%c%c%c%c ", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-'); + if(enabled) state_ |= SEL; + else state_ &= ~SEL; +// printf("-> %c%c%c%c] ", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-'); } // MARK: - Active logic @@ -264,6 +276,7 @@ void IWM::run_for(const Cycles cycles) { const bool run_disk = drive_motor_on_ && drives_[active_drive_]; int integer_cycles = cycles.as_int(); switch(state_ & (Q6 | Q7 | ENABLE)) { + case 0: case ENABLE: // i.e. read mode. while(integer_cycles--) { if(run_disk) { @@ -306,4 +319,3 @@ void IWM::set_drive(int slot, Storage::Disk::Drive *drive) { drives_[slot] = drive; drive->set_event_delegate(this); } - diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index 32dbad2f9..76e6f986b 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -187,6 +187,7 @@ template class ConcreteMachin case 0x68f000: // The IWM; this is a purely polled device, so can be run on demand. +// printf("[%06x]: ", mc68000_.get_state().program_counter); iwm_.flush(); if(cycle.operation & Microcycle::Read) { cycle.value->halves.low = iwm_.iwm.read(register_address); @@ -368,7 +369,8 @@ template class ConcreteMachin b2–b0: audio output volume */ iwm_.flush(); - iwm_.iwm.set_select(!(value & 0x20)); + printf("{SEL: %c} ", (value & 0x20) ? 't' : 'f'); + iwm_.iwm.set_select(!!(value & 0x20)); machine_.set_use_alternate_buffers(!(value & 0x40), !(value&0x08)); machine_.set_rom_is_overlay(!!(value & 0x10)); @@ -406,6 +408,7 @@ template class ConcreteMachin case Port::B: return + 0x08 | // Mouse button not down. (clock_.get_data() ? 0x02 : 0x00) | (video_.is_outputting() ? 0x00 : 0x40); // TODO: mouse button, y2, x2 diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 7d5ce99dc..adb8d2105 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -216,7 +216,7 @@ template void Proces case ExecutionState::BeginInterrupt: #ifdef LOG_TRACE - should_log = true; +// should_log = true; #endif active_program_ = nullptr; active_micro_op_ = interrupt_micro_ops_; @@ -284,7 +284,8 @@ template void Proces } #ifdef LOG_TRACE - should_log |= (program_counter_.full - 4) == 0x00400690; + should_log |= (program_counter_.full - 4) == 0x004006F4; +// should_log = ((program_counter_.full - 4) >= 0x417D9E) && ((program_counter_.full - 4) <= 0x419D96); #endif if(instructions[decoded_instruction_.full].micro_operations) { diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp index 8ce8b6110..375c974ad 100644 --- a/Storage/Disk/Drive.cpp +++ b/Storage/Disk/Drive.cpp @@ -112,6 +112,15 @@ int Drive::get_head_count() { return available_heads_; } +bool Drive::get_tachometer() { + // First guess: the tachometer ticks once per rotation. + return get_rotation() > 0.5f; +} + +float Drive::get_rotation() { + return get_time_into_track().get(); +} + Storage::Time Drive::get_time_into_track() { // `result` will initially be amount of time since the index hole was seen as a // proportion of a second; convert it into proportion of a rotation, simplify and return. diff --git a/Storage/Disk/Drive.hpp b/Storage/Disk/Drive.hpp index e86bad566..b8cc04989 100644 --- a/Storage/Disk/Drive.hpp +++ b/Storage/Disk/Drive.hpp @@ -149,9 +149,23 @@ class Drive: public ClockingHint::Source, public TimedEventLoop { */ void set_rotation_speed(float revolutions_per_minute); + /*! + @returns the current value of the tachometer pulse offered by some drives. + */ + bool get_tachometer(); + protected: + /*! + Announces the result of a step. + */ virtual void did_step(HeadPosition to_position) {} + /*! + @returns the current rotation of the disk, a float in the half-open range + 0.0 (the index hole) to 1.0 (back to the index hole, a whole rotation later). + */ + float get_rotation(); + private: // Drives contain an entire disk; from that a certain track // will be currently under the head.