mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Merge pull request #355 from TomHarte/MegaCart
Adds MegaCart support for the ColecoVision.
This commit is contained in:
commit
fdfd72a42c
@ -21,15 +21,32 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
|
||||
// which must be 8, 12, 16, 24 or 32 kb in size
|
||||
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
|
||||
const std::size_t data_size = segment.data.size();
|
||||
if((data_size&8191) && (data_size != 12*1024)) continue;
|
||||
if(data_size < 8192 || data_size > 32768) continue;
|
||||
const std::size_t overflow = data_size&8191;
|
||||
if(overflow > 8 && overflow != 512 && (data_size != 12*1024)) continue;
|
||||
if(data_size < 8192) continue;
|
||||
|
||||
// the two first bytes must be 0xaa and 0x55, either way around
|
||||
if(segment.data[0] != 0xaa && segment.data[0] != 0x55 && segment.data[1] != 0xaa && segment.data[1] != 0x55) continue;
|
||||
if(segment.data[0] == segment.data[1]) continue;
|
||||
// the two bytes that will be first must be 0xaa and 0x55, either way around
|
||||
auto *start = &segment.data[0];
|
||||
if((data_size & static_cast<std::size_t>(~8191)) > 32768) {
|
||||
start = &segment.data[segment.data.size() - 16384];
|
||||
}
|
||||
if(start[0] != 0xaa && start[0] != 0x55 && start[1] != 0xaa && start[1] != 0x55) continue;
|
||||
if(start[0] == start[1]) continue;
|
||||
|
||||
// probability of a random binary blob that isn't a Coleco ROM proceeding to here is 1 - 1/32768.
|
||||
if(!overflow) {
|
||||
coleco_cartridges.push_back(cartridge);
|
||||
} else {
|
||||
// Size down to a multiple of 8kb and apply the start address.
|
||||
std::vector<Storage::Cartridge::Cartridge::Segment> output_segments;
|
||||
|
||||
std::vector<uint8_t> truncated_data;
|
||||
std::vector<uint8_t>::difference_type truncated_size = static_cast<std::vector<uint8_t>::difference_type>(segment.data.size()) & ~8191;
|
||||
truncated_data.insert(truncated_data.begin(), segment.data.begin(), segment.data.begin() + truncated_size);
|
||||
output_segments.emplace_back(0x8000, truncated_data);
|
||||
|
||||
coleco_cartridges.emplace_back(new Storage::Cartridge::Cartridge(output_segments));
|
||||
}
|
||||
}
|
||||
|
||||
return coleco_cartridges;
|
||||
|
@ -153,6 +153,20 @@ class ConcreteMachine:
|
||||
if(!media.cartridges.empty()) {
|
||||
const auto &segment = media.cartridges.front()->get_segments().front();
|
||||
cartridge_ = segment.data;
|
||||
if(cartridge_.size() >= 32768)
|
||||
cartridge_address_limit_ = 0xffff;
|
||||
else
|
||||
cartridge_address_limit_ = static_cast<uint16_t>(0x8000 + cartridge_.size() - 1);
|
||||
|
||||
if(cartridge_.size() > 32768) {
|
||||
cartridge_pages_[0] = &cartridge_[cartridge_.size() - 16384];
|
||||
cartridge_pages_[1] = cartridge_.data();
|
||||
is_megacart_ = true;
|
||||
} else {
|
||||
cartridge_pages_[0] = cartridge_.data();
|
||||
cartridge_pages_[1] = cartridge_.data() + 16384;
|
||||
is_megacart_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -182,8 +196,11 @@ class ConcreteMachine:
|
||||
*cycle.value = bios_[address & 0x1fff];
|
||||
} else if(address >= 0x6000 && address < 0x8000) {
|
||||
*cycle.value = ram_[address & 1023];
|
||||
} else if(address >= 0x8000) {
|
||||
*cycle.value = cartridge_[(address - 0x8000) % cartridge_.size()]; // This probably isn't how 24kb ROMs work?
|
||||
} else if(address >= 0x8000 && address <= cartridge_address_limit_) {
|
||||
if(is_megacart_ && address >= 0xffc0) {
|
||||
page_megacart(address);
|
||||
}
|
||||
*cycle.value = cartridge_pages_[(address >> 14)&1][address&0x3fff];
|
||||
} else {
|
||||
*cycle.value = 0xff;
|
||||
}
|
||||
@ -192,6 +209,8 @@ class ConcreteMachine:
|
||||
case CPU::Z80::PartialMachineCycle::Write:
|
||||
if(address >= 0x6000 && address < 0x8000) {
|
||||
ram_[address & 1023] = *cycle.value;
|
||||
} else if(is_megacart_ && address >= 0xffc0) {
|
||||
page_megacart(address);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -266,10 +285,14 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
private:
|
||||
void update_audio() {
|
||||
inline void page_megacart(uint16_t address) {
|
||||
const std::size_t selected_start = (static_cast<std::size_t>(address&63) << 14) % cartridge_.size();
|
||||
cartridge_pages_[1] = &cartridge_[selected_start];
|
||||
}
|
||||
inline void update_audio() {
|
||||
speaker_.run_for(audio_queue_, time_since_sn76489_update_.divide_cycles(Cycles(sn76489_divider)));
|
||||
}
|
||||
void update_video() {
|
||||
inline void update_video() {
|
||||
vdp_->run_for(time_since_vdp_update_.flush());
|
||||
}
|
||||
|
||||
@ -282,7 +305,10 @@ class ConcreteMachine:
|
||||
|
||||
std::vector<uint8_t> bios_;
|
||||
std::vector<uint8_t> cartridge_;
|
||||
uint8_t *cartridge_pages_[2];
|
||||
uint8_t ram_[1024];
|
||||
bool is_megacart_ = false;
|
||||
uint16_t cartridge_address_limit_ = 0;
|
||||
|
||||
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
|
||||
bool joysticks_in_keypad_mode_ = false;
|
||||
|
Loading…
Reference in New Issue
Block a user