mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-07 23:29:06 +00:00
Attempts to wire up M50470 and GLU.
Resulting in an unexpected interest in R15. Bugs to find, I guess.
This commit is contained in:
parent
57e0fdfadc
commit
e8e604dc3c
@ -14,7 +14,11 @@
|
|||||||
|
|
||||||
using namespace InstructionSet::M50740;
|
using namespace InstructionSet::M50740;
|
||||||
|
|
||||||
Executor::Executor() {
|
namespace {
|
||||||
|
constexpr int port_remap[] = {0, 1, 2, 0, 3};
|
||||||
|
}
|
||||||
|
|
||||||
|
Executor::Executor(PortHandler &port_handler) : port_handler_(port_handler) {
|
||||||
// Cut down the list of all generated performers to those the processor actually uses, and install that
|
// Cut down the list of all generated performers to those the processor actually uses, and install that
|
||||||
// for future referencing by action_for.
|
// for future referencing by action_for.
|
||||||
Decoder decoder;
|
Decoder decoder;
|
||||||
@ -58,20 +62,22 @@ uint8_t Executor::read(uint16_t address) {
|
|||||||
// "Port R"; sixteen four-bit ports
|
// "Port R"; sixteen four-bit ports
|
||||||
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
|
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
|
||||||
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
|
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
|
||||||
printf("TODO: Port R\n");
|
printf("TODO: Port R [r %04x]\n", address);
|
||||||
return 0xff;
|
return 0xff;
|
||||||
|
|
||||||
// Ports P0–P3.
|
// Ports P0–P3.
|
||||||
case 0xe0: case 0xe1:
|
case 0xe0: case 0xe2:
|
||||||
case 0xe2: case 0xe3:
|
case 0xe4: case 0xe8:
|
||||||
case 0xe4: case 0xe5:
|
return port_handler_.get_port_input(port_remap[(address - 0xe0) >> 1]);
|
||||||
case 0xe8: case 0xe9:
|
|
||||||
printf("TODO: Ports P0–P3\n");
|
case 0xe1: case 0xe3:
|
||||||
|
case 0xe5: case 0xe9:
|
||||||
|
printf("TODO: Ports P0–P3 direction [r %04x]\n", address);
|
||||||
return 0xff;
|
return 0xff;
|
||||||
|
|
||||||
// Timers.
|
// Timers.
|
||||||
case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
|
case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
|
||||||
printf("TODO: Timers\n");
|
printf("TODO: Timers [r %04x]\n", address);
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,6 +90,30 @@ void Executor::write(uint16_t address, uint8_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: all external IO ports.
|
// TODO: all external IO ports.
|
||||||
|
switch(address) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
// "Port R"; sixteen four-bit ports
|
||||||
|
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
|
||||||
|
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
|
||||||
|
printf("TODO: Port R [w %04x %02x]\n", address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Ports P0–P3.
|
||||||
|
case 0xe0: case 0xe2:
|
||||||
|
case 0xe4: case 0xe8:
|
||||||
|
return port_handler_.set_port_output(port_remap[(address - 0xe0) >> 1], value);
|
||||||
|
|
||||||
|
case 0xe1: case 0xe3:
|
||||||
|
case 0xe5: case 0xe9:
|
||||||
|
printf("TODO: Ports P0–P3 direction [w %04x %02x]\n", address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Timers.
|
||||||
|
case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
|
||||||
|
printf("TODO: Timers [w %04x %02x]\n", address, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Executor::push(uint8_t value) {
|
void Executor::push(uint8_t value) {
|
||||||
|
@ -23,6 +23,11 @@ namespace M50740 {
|
|||||||
class Executor;
|
class Executor;
|
||||||
using CachingExecutor = CachingExecutor<Executor, 0x1fff, 255, Instruction, false>;
|
using CachingExecutor = CachingExecutor<Executor, 0x1fff, 255, Instruction, false>;
|
||||||
|
|
||||||
|
struct PortHandler {
|
||||||
|
virtual void set_port_output(int port, uint8_t value) = 0;
|
||||||
|
virtual uint8_t get_port_input(int port) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Executes M50740 code subject to heavy limitations:
|
Executes M50740 code subject to heavy limitations:
|
||||||
|
|
||||||
@ -31,7 +36,7 @@ using CachingExecutor = CachingExecutor<Executor, 0x1fff, 255, Instruction, fals
|
|||||||
*/
|
*/
|
||||||
class Executor: public CachingExecutor {
|
class Executor: public CachingExecutor {
|
||||||
public:
|
public:
|
||||||
Executor();
|
Executor(PortHandler &);
|
||||||
void set_rom(const std::vector<uint8_t> &rom);
|
void set_rom(const std::vector<uint8_t> &rom);
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
@ -138,6 +143,7 @@ class Executor: public CachingExecutor {
|
|||||||
template<bool is_brk> inline void perform_interrupt();
|
template<bool is_brk> inline void perform_interrupt();
|
||||||
|
|
||||||
Cycles cycles_;
|
Cycles cycles_;
|
||||||
|
PortHandler &port_handler_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,13 @@
|
|||||||
|
|
||||||
#include "ADB.hpp"
|
#include "ADB.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
using namespace Apple::IIgs::ADB;
|
using namespace Apple::IIgs::ADB;
|
||||||
|
|
||||||
|
GLU::GLU() : executor_(*this) {}
|
||||||
|
|
||||||
// MARK: - Configuration.
|
// MARK: - Configuration.
|
||||||
|
|
||||||
void GLU::set_is_rom03(bool is_rom03) {
|
void GLU::set_is_rom03(bool is_rom03) {
|
||||||
@ -219,3 +222,51 @@ void GLU::set_microcontroller_rom(const std::vector<uint8_t> &rom) {
|
|||||||
void GLU::run_for(Cycles cycles) {
|
void GLU::run_for(Cycles cycles) {
|
||||||
executor_.run_for(cycles);
|
executor_.run_for(cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - M50470 port handler
|
||||||
|
|
||||||
|
void GLU::set_port_output(int port, uint8_t value) {
|
||||||
|
switch(port) {
|
||||||
|
case 0:
|
||||||
|
printf("Set R%d: %02x\n", register_address_, value);
|
||||||
|
registers_[register_address_] = value;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// printf("Keyboard write: %02x???\n", value);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// printf("ADB data line input: %d???\n", value >> 7);
|
||||||
|
// printf("IIe keyboard reset line: %d\n", (value >> 6)&1);
|
||||||
|
// printf("IIgs reset line: %d\n", (value >> 5)&1);
|
||||||
|
// printf("GLU strobe: %d\n", (value >> 4)&1);
|
||||||
|
printf("Select GLU register: %d [%02x]\n", value & 0xf, value);
|
||||||
|
register_address_ = value & 0xf;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// printf("IIe KWS: %d\n", (value >> 6)&3);
|
||||||
|
printf("ADB data line output: %d\n", (value >> 3)&1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t GLU::get_port_input(int port) {
|
||||||
|
switch(port) {
|
||||||
|
case 0:
|
||||||
|
printf("Get R%d\n", register_address_);
|
||||||
|
return registers_[register_address_];
|
||||||
|
case 1:
|
||||||
|
// printf("IIe keyboard read\n");
|
||||||
|
return 0x06;
|
||||||
|
case 2:
|
||||||
|
printf("ADB data line input, etc\n");
|
||||||
|
return 0xff;
|
||||||
|
case 3:
|
||||||
|
// printf("ADB data line output, etc\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
@ -17,8 +17,10 @@ namespace Apple {
|
|||||||
namespace IIgs {
|
namespace IIgs {
|
||||||
namespace ADB {
|
namespace ADB {
|
||||||
|
|
||||||
class GLU {
|
class GLU: public InstructionSet::M50740::PortHandler {
|
||||||
public:
|
public:
|
||||||
|
GLU();
|
||||||
|
|
||||||
// Behaviour varies slightly between the controller shipped with ROM01 machines
|
// Behaviour varies slightly between the controller shipped with ROM01 machines
|
||||||
// and that shipped with ROM03 machines; use this to set the desired behaviour.
|
// and that shipped with ROM03 machines; use this to set the desired behaviour.
|
||||||
void set_is_rom03(bool);
|
void set_is_rom03(bool);
|
||||||
@ -59,6 +61,12 @@ class GLU {
|
|||||||
uint8_t read_microcontroller_address(uint16_t);
|
uint8_t read_microcontroller_address(uint16_t);
|
||||||
|
|
||||||
InstructionSet::M50740::Executor executor_;
|
InstructionSet::M50740::Executor executor_;
|
||||||
|
|
||||||
|
void set_port_output(int port, uint8_t value) override;
|
||||||
|
uint8_t get_port_input(int port) override;
|
||||||
|
|
||||||
|
uint8_t registers_[16];
|
||||||
|
uint8_t register_address_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user