2023-01-13 04:01:11 +00:00
|
|
|
//
|
|
|
|
// MemorySlotHandler.cpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 12/01/2023.
|
|
|
|
// Copyright © 2023 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "MemorySlotHandler.hpp"
|
|
|
|
|
2023-01-13 04:08:01 +00:00
|
|
|
#include <cassert>
|
|
|
|
|
2023-01-13 04:01:11 +00:00
|
|
|
using namespace MSX;
|
|
|
|
|
2023-01-16 03:51:17 +00:00
|
|
|
PrimarySlot::PrimarySlot(MemorySlotChangeHandler &handler) :
|
|
|
|
subslots_{handler, handler, handler, handler} {}
|
|
|
|
|
2023-01-14 02:54:59 +00:00
|
|
|
MemorySlot::MemorySlot(MemorySlotChangeHandler &handler) : handler_(handler) {
|
2023-01-17 00:52:40 +00:00
|
|
|
unmap(0x0000, 0x10000);
|
2023-01-13 04:01:11 +00:00
|
|
|
}
|
|
|
|
|
2023-01-16 03:51:17 +00:00
|
|
|
void PrimarySlot::set_secondary_paging(uint8_t value) {
|
2023-01-13 04:01:11 +00:00
|
|
|
secondary_paging_ = value;
|
|
|
|
}
|
|
|
|
|
2023-01-16 03:51:17 +00:00
|
|
|
uint8_t PrimarySlot::secondary_paging() const {
|
2023-01-13 04:01:11 +00:00
|
|
|
return secondary_paging_;
|
|
|
|
}
|
|
|
|
|
2023-01-16 03:51:17 +00:00
|
|
|
const uint8_t *PrimarySlot::read_pointer(int segment) const {
|
2023-01-13 04:01:11 +00:00
|
|
|
const int subslot = (secondary_paging_ >> (segment & ~1)) & 3;
|
2023-01-16 03:51:17 +00:00
|
|
|
return subslots_[subslot].read_pointer(segment);
|
2023-01-13 04:01:11 +00:00
|
|
|
}
|
|
|
|
|
2023-01-16 03:51:17 +00:00
|
|
|
uint8_t *PrimarySlot::write_pointer(int segment) const {
|
2023-01-13 04:01:11 +00:00
|
|
|
const int subslot = (secondary_paging_ >> (segment & ~1)) & 3;
|
2023-01-16 03:51:17 +00:00
|
|
|
return subslots_[subslot].write_pointer(segment);
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t *MemorySlot::read_pointer(int segment) const {
|
|
|
|
return read_pointers_[segment];
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t *MemorySlot::write_pointer(int segment) const {
|
|
|
|
return write_pointers_[segment];
|
2023-01-13 04:01:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySlot::set_source(const std::vector<uint8_t> &source) {
|
|
|
|
source_ = source;
|
|
|
|
}
|
|
|
|
|
2023-01-13 19:07:54 +00:00
|
|
|
void MemorySlot::resize_source(std::size_t size) {
|
|
|
|
source_.resize(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<uint8_t> &MemorySlot::source() {
|
|
|
|
return source_;
|
|
|
|
}
|
|
|
|
|
2023-01-13 04:01:11 +00:00
|
|
|
const std::vector<uint8_t> &MemorySlot::source() const {
|
|
|
|
return source_;
|
|
|
|
}
|
|
|
|
|
2023-01-13 14:31:56 +00:00
|
|
|
template <MSX::MemorySlot::AccessType type>
|
2023-01-16 03:51:17 +00:00
|
|
|
void MemorySlot::map(std::size_t source_address, uint16_t destination_address, std::size_t length) {
|
2023-01-13 04:01:11 +00:00
|
|
|
assert(!(destination_address & 8191));
|
|
|
|
assert(!(length & 8191));
|
|
|
|
assert(size_t(destination_address) + length <= 65536);
|
|
|
|
|
|
|
|
for(std::size_t c = 0; c < (length >> 13); ++c) {
|
|
|
|
source_address %= source_.size();
|
2023-01-13 14:31:56 +00:00
|
|
|
|
|
|
|
const int bank = int((destination_address >> 13) + c);
|
2023-01-16 03:51:17 +00:00
|
|
|
read_pointers_[bank] = &source_[source_address];
|
2023-01-13 14:31:56 +00:00
|
|
|
if constexpr (type == AccessType::ReadWrite) {
|
2023-01-16 03:51:17 +00:00
|
|
|
write_pointers_[bank] = read_pointers_[bank];
|
2023-01-13 14:31:56 +00:00
|
|
|
}
|
|
|
|
|
2023-01-13 04:01:11 +00:00
|
|
|
source_address += 8192;
|
|
|
|
}
|
|
|
|
|
2023-01-14 02:54:59 +00:00
|
|
|
handler_.did_page();
|
2023-01-13 04:01:11 +00:00
|
|
|
}
|
|
|
|
|
2023-01-17 00:52:40 +00:00
|
|
|
void MemorySlot::map_handler(uint16_t destination_address, std::size_t length) {
|
2023-01-13 04:01:11 +00:00
|
|
|
assert(!(destination_address & 8191));
|
|
|
|
assert(!(length & 8191));
|
|
|
|
assert(size_t(destination_address) + length <= 65536);
|
|
|
|
|
|
|
|
for(std::size_t c = 0; c < (length >> 13); ++c) {
|
2023-01-16 03:51:17 +00:00
|
|
|
read_pointers_[(destination_address >> 13) + c] = nullptr;
|
2023-01-13 04:01:11 +00:00
|
|
|
}
|
|
|
|
|
2023-01-14 02:54:59 +00:00
|
|
|
handler_.did_page();
|
2023-01-13 04:01:11 +00:00
|
|
|
}
|
2023-01-13 14:31:56 +00:00
|
|
|
|
2023-01-17 00:52:40 +00:00
|
|
|
void MemorySlot::unmap(uint16_t destination_address, std::size_t length) {
|
|
|
|
assert(!(destination_address & 8191));
|
|
|
|
assert(!(length & 8191));
|
|
|
|
assert(size_t(destination_address) + length <= 65536);
|
|
|
|
|
|
|
|
for(std::size_t c = 0; c < (length >> 13); ++c) {
|
|
|
|
read_pointers_[(destination_address >> 13) + c] = unmapped.data();
|
|
|
|
write_pointers_[(destination_address >> 13) + c] = scratch.data();
|
|
|
|
}
|
|
|
|
|
|
|
|
handler_.did_page();
|
|
|
|
}
|
|
|
|
|
2023-01-16 03:51:17 +00:00
|
|
|
MemorySlot &PrimarySlot::subslot(int slot) {
|
|
|
|
return subslots_[slot];
|
|
|
|
}
|
|
|
|
|
|
|
|
template void MemorySlot::map<MSX::MemorySlot::AccessType::Read>(std::size_t source_address, uint16_t destination_address, std::size_t length);
|
|
|
|
template void MemorySlot::map<MSX::MemorySlot::AccessType::ReadWrite>(std::size_t source_address, uint16_t destination_address, std::size_t length);
|