mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Adds reading of vertical blank and implements the full IIe keyboard logic.
i.e. there are now two Apple keys, and shift isn't assumed.
This commit is contained in:
parent
3aeb4213fe
commit
086596c28e
@ -292,6 +292,10 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
return static_cast<Joystick *>(joysticks_[channel >> 1].get())->axes[channel & 1] < analogue_charge_ + analogue_biases_[channel];
|
return static_cast<Joystick *>(joysticks_[channel >> 1].get())->axes[channel & 1] < analogue_charge_ + analogue_biases_[channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The IIe has three keys that are wired directly to the same input as the joystick buttons.
|
||||||
|
bool open_apple_is_pressed_ = false;
|
||||||
|
bool closed_apple_is_pressed_ = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConcreteMachine(const Analyser::Static::AppleII::Target &target, const ROMMachine::ROMFetcher &rom_fetcher):
|
ConcreteMachine(const Analyser::Static::AppleII::Target &target, const ROMMachine::ROMFetcher &rom_fetcher):
|
||||||
m6502_(*this),
|
m6502_(*this),
|
||||||
@ -450,9 +454,7 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
// Read-only switches.
|
// Read-only switches.
|
||||||
switch(address) {
|
switch(address) {
|
||||||
default:
|
default: break;
|
||||||
// printf("Unknown (?) read from %04x\n", address);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc000:
|
case 0xc000:
|
||||||
if(string_serialiser_) {
|
if(string_serialiser_) {
|
||||||
@ -464,12 +466,18 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
|
|
||||||
case 0xc061: // Switch input 0.
|
case 0xc061: // Switch input 0.
|
||||||
*value &= 0x7f;
|
*value &= 0x7f;
|
||||||
if(static_cast<Joystick *>(joysticks_[0].get())->buttons[0] || static_cast<Joystick *>(joysticks_[1].get())->buttons[2])
|
if(
|
||||||
|
static_cast<Joystick *>(joysticks_[0].get())->buttons[0] || static_cast<Joystick *>(joysticks_[1].get())->buttons[2] ||
|
||||||
|
(is_iie && open_apple_is_pressed_)
|
||||||
|
)
|
||||||
*value |= 0x80;
|
*value |= 0x80;
|
||||||
break;
|
break;
|
||||||
case 0xc062: // Switch input 1.
|
case 0xc062: // Switch input 1.
|
||||||
*value &= 0x7f;
|
*value &= 0x7f;
|
||||||
if(static_cast<Joystick *>(joysticks_[0].get())->buttons[1] || static_cast<Joystick *>(joysticks_[1].get())->buttons[1])
|
if(
|
||||||
|
static_cast<Joystick *>(joysticks_[0].get())->buttons[1] || static_cast<Joystick *>(joysticks_[1].get())->buttons[1] ||
|
||||||
|
(is_iie && closed_apple_is_pressed_)
|
||||||
|
)
|
||||||
*value |= 0x80;
|
*value |= 0x80;
|
||||||
break;
|
break;
|
||||||
case 0xc063: // Switch input 2.
|
case 0xc063: // Switch input 2.
|
||||||
@ -490,31 +498,28 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
// The IIe-only state reads follow...
|
// The IIe-only state reads follow...
|
||||||
case 0xc011: if(is_iie) *value = (*value & 0x7f) | (language_card_.bank1 ? 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 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 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 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 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 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 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 0xc018: if(is_iie) *value = (*value & 0x7f) | (video_->get_80_store() ? 0x80 : 0x00); break;
|
||||||
// TODO: c019 to read vertical blanking
|
case 0xc019: if(is_iie) *value = (*value & 0x7f) | (video_->get_is_vertical_blank(cycles_since_video_update_) ? 0x80 : 0x00); break;
|
||||||
case 0xc01a: if(is_iie) *value = (*value & 0x7f) | (video_->get_text() ? 0x80 : 0x00); 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 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 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 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 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 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 0xc07f: if(is_iie) *value = (*value & 0x7f) | (video_->get_double_high_resolution() ? 0x80 : 0x00); break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Write-only switches. All IIe as currently implemented.
|
// Write-only switches. All IIe as currently implemented.
|
||||||
if(is_iie) {
|
if(is_iie) {
|
||||||
// if(address >= 0xc000 && address < 0xc100) printf("w %04x\n", address);
|
|
||||||
switch(address) {
|
switch(address) {
|
||||||
default:
|
default: break;
|
||||||
// printf("Unknown (?) write to %04x\n", address);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc000:
|
case 0xc000:
|
||||||
case 0xc001:
|
case 0xc001:
|
||||||
@ -722,8 +727,16 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set_key_pressed(Key key, char value, bool is_pressed) override {
|
void set_key_pressed(Key key, char value, bool is_pressed) override {
|
||||||
if(key == Key::F12) {
|
switch(key) {
|
||||||
m6502_.set_reset_line(is_pressed);
|
default: break;
|
||||||
|
case Key::F12:
|
||||||
|
m6502_.set_reset_line(is_pressed);
|
||||||
|
return;
|
||||||
|
case Key::LeftMeta: case Key::LeftOption:
|
||||||
|
open_apple_is_pressed_ = is_pressed;
|
||||||
|
return;
|
||||||
|
case Key::RightMeta: case Key::RightOption:
|
||||||
|
closed_apple_is_pressed_ = is_pressed;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,7 +752,9 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value = static_cast<char>(toupper(value));
|
// Prior to the IIe, the keyboard could produce uppercase only.
|
||||||
|
if(!is_iie) value = static_cast<char>(toupper(value));
|
||||||
|
|
||||||
if(is_pressed) {
|
if(is_pressed) {
|
||||||
keyboard_input_ = static_cast<uint8_t>(value | 0x80);
|
keyboard_input_ = static_cast<uint8_t>(value | 0x80);
|
||||||
key_is_down_ = true;
|
key_is_down_ = true;
|
||||||
|
@ -536,6 +536,23 @@ template <class BusHandler, bool is_iie> class Video: public VideoBase {
|
|||||||
return bus_handler_.perform_read(read_address);
|
return bus_handler_.perform_read(read_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@returns @c true if the display will be within vertical blank at now + @c offset; @c false otherwise.
|
||||||
|
*/
|
||||||
|
bool get_is_vertical_blank(Cycles offset) {
|
||||||
|
// Map that backwards from the internal pixels-at-start generation to pixels-at-end
|
||||||
|
// (so what was column 0 is now column 25).
|
||||||
|
int mapped_column = column_ + offset.as_int();
|
||||||
|
|
||||||
|
// Map that backwards from the internal pixels-at-start generation to pixels-at-end
|
||||||
|
// (so what was column 0 is now column 25).
|
||||||
|
mapped_column += 25;
|
||||||
|
|
||||||
|
// Apply carry into the row counter and test it for location.
|
||||||
|
int mapped_row = row_ + (mapped_column / 65);
|
||||||
|
return (mapped_row % 262) >= 192;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GraphicsMode graphics_mode(int row) {
|
GraphicsMode graphics_mode(int row) {
|
||||||
if(text_) return columns_80_ ? GraphicsMode::DoubleText : GraphicsMode::Text;
|
if(text_) return columns_80_ ? GraphicsMode::DoubleText : GraphicsMode::Text;
|
||||||
|
Loading…
Reference in New Issue
Block a user