mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Seems to do enough padding out to get me to my second failing ADB command.
That's better than failing at the first.
This commit is contained in:
parent
32374444ba
commit
0ae49b356a
@ -12,6 +12,14 @@
|
|||||||
|
|
||||||
using namespace Apple::IIgs::ADB;
|
using namespace Apple::IIgs::ADB;
|
||||||
|
|
||||||
|
// MARK: - Configuration.
|
||||||
|
|
||||||
|
void GLU::set_is_rom03(bool is_rom03) {
|
||||||
|
is_rom03_ = is_rom03;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - External interface.
|
||||||
|
|
||||||
uint8_t GLU::get_keyboard_data() {
|
uint8_t GLU::get_keyboard_data() {
|
||||||
// The classic Apple II serial keyboard register:
|
// The classic Apple II serial keyboard register:
|
||||||
// b7: key strobe.
|
// b7: key strobe.
|
||||||
@ -50,6 +58,15 @@ uint8_t GLU::get_modifier_status() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GLU::get_data() {
|
uint8_t GLU::get_data() {
|
||||||
|
printf("ADB get data\n");
|
||||||
|
if(!pending_response_.empty()) {
|
||||||
|
// A bit yucky, pull from the from the front.
|
||||||
|
// This keeps my life simple for now, even though it's inefficient.
|
||||||
|
const uint8_t next = pending_response_[0];
|
||||||
|
pending_response_.erase(pending_response_.begin());
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
// b0–2: number of data bytes to be returned.
|
// b0–2: number of data bytes to be returned.
|
||||||
// b3: 1 = a valid service request is pending; 0 = no request pending.
|
// b3: 1 = a valid service request is pending; 0 = no request pending.
|
||||||
// b4: 1 = control, command and delete keys have been pressed simultaneously; 0 = they haven't.
|
// b4: 1 = control, command and delete keys have been pressed simultaneously; 0 = they haven't.
|
||||||
@ -68,13 +85,102 @@ uint8_t GLU::get_status() {
|
|||||||
// b2: 1 = keyboard data interrupt is enabled.
|
// b2: 1 = keyboard data interrupt is enabled.
|
||||||
// b1: 1 = mouse x-data is available; 0 = y.
|
// b1: 1 = mouse x-data is available; 0 = y.
|
||||||
// b0: 1 = command register is full (set when command is written); 0 = empty (cleared when data is read).
|
// b0: 1 = command register is full (set when command is written); 0 = empty (cleared when data is read).
|
||||||
return 0x00;
|
const uint8_t status =
|
||||||
|
(pending_response_.empty() ? 0 : 0x20); // Data is valid if a response is pending.
|
||||||
|
printf("ADB get status : %02x\n", status);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLU::set_command(uint8_t command) {
|
void GLU::set_command(uint8_t command) {
|
||||||
printf("TODO: set ADB command: %02x\n", command);
|
// Accumulate input until a full comamnd is received;
|
||||||
|
// the state machine otherwise gets somewhat oversized.
|
||||||
|
next_command_.push_back(command);
|
||||||
|
printf("ADB command: %02x\n", command);
|
||||||
|
|
||||||
|
// Command dispatch; each entry should do whatever it needs
|
||||||
|
// to do and then either: (i) break, if completed; or
|
||||||
|
// (ii) return, if awaiting further input.
|
||||||
|
#define RequireSize(n) if(next_command_.size() < (n)) return;
|
||||||
|
switch(next_command_[0]) {
|
||||||
|
// One-byte commands.
|
||||||
|
case 0x01: abort(); break;
|
||||||
|
case 0x02: reset_microcontroller(); break;
|
||||||
|
case 0x03: flush_keyboard_buffer(); break;
|
||||||
|
|
||||||
|
case 0x04: // Set modes.
|
||||||
|
RequireSize(2);
|
||||||
|
set_modes(modes_ | next_command_[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x05: // Clear modes.
|
||||||
|
RequireSize(2);
|
||||||
|
set_modes(modes_ & ~next_command_[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x06: // Set configuration bytes
|
||||||
|
RequireSize(4);
|
||||||
|
set_configuration_bytes(&next_command_[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x07: // Sync.
|
||||||
|
RequireSize(is_rom03_ ? 9 : 5);
|
||||||
|
set_modes(next_command_[1]);
|
||||||
|
set_configuration_bytes(&next_command_[2]);
|
||||||
|
|
||||||
|
// ROM03 seems to expect to send an extra four bytes here,
|
||||||
|
// with values 0x20, 0x26, 0x2d, 0x2d.
|
||||||
|
// TODO: what does the ROM03-paired ADB GLU do with the extra four bytes?
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0d: // Get version number.
|
||||||
|
pending_response_.push_back(6); // Seems to be what ROM03 is looking for?
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Enable device SRQ.
|
||||||
|
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
|
||||||
|
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
|
||||||
|
set_device_srq(device_srq_ | (1 << (next_command_[1] & 0xf)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Disable device SRQ.
|
||||||
|
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
|
||||||
|
case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
|
||||||
|
set_device_srq(device_srq_ & ~(1 << (next_command_[1] & 0xf)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("TODO: ADB command %02x\n", next_command_[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#undef RequireSize
|
||||||
|
|
||||||
|
// Input was dealt with, so throw it away.
|
||||||
|
next_command_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLU::set_status(uint8_t status) {
|
void GLU::set_status(uint8_t status) {
|
||||||
printf("TODO: set ADB status %02x\n", status);
|
printf("TODO: set ADB status %02x\n", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Internal commands.
|
||||||
|
|
||||||
|
void GLU::set_modes(uint8_t modes) {
|
||||||
|
modes_ = modes; // TODO: and this has what effect?
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::abort() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::reset_microcontroller() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::flush_keyboard_buffer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::set_configuration_bytes(uint8_t *) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::set_device_srq(int mask) {
|
||||||
|
// TODO: do I need to do any more than this here?
|
||||||
|
device_srq_ = mask;
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define Apple_IIgs_ADB_hpp
|
#define Apple_IIgs_ADB_hpp
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Apple {
|
namespace Apple {
|
||||||
namespace IIgs {
|
namespace IIgs {
|
||||||
@ -17,6 +18,10 @@ namespace ADB {
|
|||||||
|
|
||||||
class GLU {
|
class GLU {
|
||||||
public:
|
public:
|
||||||
|
// Behaviour varies slightly between the controller shipped with ROM01 machines
|
||||||
|
// and that shipped with ROM03 machines; use this to set the desired behaviour.
|
||||||
|
void set_is_rom03(bool);
|
||||||
|
|
||||||
uint8_t get_keyboard_data();
|
uint8_t get_keyboard_data();
|
||||||
uint8_t get_mouse_data();
|
uint8_t get_mouse_data();
|
||||||
uint8_t get_modifier_status();
|
uint8_t get_modifier_status();
|
||||||
@ -28,6 +33,23 @@ class GLU {
|
|||||||
void set_command(uint8_t);
|
void set_command(uint8_t);
|
||||||
void set_status(uint8_t);
|
void set_status(uint8_t);
|
||||||
void clear_key_strobe();
|
void clear_key_strobe();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_rom03_ = false;
|
||||||
|
std::vector<uint8_t> next_command_;
|
||||||
|
std::vector<uint8_t> pending_response_;
|
||||||
|
|
||||||
|
void abort();
|
||||||
|
void reset_microcontroller();
|
||||||
|
void flush_keyboard_buffer();
|
||||||
|
|
||||||
|
void set_modes(uint8_t modes);
|
||||||
|
uint8_t modes_ = 0;
|
||||||
|
|
||||||
|
void set_device_srq(int mask);
|
||||||
|
int device_srq_ = 0;
|
||||||
|
|
||||||
|
void set_configuration_bytes(uint8_t *);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,9 @@ class ConcreteMachine:
|
|||||||
memory_.set_storage(ram_, rom_);
|
memory_.set_storage(ram_, rom_);
|
||||||
video_->set_internal_ram(&ram_[ram_.size() - 128*1024]);
|
video_->set_internal_ram(&ram_[ram_.size() - 128*1024]);
|
||||||
|
|
||||||
|
// Select appropriate ADB behaviour.
|
||||||
|
adb_glu_.set_is_rom03(target.model == Target::Model::ROM03);
|
||||||
|
|
||||||
// TODO: enable once machine is otherwise sane.
|
// TODO: enable once machine is otherwise sane.
|
||||||
// Memory::Fuzz(ram_);
|
// Memory::Fuzz(ram_);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user