1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Merge pull request #100 from TomHarte/SuperChipDetection

Adds detection and emulation of the Super Chip
This commit is contained in:
Thomas Harte 2017-02-26 18:04:50 -05:00 committed by GitHub
commit 997707a45b
6 changed files with 75 additions and 17 deletions

View File

@ -87,8 +87,21 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
}
// check for a ROM read
if((address&0x1000) && isReadOperation(operation)) {
returnValue &= rom_pages_[(address >> 10)&3][address&1023];
uint16_t masked_address = address & 0x1fff;
if(address&0x1000)
{
if(isReadOperation(operation) && (!uses_superchip_ || masked_address > 0x10ff)) {
returnValue &= rom_pages_[(address >> 10)&3][address&1023];
}
// check for a Super Chip RAM access
if(uses_superchip_ && masked_address < 0x1100) {
if(masked_address < 0x1080) {
superchip_ram_[masked_address & 0x7f] = *value;
} else {
returnValue &= superchip_ram_[masked_address & 0x7f];
}
}
}
// check for a RAM access
@ -263,6 +276,8 @@ void Machine::configure_as_target(const StaticAnalyser::Target &target)
rom_pages_[1] = &rom_[1024 & romMask];
rom_pages_[2] = &rom_[2048 & romMask];
rom_pages_[3] = &rom_[3072 & romMask];
uses_superchip_ = target.atari.uses_superchip;
}
#pragma mark - Audio and Video

View File

@ -56,9 +56,14 @@ class Machine:
virtual void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs);
private:
// ROM information
uint8_t *rom_, *rom_pages_[4];
size_t rom_size_;
// cartridge RAM expansion store
uint8_t superchip_ram_[128];
bool uses_superchip_;
// the RIOT and TIA
PIA mos6532_;
std::unique_ptr<TIA> tia_;

View File

@ -27,9 +27,10 @@ void StaticAnalyser::Atari::AddTargets(
target.tapes = tapes;
target.cartridges = cartridges;
target.atari.paging_model = Atari2600PagingModel::None;
target.atari.uses_superchip = false;
// try to figure out the paging scheme
/* if(!cartridges.empty())
if(!cartridges.empty())
{
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridges.front()->get_segments();
if(segments.size() == 1)
@ -48,9 +49,23 @@ void StaticAnalyser::Atari::AddTargets(
}
StaticAnalyser::MOS6502::Disassembly disassembly =
StaticAnalyser::MOS6502::Disassemble(segment.data, 0x1000, {entry_address, break_address}, 0x1fff);
printf("%p", &disassembly);
// check for any sort of on-cartridge RAM; that might imply a Super Chip or else immediately tip the
// hat that this is a CBS RAM+ cartridge
if(!disassembly.internal_stores.empty())
{
bool writes_above_128 = false;
for(uint16_t address : disassembly.internal_stores)
{
writes_above_128 |= ((address & 0x1fff) > 0x10ff) && ((address & 0x1fff) < 0x1200);
}
if(writes_above_128)
target.atari.paging_model = Atari2600PagingModel::CBSRamPlus;
else
target.atari.uses_superchip = true;
}
}
}*/
}
destination.push_back(target);
}

View File

@ -189,7 +189,7 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
break;
case 0x87: case 0x97: case 0x83: case 0x8f:
instruction.operation = Instruction::SAX;
instruction.operation = Instruction::AXS;
break;
case 0xa7: case 0xb7: case 0xa3: case 0xb3: case 0xaf: case 0xbf:
instruction.operation = Instruction::LAX;
@ -205,7 +205,7 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
IM_INSTRUCTION(0x6b, Instruction::ARR)
IM_INSTRUCTION(0x8b, Instruction::XAA)
IM_INSTRUCTION(0xab, Instruction::LAX)
IM_INSTRUCTION(0xcb, Instruction::AXS)
IM_INSTRUCTION(0xcb, Instruction::SAX)
IM_INSTRUCTION(0xeb, Instruction::SBC)
case 0x93: case 0x9f:
instruction.operation = Instruction::AHX;
@ -259,16 +259,36 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
disassembly.disassembly.instructions_by_address[instruction.address] = instruction;
// TODO: something wider-ranging than this
if((instruction.addressing_mode == Instruction::Absolute || instruction.addressing_mode == Instruction::ZeroPage) && (instruction.operand < start_address || instruction.operand >= start_address + memory.size()))
if(instruction.addressing_mode == Instruction::Absolute || instruction.addressing_mode == Instruction::ZeroPage)
{
if( instruction.operation == Instruction::STY ||
instruction.operation == Instruction::STX ||
instruction.operation == Instruction::STA)
disassembly.disassembly.external_stores.insert(instruction.operand);
if( instruction.operation == Instruction::LDY ||
instruction.operation == Instruction::LDX ||
instruction.operation == Instruction::LDA)
disassembly.disassembly.external_loads.insert(instruction.operand);
bool is_external = (instruction.operand&address_mask) < start_address || (instruction.operand&address_mask) >= start_address + memory.size();
switch(instruction.operation)
{
default: break;
case Instruction::LDY: case Instruction::LDX: case Instruction::LDA:
case Instruction::LAX:
case Instruction::AND: case Instruction::EOR: case Instruction::ORA: case Instruction::BIT:
case Instruction::ADC: case Instruction::SBC:
case Instruction::LAS:
case Instruction::CMP: case Instruction::CPX: case Instruction::CPY:
(is_external ? disassembly.disassembly.external_loads : disassembly.disassembly.internal_loads).insert(instruction.operand);
break;
case Instruction::STY: case Instruction::STX: case Instruction::STA:
case Instruction::AXS: case Instruction::AHX: case Instruction::SHX: case Instruction::SHY:
case Instruction::TAS:
(is_external ? disassembly.disassembly.external_stores : disassembly.disassembly.internal_stores).insert(instruction.operand);
break;
case Instruction::SLO: case Instruction::RLA: case Instruction::SRE: case Instruction::RRA:
case Instruction::DCP: case Instruction::ISC:
case Instruction::INC: case Instruction::DEC:
case Instruction::ASL: case Instruction::ROL: case Instruction::LSR: case Instruction::ROR:
(is_external ? disassembly.disassembly.external_modifies : disassembly.disassembly.internal_modifies).insert(instruction.operand);
break;
}
}
// decide on overall flow control

View File

@ -65,6 +65,7 @@ struct Disassembly {
std::map<uint16_t, Instruction> instructions_by_address;
std::set<uint16_t> outward_calls;
std::set<uint16_t> external_stores, external_loads, external_modifies;
std::set<uint16_t> internal_stores, internal_loads, internal_modifies;
};
Disassembly Disassemble(const std::vector<uint8_t> &memory, uint16_t start_address, std::vector<uint16_t> entry_points, uint16_t address_mask = 0xffff);

View File

@ -32,7 +32,8 @@ enum class Atari2600PagingModel {
Atari32k,
ActivisionStack,
ParkerBros,
Tigervision
Tigervision,
CBSRamPlus
};
/*!
@ -57,6 +58,7 @@ struct Target {
struct {
Atari2600PagingModel paging_model;
bool uses_superchip;
} atari;
struct {