1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +00:00

Expands towards supporting multiple Macintosh models.

To provide another variable to help with bug isolation.
This commit is contained in:
Thomas Harte 2019-06-03 14:50:36 -04:00
parent 881feb1bd3
commit 85298319fa
7 changed files with 123 additions and 19 deletions

View File

@ -7,6 +7,7 @@
//
#include "StaticAnalyser.hpp"
#include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) {
// This analyser can comprehend disks only.
@ -15,7 +16,7 @@ Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(const Media
// If there is at least one disk, wave it through.
Analyser::Static::TargetList targets;
using Target = Analyser::Static::Target;
using Target = Analyser::Static::Macintosh::Target;
auto *target = new Target;
target->machine = Analyser::Machine::Macintosh;
target->media = media;

View File

@ -0,0 +1,31 @@
//
// Target.hpp
// Clock Signal
//
// Created by Thomas Harte on 03/06/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Macintosh_Target_h
#define Analyser_Static_Macintosh_Target_h
namespace Analyser {
namespace Static {
namespace Macintosh {
struct Target: public ::Analyser::Static::Target {
enum class Model {
Mac128k,
Mac512k,
Mac512ke,
MacPlus
};
Model model = Model::Mac128k;
};
}
}
}
#endif /* Analyser_Static_Macintosh_Target_h */

View File

@ -24,6 +24,8 @@
#include "../../../Components/DiskII/IWM.hpp"
#include "../../../Processors/68000/68000.hpp"
#include "../../../Analyser/Static/Macintosh/Target.hpp"
#include "../../Utility/MemoryPacker.hpp"
namespace {
@ -35,7 +37,7 @@ const int CLOCK_RATE = 7833600;
namespace Apple {
namespace Macintosh {
class ConcreteMachine:
template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachine:
public Machine,
public CRTMachine::Machine,
public CPU::MC68000::BusHandler {
@ -43,17 +45,45 @@ class ConcreteMachine:
ConcreteMachine(const ROMMachine::ROMFetcher &rom_fetcher) :
mc68000_(*this),
iwm_(CLOCK_RATE),
video_(ram_.data(), audio_, drive_speed_accumulator_),
video_(ram_, audio_, drive_speed_accumulator_),
via_(via_port_handler_),
via_port_handler_(*this, clock_, keyboard_, video_, audio_, iwm_) {
// Select a ROM name and determine the proper ROM and RAM sizes
// based on the machine model.
using Model = Analyser::Static::Macintosh::Target::Model;
std::string rom_name;
uint32_t ram_size, rom_size;
switch(model) {
default:
case Model::Mac128k:
ram_size = 128*1024;
rom_size = 64*1024;
rom_name = "mac128k.rom";
break;
case Model::Mac512k:
ram_size = 512*1024;
rom_size = 64*1024;
rom_name = "mac512k.rom";
break;
case Model::Mac512ke:
case Model::MacPlus:
ram_size = 512*1024;
rom_size = 128*1024;
rom_name = "macplus.rom";
break;
}
ram_mask_ = (ram_size >> 1) - 1;
rom_mask_ = (rom_size >> 1) - 1;
video_.set_ram_mask(ram_mask_);
// Grab a copy of the ROM and convert it into big-endian data.
const auto roms = rom_fetcher("Macintosh", { "mac128k.rom" });
const auto roms = rom_fetcher("Macintosh", { rom_name });
if(!roms[0]) {
throw ROMMachine::Error::MissingROMs;
}
roms[0]->resize(64*1024);
Memory::PackBigEndian16(*roms[0], rom_.data());
roms[0]->resize(rom_size);
Memory::PackBigEndian16(*roms[0], rom_);
// The Mac runs at 7.8336mHz.
set_clock_rate(double(CLOCK_RATE));
@ -125,7 +155,6 @@ class ConcreteMachine:
if(word_address >= 0x400000) {
if(cycle.data_select_active()) {
const int register_address = word_address >> 8;
switch(word_address & 0x78f000) {
@ -151,11 +180,32 @@ class ConcreteMachine:
}
break;
case 0x780000:
// Phase read.
if(cycle.operation & Microcycle::Read) {
cycle.value->halves.low = phase_ & 7;
if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
}
break;
case 0x480000: case 0x48f000:
case 0x500000: case 0x580000: case 0x58f000:
// Any word access here adjusts phase.
if(cycle.operation & Microcycle::SelectWord) {
++phase_;
} else {
// TODO: SCC access.
printf("SCC access %06x\n", *cycle.address & 0xffffff);
}
break;
default:
if(cycle.operation & Microcycle::Read) {
// printf("Unrecognised read %06x\n", *cycle.address & 0xffffff);
printf("Unrecognised read %06x\n", *cycle.address & 0xffffff);
cycle.value->halves.low = 0x00;
if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
} else {
printf("Unrecognised write %06x\n", *cycle.address & 0xffffff);
}
break;
}
@ -173,11 +223,11 @@ class ConcreteMachine:
(ROM_is_overlay_ && word_address >= 0x300000) ||
(!ROM_is_overlay_ && word_address < 0x200000)
) {
memory_base = ram_.data();
word_address %= ram_.size();
memory_base = ram_;
word_address &= ram_mask_;
} else {
memory_base = rom_.data();
word_address %= rom_.size();
memory_base = rom_;
word_address &= rom_mask_;
// Disallow writes to ROM; also it doesn't mirror above 0x60000, ever.
if(!(operation & Microcycle::Read) || word_address >= 0x300000) operation = 0;
@ -363,9 +413,6 @@ class ConcreteMachine:
IWM &iwm_;
};
std::array<uint16_t, 32*1024> rom_;
std::array<uint16_t, 64*1024> ram_;
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
DriveSpeedAccumulator drive_speed_accumulator_;
@ -388,6 +435,12 @@ class ConcreteMachine:
HalfCycles time_since_iwm_update_;
bool ROM_is_overlay_ = true;
int phase_ = 1;
uint32_t ram_mask_ = 0;
uint32_t rom_mask_ = 0;
uint16_t rom_[64*1024];
uint16_t ram_[256*1024];
};
}
@ -396,7 +449,16 @@ class ConcreteMachine:
using namespace Apple::Macintosh;
Machine *Machine::Macintosh(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
return new ConcreteMachine(rom_fetcher);
auto *const mac_target = dynamic_cast<const Analyser::Static::Macintosh::Target *>(target);
using Model = Analyser::Static::Macintosh::Target::Model;
switch(mac_target->model) {
default:
case Model::Mac128k: return new ConcreteMachine<Model::Mac128k>(rom_fetcher);
case Model::Mac512k: return new ConcreteMachine<Model::Mac512k>(rom_fetcher);
case Model::Mac512ke: return new ConcreteMachine<Model::Mac512ke>(rom_fetcher);
case Model::MacPlus: return new ConcreteMachine<Model::MacPlus>(rom_fetcher);
}
}
Machine::~Machine() {}

View File

@ -150,13 +150,13 @@ void Video::run_for(HalfCycles duration) {
/*
Video: $1A700 and the alternate buffer starts at $12700; for a 512K Macintosh, add $60000 to these numbers.
*/
video_address_ = use_alternate_screen_buffer_ ? (0x12700 >> 1) : (0x1a700 >> 1);
video_address_ = (use_alternate_screen_buffer_ ? (0xffff2700 >> 1) : (0xffffa700 >> 1)) & ram_mask_;
/*
"The main sound buffer is at $1FD00 in a 128K Macintosh, and the alternate buffer is at $1A100;
for a 512K Macintosh, add $60000 to these values."
*/
audio_address_ = use_alternate_audio_buffer_ ? (0x1a100 >> 1) : (0x1fd00 >> 1);
audio_address_ = (use_alternate_audio_buffer_ ? (0xffffa100 >> 1) : (0xfffffd00 >> 1)) & ram_mask_;
}
}
}
@ -176,3 +176,7 @@ void Video::set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use
use_alternate_screen_buffer_ = use_alternate_screen_buffer;
use_alternate_audio_buffer_ = use_alternate_audio_buffer;
}
void Video::set_ram_mask(uint32_t mask) {
ram_mask_ = mask;
}

View File

@ -29,12 +29,15 @@ class Video {
bool vsync();
bool is_outputting();
void set_ram_mask(uint32_t);
private:
DeferredAudio &audio_;
DriveSpeedAccumulator &drive_speed_accumulator_;
Outputs::CRT::CRT crt_;
uint16_t *ram_ = nullptr;
uint32_t ram_mask_ = 0;
HalfCycles frame_position_;

View File

@ -712,6 +712,7 @@
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = "<group>"; };
4B047075201ABC180047AB0D /* Cartridge.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Cartridge.hpp; sourceTree = "<group>"; };
4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = "<group>"; };
4B04B65622A58CB40006AB58 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4B05401D219D1618001BF69C /* ScanTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ScanTarget.cpp; path = ../../Outputs/ScanTarget.cpp; sourceTree = "<group>"; };
4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Clock Signal Kiosk"; sourceTree = BUILT_PRODUCTS_DIR; };
4B055A771FAE78210060FFFF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../Library/Frameworks/SDL2.framework; sourceTree = SOURCE_ROOT; };
@ -2791,6 +2792,7 @@
children = (
4BB4BFB722A4372E0069048D /* StaticAnalyser.hpp */,
4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */,
4B04B65622A58CB40006AB58 /* Target.hpp */,
);
path = Macintosh;
sourceTree = "<group>";

View File

@ -17,6 +17,7 @@
#include "../../../../../Analyser/Static/AmstradCPC/Target.hpp"
#include "../../../../../Analyser/Static/AppleII/Target.hpp"
#include "../../../../../Analyser/Static/Commodore/Target.hpp"
#include "../../../../../Analyser/Static/Macintosh/Target.hpp"
#include "../../../../../Analyser/Static/MSX/Target.hpp"
#include "../../../../../Analyser/Static/Oric/Target.hpp"
#include "../../../../../Analyser/Static/ZX8081/Target.hpp"
@ -193,7 +194,7 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K
- (instancetype)initWithMacintoshModel:(CSMachineMacintoshModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::Target;
using Target = Analyser::Static::Macintosh::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::Macintosh;
_targets.push_back(std::move(target));