mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +00:00
Merge pull request #987 from TomHarte/IIgsImprovements
Further iterates the IIgs towards full functionality.
This commit is contained in:
commit
2f86dfdf2b
@ -29,7 +29,7 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
|
|||||||
EightMB
|
EightMB
|
||||||
);
|
);
|
||||||
|
|
||||||
Model model = Model::ROM03;
|
Model model = Model::ROM01;
|
||||||
MemoryModel memory_model = MemoryModel::EightMB;
|
MemoryModel memory_model = MemoryModel::EightMB;
|
||||||
|
|
||||||
Target() : Analyser::Static::Target(Machine::AppleIIgs) {
|
Target() : Analyser::Static::Target(Machine::AppleIIgs) {
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef Apple_RealTimeClock_hpp
|
#ifndef Apple_RealTimeClock_hpp
|
||||||
#define Apple_RealTimeClock_hpp
|
#define Apple_RealTimeClock_hpp
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Apple {
|
namespace Apple {
|
||||||
namespace Clock {
|
namespace Clock {
|
||||||
|
|
||||||
@ -21,32 +23,36 @@ namespace Clock {
|
|||||||
*/
|
*/
|
||||||
class ClockStorage {
|
class ClockStorage {
|
||||||
public:
|
public:
|
||||||
ClockStorage() {
|
ClockStorage() {}
|
||||||
// TODO: this should persist, if possible, rather than
|
|
||||||
// being default initialised.
|
|
||||||
constexpr uint8_t default_data[] = {
|
|
||||||
0xa8, 0x00, 0x00, 0x00,
|
|
||||||
0xcc, 0x0a, 0xcc, 0x0a,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x02, 0x63, 0x00,
|
|
||||||
0x03, 0x88, 0x00, 0x4c
|
|
||||||
};
|
|
||||||
memcpy(data_, default_data, sizeof(default_data));
|
|
||||||
memset(&data_[sizeof(default_data)], 0xff, sizeof(data_) - sizeof(default_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Advances the clock by 1 second.
|
Advances the clock by 1 second.
|
||||||
|
|
||||||
The caller should also signal an interrupt.
|
The caller should also signal an interrupt if applicable.
|
||||||
*/
|
*/
|
||||||
void update() {
|
void update() {
|
||||||
for(int c = 0; c < 4; ++c) {
|
for(size_t c = 0; c < 4; ++c) {
|
||||||
++seconds_[c];
|
++seconds_[c];
|
||||||
if(seconds_[c]) break;
|
if(seconds_[c]) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the current [P/B]RAM contents.
|
||||||
|
*/
|
||||||
|
template <typename CollectionT> void set_data(const CollectionT &collection) {
|
||||||
|
set_data(collection.begin(), collection.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IteratorT> void set_data(IteratorT begin, const IteratorT end) {
|
||||||
|
size_t c = 0;
|
||||||
|
while(begin != end && c < 256) {
|
||||||
|
data_[c] = *begin;
|
||||||
|
++begin;
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static constexpr uint16_t NoResult = 0x100;
|
static constexpr uint16_t NoResult = 0x100;
|
||||||
static constexpr uint16_t DidComplete = 0x101;
|
static constexpr uint16_t DidComplete = 0x101;
|
||||||
@ -92,7 +98,7 @@ class ClockStorage {
|
|||||||
case 0x30:
|
case 0x30:
|
||||||
// Either a register access or an extended instruction.
|
// Either a register access or an extended instruction.
|
||||||
if(command & 0x08) {
|
if(command & 0x08) {
|
||||||
address_ = (command & 0x7) << 5;
|
address_ = unsigned((command & 0x7) << 5);
|
||||||
phase_ = (command & 0x80) ? Phase::SecondAddressByteRead : Phase::SecondAddressByteWrite;
|
phase_ = (command & 0x80) ? Phase::SecondAddressByteRead : Phase::SecondAddressByteWrite;
|
||||||
return NoResult;
|
return NoResult;
|
||||||
} else {
|
} else {
|
||||||
@ -162,10 +168,10 @@ class ClockStorage {
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t data_[256];
|
std::array<uint8_t, 256> data_{0xff};
|
||||||
uint8_t seconds_[4];
|
std::array<uint8_t, 4> seconds_{};
|
||||||
uint8_t write_protect_;
|
uint8_t write_protect_ = 0;
|
||||||
int address_;
|
unsigned int address_ = 0;
|
||||||
|
|
||||||
static constexpr int SecondsBuffer = 0x100;
|
static constexpr int SecondsBuffer = 0x100;
|
||||||
static constexpr int RegisterTest = 0x200;
|
static constexpr int RegisterTest = 0x200;
|
||||||
@ -257,7 +263,10 @@ class ParallelClock: public ClockStorage {
|
|||||||
// A no-op for now.
|
// A no-op for now.
|
||||||
} else {
|
} else {
|
||||||
// Write to the RTC. Which in this implementation also sets up a future read.
|
// Write to the RTC. Which in this implementation also sets up a future read.
|
||||||
data_ = uint8_t(perform(data_));
|
const auto result = perform(data_);
|
||||||
|
if(result < 0x100) {
|
||||||
|
data_ = uint8_t(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAGIC! The transaction took 0 seconds.
|
// MAGIC! The transaction took 0 seconds.
|
||||||
|
@ -82,7 +82,7 @@ template <typename Machine> class AuxiliaryMemorySwitches {
|
|||||||
bool read_auxiliary_memory = false;
|
bool read_auxiliary_memory = false;
|
||||||
bool write_auxiliary_memory = false;
|
bool write_auxiliary_memory = false;
|
||||||
|
|
||||||
bool internal_CX_rom = false;
|
bool internal_CX_rom = true;
|
||||||
bool slot_C3_rom = false;
|
bool slot_C3_rom = false;
|
||||||
bool internal_C8_rom = false;
|
bool internal_C8_rom = false;
|
||||||
|
|
||||||
|
@ -38,11 +38,40 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
//
|
||||||
|
// HEAVY WARNING: THIS IS INCOMPLETE AND VERY PROVISIONAL.
|
||||||
|
//
|
||||||
|
// You'll notice lots of random bits of debugging code sitting around but commented out.
|
||||||
|
// Most of this will go when this machine is complete. Please look past the gross ugliness
|
||||||
|
// of this code's intermediate state if you are able.
|
||||||
|
//
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr int CLOCK_RATE = 14'318'180;
|
constexpr int CLOCK_RATE = 14'318'180;
|
||||||
|
|
||||||
class MemManagerChecker {
|
// This is the first result that came up when searching for valid Apple IIgs BRAM states;
|
||||||
|
// I'm unclear on its provenance.
|
||||||
|
constexpr uint8_t default_bram[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x06, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x07, 0x06, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x06, 0x06, 0x00, 0x05, 0x06,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||||
|
0x07, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
||||||
|
0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x96, 0x57, 0x3c,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*class MemManagerChecker {
|
||||||
int handle_total_ = 0;
|
int handle_total_ = 0;
|
||||||
bool dump_bank(const Apple::IIgs::MemoryMap &memory, const char *name, uint32_t address, bool print, uint32_t must_contain = 0xffffffff) {
|
bool dump_bank(const Apple::IIgs::MemoryMap &memory, const char *name, uint32_t address, bool print, uint32_t must_contain = 0xffffffff) {
|
||||||
const auto handles = memory.regions[memory.region_map[0xe117]].read;
|
const auto handles = memory.regions[memory.region_map[0xe117]].read;
|
||||||
@ -149,7 +178,7 @@ class MemManagerChecker {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +216,7 @@ class ConcreteMachine:
|
|||||||
|
|
||||||
set_clock_rate(double(CLOCK_RATE));
|
set_clock_rate(double(CLOCK_RATE));
|
||||||
speaker_.set_input_rate(float(CLOCK_RATE) / float(audio_divider));
|
speaker_.set_input_rate(float(CLOCK_RATE) / float(audio_divider));
|
||||||
|
clock_.ClockStorage::set_data(std::begin(default_bram), std::end(default_bram));
|
||||||
|
|
||||||
using Target = Analyser::Static::AppleIIgs::Target;
|
using Target = Analyser::Static::AppleIIgs::Target;
|
||||||
ROM::Name system;
|
ROM::Name system;
|
||||||
@ -277,6 +307,11 @@ class ConcreteMachine:
|
|||||||
// std::srand(23);
|
// std::srand(23);
|
||||||
Memory::Fuzz(ram_);
|
Memory::Fuzz(ram_);
|
||||||
|
|
||||||
|
// Prior to ROM03 there's no power-on bit.
|
||||||
|
if(target.model != Target::Model::ROM03) {
|
||||||
|
speed_register_ &= ~0x40;
|
||||||
|
}
|
||||||
|
|
||||||
// Sync up initial values.
|
// Sync up initial values.
|
||||||
memory_.set_speed_register(speed_register_ ^ 0x80);
|
memory_.set_speed_register(speed_register_ ^ 0x80);
|
||||||
|
|
||||||
@ -348,6 +383,23 @@ class ConcreteMachine:
|
|||||||
static bool log = false;
|
static bool log = false;
|
||||||
bool is_1Mhz = false;
|
bool is_1Mhz = false;
|
||||||
|
|
||||||
|
// if(operation == CPU::WDC65816::BusOperation::ReadOpcode) {
|
||||||
|
// if(address == 0xfe00d5) {
|
||||||
|
// printf("");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// printf("%06x a:%04x x:%04x y:%04x s:%04x d:%04x b:%04x\n",
|
||||||
|
// address,
|
||||||
|
// m65816_.get_value_of_register(CPU::WDC65816::Register::A),
|
||||||
|
// m65816_.get_value_of_register(CPU::WDC65816::Register::X),
|
||||||
|
// m65816_.get_value_of_register(CPU::WDC65816::Register::Y),
|
||||||
|
//// m65816_.get_value_of_register(CPU::WDC65816::Register::Flags),
|
||||||
|
// m65816_.get_value_of_register(CPU::WDC65816::Register::StackPointer),
|
||||||
|
// m65816_.get_value_of_register(CPU::WDC65816::Register::Direct),
|
||||||
|
// m65816_.get_value_of_register(CPU::WDC65816::Register::DataBank)
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
if(operation == CPU::WDC65816::BusOperation::ReadVector && !(memory_.get_shadow_register()&0x40)) {
|
if(operation == CPU::WDC65816::BusOperation::ReadVector && !(memory_.get_shadow_register()&0x40)) {
|
||||||
// I think vector pulls always go to ROM?
|
// I think vector pulls always go to ROM?
|
||||||
// That's slightly implied in the documentation, and doing so makes GS/OS boot, so...
|
// That's slightly implied in the documentation, and doing so makes GS/OS boot, so...
|
||||||
@ -936,9 +988,9 @@ class ConcreteMachine:
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if(operation == CPU::WDC65816::BusOperation::ReadOpcode) {
|
if(operation == CPU::WDC65816::BusOperation::ReadOpcode) {
|
||||||
if(total > 482342960 && total < 482352960 && address == 0xe10000) {
|
// if(total > 482342960 && total < 482352960 && address == 0xe10000) {
|
||||||
printf("entry: %llu\n", static_cast<unsigned long long>(total));
|
// printf("entry: %llu\n", static_cast<unsigned long long>(total));
|
||||||
}
|
// }
|
||||||
|
|
||||||
// log |= address == 0xfc144f;
|
// log |= address == 0xfc144f;
|
||||||
// log &= !((address < 0xfc144f) || (address >= 0xfc1490));
|
// log &= !((address < 0xfc144f) || (address >= 0xfc1490));
|
||||||
@ -1147,3 +1199,4 @@ Machine *Machine::AppleIIgs(const Analyser::Static::Target *target, const ROMMac
|
|||||||
}
|
}
|
||||||
|
|
||||||
Machine::~Machine() {}
|
Machine::~Machine() {}
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ class MemoryMap {
|
|||||||
friend AuxiliaryMemorySwitches;
|
friend AuxiliaryMemorySwitches;
|
||||||
friend LanguageCardSwitches;
|
friend LanguageCardSwitches;
|
||||||
|
|
||||||
uint8_t shadow_register_ = 0x08;
|
uint8_t shadow_register_ = 0x00;
|
||||||
uint8_t speed_register_ = 0x00;
|
uint8_t speed_register_ = 0x00;
|
||||||
|
|
||||||
// MARK: - Memory banking.
|
// MARK: - Memory banking.
|
||||||
|
@ -49,6 +49,15 @@ namespace {
|
|||||||
|
|
||||||
constexpr int CLOCK_RATE = 7833600;
|
constexpr int CLOCK_RATE = 7833600;
|
||||||
|
|
||||||
|
|
||||||
|
// Former default PRAM:
|
||||||
|
//
|
||||||
|
// 0xa8, 0x00, 0x00, 0x00,
|
||||||
|
// 0xcc, 0x0a, 0xcc, 0x0a,
|
||||||
|
// 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// 0x00, 0x02, 0x63, 0x00,
|
||||||
|
// 0x03, 0x88, 0x00, 0x4c
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Apple {
|
namespace Apple {
|
||||||
|
Loading…
Reference in New Issue
Block a user