1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +00:00

Attempts to bring card support to the Apple II, and adds a 'has disk' flag.

This commit is contained in:
Thomas Harte 2018-04-23 21:14:45 -07:00
parent e92e06a5f4
commit 7463edaa1b
6 changed files with 83 additions and 4 deletions

View File

@ -14,6 +14,8 @@ Analyser::Static::TargetList Analyser::Static::AppleII::GetTargets(const Media &
target->machine = Machine::AppleII;
target->media = media;
target->has_disk = !target->media.disks.empty();
TargetList targets;
targets.push_back(std::move(target));
return targets;

View File

@ -16,7 +16,7 @@ namespace Static {
namespace AppleII {
struct Target: public ::Analyser::Static::Target {
bool has_disk_; // TODO: Disk II versus IWM?
bool has_disk; // TODO: Disk II versus IWM?
};
}

View File

@ -18,8 +18,11 @@
#include "../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
#include "Card.hpp"
#include "Video.hpp"
#include "../../Analyser/Static/AppleII/Target.hpp"
#include <memory>
namespace {
@ -57,6 +60,16 @@ class ConcreteMachine:
void update_audio() {
speaker_.run_for(audio_queue_, cycles_since_audio_update_.divide(Cycles(audio_divider)));
}
void update_cards() {
cycles_since_card_update_ += stretched_cycles_since_card_update_ / 7;
stretched_cycles_since_card_update_ %= 7;
for(int c = 0; c < 7; ++c) {
if(cards_[c])
cards_[c]->run_for(cycles_since_card_update_, stretched_cycles_since_card_update_);
}
cycles_since_card_update_ = 0;
stretched_cycles_since_card_update_ = 0;
}
uint8_t ram_[48*1024];
std::vector<uint8_t> rom_;
@ -69,6 +82,11 @@ class ConcreteMachine:
Outputs::Speaker::LowpassSpeaker<Audio::Toggle> speaker_;
Cycles cycles_since_audio_update_;
ROMMachine::ROMFetcher rom_fetcher_;
AppleII::Card *cards_[7] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
Cycles cycles_since_card_update_;
int stretched_cycles_since_card_update_ = 0;
public:
ConcreteMachine():
m6502_(*this),
@ -110,6 +128,7 @@ class ConcreteMachine:
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
++ cycles_since_video_update_;
++ cycles_since_card_update_;
cycles_since_audio_update_ += Cycles(7);
switch(address) {
@ -123,7 +142,6 @@ class ConcreteMachine:
switch(address) {
default:
// printf("Unknown access to %04x\n", address);
*value = 0xff;
break;
case 0xc000:
*value = keyboard_input_;
@ -160,6 +178,28 @@ class ConcreteMachine:
break;
}
if(address >= 0xc100 && address < 0xc800) {
/*
Decode the area conventionally used by cards for ROMs:
0xCn00 0xCnff: card n.
*/
const int card_number = (address - 0xc100) >> 8;
if(cards_[card_number]) {
update_cards();
cards_[card_number]->perform_bus_operation(operation, address & 0xff, value);
}
} else if(address >= 0xc090 && address < 0xc100) {
/*
Decode the area conventionally used by cards for registers:
C0n0--C0nF: card n - 8.
*/
const int card_number = (address - 0xc080) >> 4;
if(cards_[card_number]) {
update_cards();
cards_[card_number]->perform_bus_operation(operation, address, value);
}
}
// The Apple II has a slightly weird timing pattern: every 65th CPU cycle is stretched
// by an extra 1/7th. That's because one cycle lasts 3.5 NTSC colour clocks, so after
// 65 cycles a full line of 227.5 colour clocks have passed. But the high-rate binary
@ -169,6 +209,7 @@ class ConcreteMachine:
cycles_into_current_line_ = (cycles_into_current_line_ + 1) % 65;
if(!cycles_into_current_line_) {
++ cycles_since_audio_update_;
++ stretched_cycles_since_card_update_;
}
return Cycles(1);
@ -180,7 +221,7 @@ class ConcreteMachine:
audio_queue_.perform();
}
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
bool set_rom_fetcher(const ROMMachine::ROMFetcher &roms_with_names) override {
auto roms = roms_with_names(
"AppleII",
{
@ -194,6 +235,8 @@ class ConcreteMachine:
character_rom_ = std::move(*roms[1]);
rom_fetcher_ = roms_with_names;
return true;
}
@ -223,6 +266,10 @@ class ConcreteMachine:
// MARK: ConfigurationTarget
void configure_as_target(const Analyser::Static::Target *target) override {
auto *const apple_target = dynamic_cast<const Analyser::Static::AppleII::Target *>(target);
if(apple_target->has_disk) {
// ... add Disk II
}
}
bool insert_media(const Analyser::Static::Media &media) override {

27
Machines/AppleII/Card.hpp Normal file
View File

@ -0,0 +1,27 @@
//
// Card.h
// Clock Signal
//
// Created by Thomas Harte on 23/04/2018.
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Card_h
#define Card_h
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace AppleII {
class Card {
public:
/*! Advances time by @c cycles, of which @c stretches were stretched. */
virtual void run_for(Cycles half_cycles, int stretches) {}
/*! Performs a bus operation; the card is implicitly selected. */
virtual void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) = 0;
};
}
#endif /* Card_h */

View File

@ -1332,6 +1332,7 @@
4BBFBB6A1EE8401E00C01E7A /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZX8081.cpp; path = Parsers/ZX8081.cpp; sourceTree = "<group>"; };
4BBFBB6B1EE8401E00C01E7A /* ZX8081.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ZX8081.hpp; path = Parsers/ZX8081.hpp; sourceTree = "<group>"; };
4BBFFEE51F7B27F1005F3FEB /* TrackSerialiser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TrackSerialiser.cpp; sourceTree = "<group>"; };
4BC39565208EDFCE0044766B /* Card.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Card.hpp; sourceTree = "<group>"; };
4BC3B74D1CD194CC00F86E85 /* Shader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Shader.cpp; sourceTree = "<group>"; };
4BC3B74E1CD194CC00F86E85 /* Shader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Shader.hpp; sourceTree = "<group>"; };
4BC3B7501CD1956900F86E85 /* OutputShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OutputShader.cpp; sourceTree = "<group>"; };
@ -1555,6 +1556,7 @@
4B15AA0A2082C799005E6C8D /* Video.cpp */,
4B15AA092082C799005E6C8D /* AppleII.hpp */,
4B15AA0B2082C799005E6C8D /* Video.hpp */,
4BC39565208EDFCE0044766B /* Card.hpp */,
);
path = AppleII;
sourceTree = "<group>";

View File

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