mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-13 22:32:03 +00:00
Slightly corrects style errors in the Cartridge hierarchy, and introduces mapping of .ROM to the MSX when appropriate.
This commit is contained in:
parent
d3dd8f3f2a
commit
ca26ce8400
@ -105,14 +105,14 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
|||||||
|
|
||||||
while(access_pointer_ < end) {
|
while(access_pointer_ < end) {
|
||||||
switch(access_pointer_%3) {
|
switch(access_pointer_%3) {
|
||||||
case 2:
|
|
||||||
pattern_name_ = ram_[row_base + character_column];
|
|
||||||
break;
|
|
||||||
case 1: break; // TODO: CPU access.
|
|
||||||
case 0:
|
case 0:
|
||||||
pattern_buffer_[character_column] = ram_[pattern_generator_table_address_ + (pattern_name_ << 3) + (row_ & 7)];
|
pattern_buffer_[character_column] = ram_[pattern_generator_table_address_ + (pattern_name_ << 3) + (row_ & 7)];
|
||||||
character_column++;
|
character_column++;
|
||||||
break;
|
break;
|
||||||
|
case 1: break; // TODO: CPU access.
|
||||||
|
case 2:
|
||||||
|
pattern_name_ = ram_[row_base + character_column];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
access_pointer_++;
|
access_pointer_++;
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
|
|||||||
AcornCartridgesFrom(const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
|
AcornCartridgesFrom(const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
|
||||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> acorn_cartridges;
|
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> acorn_cartridges;
|
||||||
|
|
||||||
for(std::shared_ptr<Storage::Cartridge::Cartridge> cartridge : cartridges) {
|
for(const auto &cartridge : cartridges) {
|
||||||
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridge->get_segments();
|
const auto &segments = cartridge->get_segments();
|
||||||
|
|
||||||
// only one mapped item is allowed
|
// only one mapped item is allowed
|
||||||
if(segments.size() != 1) continue;
|
if(segments.size() != 1) continue;
|
||||||
|
@ -189,7 +189,7 @@ void StaticAnalyser::Atari::AddTargets(const Media &media, std::list<Target> &de
|
|||||||
|
|
||||||
// try to figure out the paging scheme
|
// try to figure out the paging scheme
|
||||||
if(!media.cartridges.empty()) {
|
if(!media.cartridges.empty()) {
|
||||||
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = media.cartridges.front()->get_segments();
|
const auto &segments = media.cartridges.front()->get_segments();
|
||||||
|
|
||||||
if(segments.size() == 1) {
|
if(segments.size() == 1) {
|
||||||
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
|
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
|
||||||
|
@ -21,8 +21,8 @@ static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
|
|||||||
Vic20CartridgesFrom(const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
|
Vic20CartridgesFrom(const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
|
||||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> vic20_cartridges;
|
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> vic20_cartridges;
|
||||||
|
|
||||||
for(std::shared_ptr<Storage::Cartridge::Cartridge> cartridge : cartridges) {
|
for(const auto &cartridge : cartridges) {
|
||||||
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridge->get_segments();
|
const auto &segments = cartridge->get_segments();
|
||||||
|
|
||||||
// only one mapped item is allowed
|
// only one mapped item is allowed
|
||||||
if(segments.size() != 1) continue;
|
if(segments.size() != 1) continue;
|
||||||
|
@ -8,11 +8,68 @@
|
|||||||
|
|
||||||
#include "StaticAnalyser.hpp"
|
#include "StaticAnalyser.hpp"
|
||||||
|
|
||||||
void StaticAnalyser::MSX::AddTargets(const Media &media, std::list<Target> &destination) {
|
/*
|
||||||
// Very trusting...
|
DEFB "AB" ; expansion ROM header
|
||||||
Target target;
|
DEFW initcode ; start of the init code, 0 if no initcode
|
||||||
target.machine = Target::MSX;
|
DEFW callstat; pointer to CALL statement handler, 0 if no such handler
|
||||||
target.probability = 1.0;
|
DEFW device; pointer to expansion device handler, 0 if no such handler
|
||||||
target.media = media;
|
DEFW basic ; pointer to the start of a tokenized basicprogram, 0 if no basicprogram
|
||||||
destination.push_back(target);
|
DEFS 6,0 ; room reserved for future extensions
|
||||||
|
*/
|
||||||
|
static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
|
||||||
|
MSXCartridgesFrom(const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
|
||||||
|
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> msx_cartridges;
|
||||||
|
|
||||||
|
for(const auto &cartridge : cartridges) {
|
||||||
|
const auto &segments = cartridge->get_segments();
|
||||||
|
|
||||||
|
// Only one mapped item is allowed.
|
||||||
|
if(segments.size() != 1) continue;
|
||||||
|
|
||||||
|
// Which must be a multiple of 16 kb in size.
|
||||||
|
Storage::Cartridge::Cartridge::Segment segment = segments.front();
|
||||||
|
const size_t data_size = segment.data.size();
|
||||||
|
if(data_size < 0x4000 || data_size & 0x3fff) continue;
|
||||||
|
|
||||||
|
// Check for a ROM header at address 0; TODO: if it's not found then try 0x4000
|
||||||
|
// and consider swapping the image.
|
||||||
|
|
||||||
|
// Check for the expansion ROM header and the reserved bytes.
|
||||||
|
if(segment.data[0] != 0x41 || segment.data[1] != 0x42) continue;
|
||||||
|
bool all_zeroes = true;
|
||||||
|
for(size_t c = 0; c < 6; ++c) {
|
||||||
|
if(segment.data[10 + c] != 0) all_zeroes = false;
|
||||||
|
}
|
||||||
|
if(!all_zeroes) continue;
|
||||||
|
|
||||||
|
// Pick a paging address based on the four pointers.
|
||||||
|
uint16_t start_address = 0xc000;
|
||||||
|
for(size_t c = 0; c < 8; c += 2) {
|
||||||
|
uint16_t code_pointer = static_cast<uint16_t>(segment.data[2 + c] | segment.data[3 + c] << 8);
|
||||||
|
if(code_pointer) {
|
||||||
|
start_address = std::min(static_cast<uint16_t>(code_pointer &~ 0x3fff), start_address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// That'll do then, but apply the detected start address.
|
||||||
|
// printf("%04x\n", start_address);
|
||||||
|
|
||||||
|
msx_cartridges.emplace_back(new Storage::Cartridge::Cartridge({
|
||||||
|
Storage::Cartridge::Cartridge::Segment(start_address, segment.data)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return msx_cartridges;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticAnalyser::MSX::AddTargets(const Media &media, std::list<Target> &destination) {
|
||||||
|
Target target;
|
||||||
|
|
||||||
|
target.media.cartridges = MSXCartridgesFrom(media.cartridges);
|
||||||
|
|
||||||
|
if(!target.media.empty()) {
|
||||||
|
target.machine = Target::MSX;
|
||||||
|
target.probability = 1.0;
|
||||||
|
destination.push_back(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ static Media GetMediaAndPlatforms(const char *file_name, TargetPlatform::IntType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Format("rom", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Acorn) // ROM
|
Format("rom", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Acorn | TargetPlatform::MSX) // ROM
|
||||||
Format("ssd", result.disks, Disk::DiskImageHolder<Storage::Disk::SSD>, TargetPlatform::Acorn) // SSD
|
Format("ssd", result.disks, Disk::DiskImageHolder<Storage::Disk::SSD>, TargetPlatform::Acorn) // SSD
|
||||||
Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore)
|
Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore)
|
||||||
Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric)
|
Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric)
|
||||||
|
@ -59,6 +59,10 @@ struct Media {
|
|||||||
std::list<std::shared_ptr<Storage::Disk::Disk>> disks;
|
std::list<std::shared_ptr<Storage::Disk::Disk>> disks;
|
||||||
std::list<std::shared_ptr<Storage::Tape::Tape>> tapes;
|
std::list<std::shared_ptr<Storage::Tape::Tape>> tapes;
|
||||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
|
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return disks.empty() && tapes.empty() && cartridges.empty();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -8,4 +8,5 @@
|
|||||||
|
|
||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
const int Storage::Cartridge::Cartridge::Segment::UnknownAddress = -1;
|
const size_t Storage::Cartridge::Cartridge::Segment::UnknownAddress = -1;
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#ifndef Storage_Cartridge_hpp
|
#ifndef Storage_Cartridge_hpp
|
||||||
#define Storage_Cartridge_hpp
|
#define Storage_Cartridge_hpp
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -29,19 +28,22 @@ namespace Cartridge {
|
|||||||
class Cartridge {
|
class Cartridge {
|
||||||
public:
|
public:
|
||||||
struct Segment {
|
struct Segment {
|
||||||
Segment(int start_address, int end_address, std::vector<uint8_t> data) :
|
Segment(size_t start_address, size_t end_address, std::vector<uint8_t> data) :
|
||||||
start_address(start_address), end_address(end_address), data(std::move(data)) {}
|
start_address(start_address), end_address(end_address), data(std::move(data)) {}
|
||||||
|
|
||||||
|
Segment(int start_address, std::vector<uint8_t> data) :
|
||||||
|
Segment(start_address, start_address + data.size(), data) {}
|
||||||
|
|
||||||
/// Indicates that an address is unknown.
|
/// Indicates that an address is unknown.
|
||||||
static const int UnknownAddress;
|
static const size_t UnknownAddress;
|
||||||
|
|
||||||
/// The initial CPU-exposed starting address for this segment; may be @c UnknownAddress.
|
/// The initial CPU-exposed starting address for this segment; may be @c UnknownAddress.
|
||||||
int start_address;
|
size_t start_address;
|
||||||
/*!
|
/*!
|
||||||
The initial CPU-exposed ending address for this segment; may be @c UnknownAddress. Not necessarily equal
|
The initial CPU-exposed ending address for this segment; may be @c UnknownAddress. Not necessarily equal
|
||||||
to start_address + data_length due to potential paging.
|
to start_address + data_length due to potential paging.
|
||||||
*/
|
*/
|
||||||
int end_address;
|
size_t end_address;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
The data contents for this segment. If @c start_address and @c end_address are suppled then
|
The data contents for this segment. If @c start_address and @c end_address are suppled then
|
||||||
@ -51,11 +53,16 @@ class Cartridge {
|
|||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::list<Segment> &get_segments() { return segments_; }
|
const std::vector<Segment> &get_segments() const {
|
||||||
|
return segments_;
|
||||||
|
}
|
||||||
virtual ~Cartridge() {}
|
virtual ~Cartridge() {}
|
||||||
|
|
||||||
|
Cartridge() {}
|
||||||
|
Cartridge(const std::vector<Segment> &segments) : segments_(segments) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::list<Segment> segments_;
|
std::vector<Segment> segments_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user