1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Merge pull request #431 from TomHarte/DiskIIRemap

Shuffles the Disk II ROM at load time into B.A.P. form.
This commit is contained in:
Thomas Harte 2018-05-09 22:10:29 -04:00 committed by GitHub
commit 86192b18d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 35 deletions

View File

@ -13,9 +13,9 @@
using namespace Apple; using namespace Apple;
namespace { namespace {
const uint8_t input_command = 0x1; // i.e. Q6 const uint8_t input_command = 0x4; // i.e. Q6
const uint8_t input_mode = 0x2; // i.e. Q7 const uint8_t input_mode = 0x8; // i.e. Q7
const uint8_t input_flux = 0x4; const uint8_t input_flux = 0x1;
} }
DiskII::DiskII() : DiskII::DiskII() :
@ -90,47 +90,24 @@ uint8_t DiskII::get_shift_register() {
} }
void DiskII::run_for(const Cycles cycles) { void DiskII::run_for(const Cycles cycles) {
/*
... address the P6 ROM with an index byte built up as:
+-------+-------+-------+-------+-------+-------+-------+-------+
| STATE | STATE | STATE | PULSE | Q7 | Q6 | SR | STATE |
| bit 0 | bit 2 | bit 3 | | | | MSB | bit 1 |
+-------+-------+-------+-------+-------+-------+-------+-------+
7 6 5 4 3 2 1 0
...
The bytes in the P6 ROM has the high four bits reversed compared to the BAPD charts, so you will have to reverse them after fetching the byte.
*/
if(is_sleeping()) return; if(is_sleeping()) return;
int integer_cycles = cycles.as_int(); int integer_cycles = cycles.as_int();
if(!controller_can_sleep_) { if(!controller_can_sleep_) {
while(integer_cycles--) { while(integer_cycles--) {
const int address = const int address = (state_ & 0xf0) | inputs_ | ((shift_register_&0x80) >> 6);
(inputs_ << 2) |
((shift_register_&0x80) >> 6) |
((state_&0x2) >> 1) |
((state_&0x1) << 7) |
((state_&0x4) << 4) |
((state_&0x8) << 2);
inputs_ |= input_flux; inputs_ |= input_flux;
state_ = state_machine_[static_cast<std::size_t>(address)];
const uint8_t update = state_machine_[static_cast<std::size_t>(address)]; switch(state_ & 0xf) {
state_ = update >> 4;
state_ = ((state_ & 0x8) ? 0x1 : 0x0) | ((state_ & 0x4) ? 0x2 : 0x0) | ((state_ & 0x2) ? 0x4 : 0x0) | ((state_ & 0x1) ? 0x8 : 0x0);
uint8_t command = update & 0xf;
switch(command) {
case 0x0: shift_register_ = 0; break; // clear case 0x0: shift_register_ = 0; break; // clear
case 0x9: shift_register_ = static_cast<uint8_t>(shift_register_ << 1); break; // shift left, bringing in a zero case 0x9: shift_register_ = static_cast<uint8_t>(shift_register_ << 1); break; // shift left, bringing in a zero
case 0xd: shift_register_ = static_cast<uint8_t>((shift_register_ << 1) | 1); break; // shift left, bringing in a one case 0xd: shift_register_ = static_cast<uint8_t>((shift_register_ << 1) | 1); break; // shift left, bringing in a one
case 0xb: shift_register_ = data_register_; break; // load case 0xb: shift_register_ = data_register_; break; // load
case 0xa:
case 0xa: // shift right, bringing in write protected status
shift_register_ = (shift_register_ >> 1) | (is_write_protected() ? 0x80 : 0x00); shift_register_ = (shift_register_ >> 1) | (is_write_protected() ? 0x80 : 0x00);
break; // shift right, bringing in write protected status break;
default: break; default: break;
} }
@ -160,8 +137,47 @@ bool DiskII::is_write_protected() {
} }
void DiskII::set_state_machine(const std::vector<uint8_t> &state_machine) { void DiskII::set_state_machine(const std::vector<uint8_t> &state_machine) {
state_machine_ = state_machine; /*
// TODO: shuffle ordering here? An unadulterated P6 ROM read returns values with an address formed as:
state b0, state b2, state b3, pulse, Q7, Q6, shift, state b1
... and has the top nibble reflected. Beneath Apple Pro-DOS uses a
different order and several of the online copies are reformatted
into that order.
So the code below remaps into Beneath Apple Pro-DOS order if the
supplied state machine isn't already in that order.
*/
if(state_machine[0] != 0x18) {
for(size_t source_address = 0; source_address < 256; ++source_address) {
// Remap into Beneath Apple Pro-DOS address form.
size_t destination_address =
((source_address&0x80) ? 0x10 : 0x00) |
((source_address&0x01) ? 0x20 : 0x00) |
((source_address&0x40) ? 0x40 : 0x00) |
((source_address&0x20) ? 0x80 : 0x00) |
((source_address&0x10) ? 0x01 : 0x00) |
((source_address&0x08) ? 0x08 : 0x00) |
((source_address&0x04) ? 0x04 : 0x00) |
((source_address&0x02) ? 0x02 : 0x00);
uint8_t source_value = state_machine[source_address];
// Remap into Beneath Apple Pro-DOS value form.
source_value =
((source_value & 0x80) ? 0x10 : 0x0) |
((source_value & 0x40) ? 0x20 : 0x0) |
((source_value & 0x20) ? 0x40 : 0x0) |
((source_value & 0x10) ? 0x80 : 0x0) |
(source_value & 0x0f);
// Store.
state_machine_[destination_address] = source_value;
}
} else {
memcpy(&state_machine_[0], &state_machine[0], 128);
}
} }
void DiskII::set_disk(const std::shared_ptr<Storage::Disk::Disk> &disk, int drive) { void DiskII::set_disk(const std::shared_ptr<Storage::Disk::Disk> &disk, int drive) {

View File

@ -15,6 +15,7 @@
#include "../../Storage/Disk/Disk.hpp" #include "../../Storage/Disk/Disk.hpp"
#include "../../Storage/Disk/Drive.hpp" #include "../../Storage/Disk/Drive.hpp"
#include <array>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
@ -66,7 +67,7 @@ class DiskII:
int stepper_position_ = 0; int stepper_position_ = 0;
bool is_write_protected(); bool is_write_protected();
std::vector<uint8_t> state_machine_; std::array<uint8_t, 256> state_machine_;
Storage::Disk::Drive drives_[2]; Storage::Disk::Drive drives_[2];
bool drive_is_sleeping_[2]; bool drive_is_sleeping_[2];
bool controller_can_sleep_ = false; bool controller_can_sleep_ = false;