1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-08 10:52:58 +00:00

Implements the Enhanced IIe, other than some text selection errors.

This commit is contained in:
Thomas Harte 2018-08-11 10:26:30 -04:00
parent 4b91910fab
commit a13eb351da
7 changed files with 53 additions and 38 deletions

View File

@ -19,7 +19,8 @@ struct Target: public ::Analyser::Static::Target {
enum class Model {
II,
IIplus,
IIe
IIe,
EnhancedIIe
};
enum class DiskController {
None,

View File

@ -34,7 +34,9 @@
namespace {
template <bool is_iie> class ConcreteMachine:
#define is_iie() ((model == Analyser::Static::AppleII::Target::Model::IIe) || (model == Analyser::Static::AppleII::Target::Model::EnhancedIIe))
template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
public CRTMachine::Machine,
public MediaTarget::Machine,
public KeyboardMachine::Machine,
@ -62,7 +64,7 @@ template <bool is_iie> class ConcreteMachine:
CPU::MOS6502::Processor<ConcreteMachine, false> m6502_;
VideoBusHandler video_bus_handler_;
std::unique_ptr<AppleII::Video::Video<VideoBusHandler, is_iie>> video_;
std::unique_ptr<AppleII::Video::Video<VideoBusHandler, is_iie()>> video_;
int cycles_into_current_line_ = 0;
Cycles cycles_since_video_update_;
@ -179,7 +181,7 @@ template <bool is_iie> class ConcreteMachine:
bool has_language_card_ = true;
void set_language_card_paging() {
uint8_t *const ram = alternative_zero_page_ ? aux_ram_ : ram_;
uint8_t *const rom = is_iie ? &rom_[3840] : rom_.data();
uint8_t *const rom = is_iie() ? &rom_[3840] : rom_.data();
page(0xd0, 0xe0,
language_card_.read ? &ram[language_card_.bank1 ? 0xd000 : 0xc000] : rom,
@ -298,7 +300,7 @@ template <bool is_iie> class ConcreteMachine:
public:
ConcreteMachine(const Analyser::Static::AppleII::Target &target, const ROMMachine::ROMFetcher &rom_fetcher):
m6502_(CPU::MOS6502::Personality::P6502, *this),
m6502_((model == Analyser::Static::AppleII::Target::Model::EnhancedIIe) ? CPU::MOS6502::Personality::P65C02 : CPU::MOS6502::Personality::P6502, *this),
video_bus_handler_(ram_, aux_ram_),
audio_toggle_(audio_queue_),
speaker_(audio_toggle_) {
@ -345,6 +347,11 @@ template <bool is_iie> class ConcreteMachine:
rom_names.push_back("apple2eu-character.rom");
rom_names.push_back("apple2eu.rom");
break;
case Target::Model::EnhancedIIe:
rom_size += 3840;
rom_names.push_back("apple2e-character.rom");
rom_names.push_back("apple2e.rom");
break;
}
const auto roms = rom_fetcher("AppleII", rom_names);
@ -383,7 +390,7 @@ template <bool is_iie> class ConcreteMachine:
}
void setup_output(float aspect_ratio) override {
video_.reset(new AppleII::Video::Video<VideoBusHandler, is_iie>(video_bus_handler_));
video_.reset(new AppleII::Video::Video<VideoBusHandler, is_iie()>(video_bus_handler_));
video_->set_character_rom(character_rom_);
}
@ -422,7 +429,7 @@ template <bool is_iie> class ConcreteMachine:
if(isReadOperation(operation)) *value = read_pages_[address >> 8][address & 0xff];
else if(write_pages_[address >> 8]) write_pages_[address >> 8][address & 0xff] = *value;
if(is_iie && address >= 0xc300 && address < 0xd000) {
if(is_iie() && address >= 0xc300 && address < 0xd000) {
bool internal_c8_rom = internal_c8_rom_;
internal_c8_rom |= ((address >> 8) == 0xc3) && !slot_C3_rom_;
internal_c8_rom &= (address != 0xcfff);
@ -468,7 +475,7 @@ template <bool is_iie> class ConcreteMachine:
*value &= 0x7f;
if(
static_cast<Joystick *>(joysticks_[0].get())->buttons[0] || static_cast<Joystick *>(joysticks_[1].get())->buttons[2] ||
(is_iie && open_apple_is_pressed_)
(is_iie() && open_apple_is_pressed_)
)
*value |= 0x80;
break;
@ -476,7 +483,7 @@ template <bool is_iie> class ConcreteMachine:
*value &= 0x7f;
if(
static_cast<Joystick *>(joysticks_[0].get())->buttons[1] || static_cast<Joystick *>(joysticks_[1].get())->buttons[1] ||
(is_iie && closed_apple_is_pressed_)
(is_iie() && closed_apple_is_pressed_)
)
*value |= 0x80;
break;
@ -498,26 +505,26 @@ template <bool is_iie> class ConcreteMachine:
} break;
// The IIe-only state reads follow...
case 0xc011: if(is_iie) *value = (*value & 0x7f) | (language_card_.bank1 ? 0x80 : 0x00); break;
case 0xc012: if(is_iie) *value = (*value & 0x7f) | (language_card_.read ? 0x80 : 0x00); break;
case 0xc013: if(is_iie) *value = (*value & 0x7f) | (read_auxiliary_memory_ ? 0x80 : 0x00); break;
case 0xc014: if(is_iie) *value = (*value & 0x7f) | (write_auxiliary_memory_ ? 0x80 : 0x00); break;
case 0xc015: if(is_iie) *value = (*value & 0x7f) | (internal_CX_rom_ ? 0x80 : 0x00); break;
case 0xc016: if(is_iie) *value = (*value & 0x7f) | (alternative_zero_page_ ? 0x80 : 0x00); break;
case 0xc017: if(is_iie) *value = (*value & 0x7f) | (slot_C3_rom_ ? 0x80 : 0x00); break;
case 0xc018: if(is_iie) *value = (*value & 0x7f) | (video_->get_80_store() ? 0x80 : 0x00); break;
case 0xc019: if(is_iie) *value = (*value & 0x7f) | (video_->get_is_vertical_blank(cycles_since_video_update_) ? 0x00 : 0x80); break;
case 0xc01a: if(is_iie) *value = (*value & 0x7f) | (video_->get_text() ? 0x80 : 0x00); break;
case 0xc01b: if(is_iie) *value = (*value & 0x7f) | (video_->get_mixed() ? 0x80 : 0x00); break;
case 0xc01c: if(is_iie) *value = (*value & 0x7f) | (video_->get_page2() ? 0x80 : 0x00); break;
case 0xc01d: if(is_iie) *value = (*value & 0x7f) | (video_->get_high_resolution() ? 0x80 : 0x00); break;
case 0xc01e: if(is_iie) *value = (*value & 0x7f) | (video_->get_alternative_character_set() ? 0x80 : 0x00); break;
case 0xc01f: if(is_iie) *value = (*value & 0x7f) | (video_->get_80_columns() ? 0x80 : 0x00); break;
case 0xc07f: if(is_iie) *value = (*value & 0x7f) | (video_->get_double_high_resolution() ? 0x80 : 0x00); break;
case 0xc011: if(is_iie()) *value = (*value & 0x7f) | (language_card_.bank1 ? 0x80 : 0x00); break;
case 0xc012: if(is_iie()) *value = (*value & 0x7f) | (language_card_.read ? 0x80 : 0x00); break;
case 0xc013: if(is_iie()) *value = (*value & 0x7f) | (read_auxiliary_memory_ ? 0x80 : 0x00); break;
case 0xc014: if(is_iie()) *value = (*value & 0x7f) | (write_auxiliary_memory_ ? 0x80 : 0x00); break;
case 0xc015: if(is_iie()) *value = (*value & 0x7f) | (internal_CX_rom_ ? 0x80 : 0x00); break;
case 0xc016: if(is_iie()) *value = (*value & 0x7f) | (alternative_zero_page_ ? 0x80 : 0x00); break;
case 0xc017: if(is_iie()) *value = (*value & 0x7f) | (slot_C3_rom_ ? 0x80 : 0x00); break;
case 0xc018: if(is_iie()) *value = (*value & 0x7f) | (video_->get_80_store() ? 0x80 : 0x00); break;
case 0xc019: if(is_iie()) *value = (*value & 0x7f) | (video_->get_is_vertical_blank(cycles_since_video_update_) ? 0x00 : 0x80); break;
case 0xc01a: if(is_iie()) *value = (*value & 0x7f) | (video_->get_text() ? 0x80 : 0x00); break;
case 0xc01b: if(is_iie()) *value = (*value & 0x7f) | (video_->get_mixed() ? 0x80 : 0x00); break;
case 0xc01c: if(is_iie()) *value = (*value & 0x7f) | (video_->get_page2() ? 0x80 : 0x00); break;
case 0xc01d: if(is_iie()) *value = (*value & 0x7f) | (video_->get_high_resolution() ? 0x80 : 0x00); break;
case 0xc01e: if(is_iie()) *value = (*value & 0x7f) | (video_->get_alternative_character_set() ? 0x80 : 0x00); break;
case 0xc01f: if(is_iie()) *value = (*value & 0x7f) | (video_->get_80_columns() ? 0x80 : 0x00); break;
case 0xc07f: if(is_iie()) *value = (*value & 0x7f) | (video_->get_double_high_resolution() ? 0x80 : 0x00); break;
}
} else {
// Write-only switches. All IIe as currently implemented.
if(is_iie) {
if(is_iie()) {
switch(address) {
default: printf("Write %04x?\n", address); break;
@ -612,7 +619,7 @@ template <bool is_iie> class ConcreteMachine:
case 0xc05e:
case 0xc05f:
if(is_iie) {
if(is_iie()) {
update_video();
video_->set_double_high_resolution(!(address&1));
}
@ -626,7 +633,7 @@ template <bool is_iie> class ConcreteMachine:
}
// On the IIe, reading C010 returns additional key info.
if(is_iie && isReadOperation(operation)) {
if(is_iie() && isReadOperation(operation)) {
*value = (key_is_down_ ? 0x80 : 0x00) | (keyboard_input_ & 0x7f);
}
break;
@ -769,7 +776,7 @@ template <bool is_iie> class ConcreteMachine:
}
// Prior to the IIe, the keyboard could produce uppercase only.
if(!is_iie) value = static_cast<char>(toupper(value));
if(!is_iie()) value = static_cast<char>(toupper(value));
if(is_pressed) {
keyboard_input_ = static_cast<uint8_t>(value | 0x80);
@ -818,10 +825,12 @@ using namespace AppleII;
Machine *Machine::AppleII(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
using Target = Analyser::Static::AppleII::Target;
const Target *const appleii_target = dynamic_cast<const Target *>(target);
if(appleii_target->model == Target::Model::IIe) {
return new ConcreteMachine<true>(*appleii_target, rom_fetcher);
} else {
return new ConcreteMachine<false>(*appleii_target, rom_fetcher);
switch(appleii_target->model) {
default: return nullptr;
case Target::Model::II: return new ConcreteMachine<Target::Model::II>(*appleii_target, rom_fetcher);
case Target::Model::IIplus: return new ConcreteMachine<Target::Model::IIplus>(*appleii_target, rom_fetcher);
case Target::Model::IIe: return new ConcreteMachine<Target::Model::IIe>(*appleii_target, rom_fetcher);
case Target::Model::EnhancedIIe: return new ConcreteMachine<Target::Model::EnhancedIIe>(*appleii_target, rom_fetcher);
}
}

View File

@ -13,7 +13,8 @@
typedef NS_ENUM(NSInteger, CSMachineAppleIIModel) {
CSMachineAppleIIModelAppleII,
CSMachineAppleIIModelAppleIIPlus,
CSMachineAppleIIModelAppleIIe
CSMachineAppleIIModelAppleIIe,
CSMachineAppleIIModelAppleEnhancedIIe
};
typedef NS_ENUM(NSInteger, CSMachineAppleIIDiskController) {

View File

@ -169,9 +169,10 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::AppleII;
switch(model) {
default: target->model = Target::Model::II; break;
case CSMachineAppleIIModelAppleIIPlus: target->model = Target::Model::IIplus; break;
case CSMachineAppleIIModelAppleIIe: target->model = Target::Model::IIe; break;
default: target->model = Target::Model::II; break;
case CSMachineAppleIIModelAppleIIPlus: target->model = Target::Model::IIplus; break;
case CSMachineAppleIIModelAppleIIe: target->model = Target::Model::IIe; break;
case CSMachineAppleIIModelAppleEnhancedIIe: target->model = Target::Model::EnhancedIIe; break;
}
switch(diskController) {
default:

View File

@ -84,7 +84,7 @@ Gw
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="jli-ac-Sij">
<rect key="frame" x="65" y="67" width="91" height="26"/>
<rect key="frame" x="65" y="67" width="115" height="26"/>
<popUpButtonCell key="cell" type="push" title="Apple II" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="VBQ-JG-AeM" id="U6V-us-O2F">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -93,6 +93,7 @@ Gw
<menuItem title="Apple II" state="on" id="VBQ-JG-AeM"/>
<menuItem title="Apple II+" tag="1" id="Yme-Wn-Obh"/>
<menuItem title="Apple IIe" tag="2" id="AMt-WU-a0H"/>
<menuItem title="Enhanced IIe" tag="3" id="kUz-FG-lqW"/>
</items>
</menu>
</popUpButtonCell>

View File

@ -131,6 +131,7 @@ class MachinePicker: NSObject {
switch appleIIModelButton!.selectedTag() {
case 1: model = .appleIIPlus
case 2: model = .appleIIe
case 3: model = .appleEnhancedIIe
case 0: fallthrough
default: model = .appleII
}

View File

@ -9,5 +9,6 @@ apple2eu.rom — as per apple2e.rom, but for the Unenhanced Apple II.
apple2-character.rom — a 2kb image of the Apple IIe's character ROM.
apple2eu-character.rom — a 4kb image of the Unenhanced IIe's character ROM.
apple2e-character.rom — a 4kb image of the Enhanced IIe's character ROM.
Apologies for the wackiness around "at least xkb big", it's to allow for use of files such as those on ftp.apple.asimov.net, which tend to be a bunch of other things, then the system ROM.