mirror of
https://github.com/TomHarte/CLK.git
synced 2024-09-08 18:55:14 +00:00
Merge pull request #101 from TomHarte/CommaVid
Adds detection and emulation of the CommaVid paging scheme
This commit is contained in:
commit
1625b9c7f9
@ -90,17 +90,20 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
|
|||||||
uint16_t masked_address = address & 0x1fff;
|
uint16_t masked_address = address & 0x1fff;
|
||||||
if(address&0x1000)
|
if(address&0x1000)
|
||||||
{
|
{
|
||||||
if(isReadOperation(operation) && (!uses_superchip_ || masked_address > 0x10ff)) {
|
// check for a RAM access
|
||||||
returnValue &= rom_pages_[(address >> 10)&3][address&1023];
|
bool was_ram_access = false;
|
||||||
|
if(has_ram_) {
|
||||||
|
if(masked_address >= ram_write_start_ && masked_address < ram_.size() + ram_write_start_) {
|
||||||
|
ram_[masked_address & ram_.size() - 1] = *value;
|
||||||
|
was_ram_access = true;
|
||||||
|
} else if(masked_address >= ram_read_start_ && masked_address < ram_.size() + ram_read_start_) {
|
||||||
|
returnValue &= ram_[masked_address & ram_.size() - 1];
|
||||||
|
was_ram_access = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for a Super Chip RAM access
|
if(isReadOperation(operation) && !was_ram_access) {
|
||||||
if(uses_superchip_ && masked_address < 0x1100) {
|
returnValue &= rom_pages_[(address >> 10)&3][address&1023];
|
||||||
if(masked_address < 0x1080) {
|
|
||||||
superchip_ram_[masked_address & 0x7f] = *value;
|
|
||||||
} else {
|
|
||||||
returnValue &= superchip_ram_[masked_address & 0x7f];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,7 +280,25 @@ void Machine::configure_as_target(const StaticAnalyser::Target &target)
|
|||||||
rom_pages_[2] = &rom_[2048 & romMask];
|
rom_pages_[2] = &rom_[2048 & romMask];
|
||||||
rom_pages_[3] = &rom_[3072 & romMask];
|
rom_pages_[3] = &rom_[3072 & romMask];
|
||||||
|
|
||||||
uses_superchip_ = target.atari.uses_superchip;
|
switch(target.atari.paging_model)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
if(target.atari.uses_superchip)
|
||||||
|
{
|
||||||
|
ram_.resize(128);
|
||||||
|
has_ram_ = true;
|
||||||
|
ram_write_start_ = 0x1000;
|
||||||
|
ram_read_start_ = 0x1080;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StaticAnalyser::Atari2600PagingModel::CommaVid:
|
||||||
|
ram_.resize(1024);
|
||||||
|
has_ram_ = true;
|
||||||
|
ram_write_start_ = 0x1400;
|
||||||
|
ram_read_start_ = 0x1000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Audio and Video
|
#pragma mark - Audio and Video
|
||||||
|
@ -61,8 +61,9 @@ class Machine:
|
|||||||
size_t rom_size_;
|
size_t rom_size_;
|
||||||
|
|
||||||
// cartridge RAM expansion store
|
// cartridge RAM expansion store
|
||||||
uint8_t superchip_ram_[128];
|
std::vector<uint8_t> ram_;
|
||||||
bool uses_superchip_;
|
uint16_t ram_write_start_, ram_read_start_;
|
||||||
|
bool has_ram_;
|
||||||
|
|
||||||
// the RIOT and TIA
|
// the RIOT and TIA
|
||||||
PIA mos6532_;
|
PIA mos6532_;
|
||||||
|
@ -12,6 +12,120 @@
|
|||||||
|
|
||||||
using namespace StaticAnalyser::Atari;
|
using namespace StaticAnalyser::Atari;
|
||||||
|
|
||||||
|
static void DeterminePagingFor2kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment)
|
||||||
|
{
|
||||||
|
// if this is a 2kb cartridge then it's definitely either unpaged or a CommaVid
|
||||||
|
uint16_t entry_address, break_address;
|
||||||
|
|
||||||
|
entry_address = ((uint16_t)(segment.data[0x7fc] | (segment.data[0x7fd] << 8))) & 0x1fff;
|
||||||
|
break_address = ((uint16_t)(segment.data[0x7fe] | (segment.data[0x7ff] << 8))) & 0x1fff;
|
||||||
|
|
||||||
|
// a CommaVid start address needs to be outside of its RAM
|
||||||
|
if(entry_address < 0x1800 || break_address < 0x1800) return;
|
||||||
|
|
||||||
|
std::function<size_t(uint16_t address)> high_location_mapper = [](uint16_t address) {
|
||||||
|
address &= 0x1fff;
|
||||||
|
return (size_t)(address - 0x1800);
|
||||||
|
};
|
||||||
|
std::function<size_t(uint16_t address)> full_range_mapper = [](uint16_t address) {
|
||||||
|
if(!(address & 0x1000)) return (size_t)-1;
|
||||||
|
return (size_t)(address & 0x7ff);
|
||||||
|
};
|
||||||
|
|
||||||
|
StaticAnalyser::MOS6502::Disassembly high_location_disassembly =
|
||||||
|
StaticAnalyser::MOS6502::Disassemble(segment.data, high_location_mapper, {entry_address, break_address});
|
||||||
|
// StaticAnalyser::MOS6502::Disassembly full_range_disassembly =
|
||||||
|
// StaticAnalyser::MOS6502::Disassemble(segment.data, full_range_mapper, {entry_address, break_address});
|
||||||
|
|
||||||
|
// if there are no subroutines in the top 2kb of memory then this isn't a CommaVid
|
||||||
|
bool has_appropriate_subroutine_calls = false;
|
||||||
|
bool has_inappropriate_subroutine_calls = false;
|
||||||
|
for(uint16_t address : high_location_disassembly.internal_calls)
|
||||||
|
{
|
||||||
|
const uint16_t masked_address = address & 0x1fff;
|
||||||
|
has_appropriate_subroutine_calls |= (masked_address >= 0x1800);
|
||||||
|
has_inappropriate_subroutine_calls |= (masked_address < 0x1800);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumption here: a CommaVid will never branch into RAM. Possibly unsafe: if it won't then what's the RAM for?
|
||||||
|
if(!has_appropriate_subroutine_calls || has_inappropriate_subroutine_calls) return;
|
||||||
|
|
||||||
|
std::set<uint16_t> all_writes = high_location_disassembly.external_stores;
|
||||||
|
all_writes.insert(high_location_disassembly.external_modifies.begin(), high_location_disassembly.external_modifies.end());
|
||||||
|
|
||||||
|
// a CommaVid will use its RAM
|
||||||
|
if(all_writes.empty()) return;
|
||||||
|
|
||||||
|
bool has_appropriate_accesses = false;
|
||||||
|
for(uint16_t address : all_writes)
|
||||||
|
{
|
||||||
|
const uint16_t masked_address = address & 0x1fff;
|
||||||
|
if(masked_address >= 0x1400 && masked_address < 0x1800)
|
||||||
|
{
|
||||||
|
has_appropriate_accesses = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// in desperation, accept any kind of store that looks likely to be intended for large amounts of memory
|
||||||
|
bool has_wide_area_store = false;
|
||||||
|
if(!has_appropriate_accesses)
|
||||||
|
{
|
||||||
|
for(std::map<uint16_t, StaticAnalyser::MOS6502::Instruction>::value_type &entry : high_location_disassembly.instructions_by_address)
|
||||||
|
{
|
||||||
|
if(entry.second.operation == StaticAnalyser::MOS6502::Instruction::STA)
|
||||||
|
{
|
||||||
|
has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::Indirect;
|
||||||
|
has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::IndexedIndirectX;
|
||||||
|
has_wide_area_store |= entry.second.addressing_mode == StaticAnalyser::MOS6502::Instruction::IndirectIndexedY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// conclude that this is a CommaVid if it attempted to write something to the CommaVid RAM locations;
|
||||||
|
// caveat: false positives aren't likely to be problematic; a false positive is a 2KB ROM that always addresses
|
||||||
|
// itself so as to land in ROM even if mapped as a CommaVid and this code is on the fence as to whether it
|
||||||
|
// attempts to modify itself but it probably doesn't
|
||||||
|
if(has_appropriate_accesses || has_wide_area_store)
|
||||||
|
target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CommaVid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment)
|
||||||
|
{
|
||||||
|
if(segment.data.size() == 2048)
|
||||||
|
{
|
||||||
|
DeterminePagingFor2kCartridge(target, segment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t entry_address, break_address;
|
||||||
|
|
||||||
|
entry_address = (uint16_t)(segment.data[0xffc] | (segment.data[0xffd] << 8));
|
||||||
|
break_address = (uint16_t)(segment.data[0xffe] | (segment.data[0xfff] << 8));
|
||||||
|
|
||||||
|
std::function<size_t(uint16_t address)> address_mapper = [](uint16_t address) {
|
||||||
|
if(!(address & 0x1000)) return (size_t)-1;
|
||||||
|
return (size_t)(address & 0xfff);
|
||||||
|
};
|
||||||
|
StaticAnalyser::MOS6502::Disassembly disassembly =
|
||||||
|
StaticAnalyser::MOS6502::Disassemble(segment.data, address_mapper, {entry_address, break_address});
|
||||||
|
|
||||||
|
// 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 = StaticAnalyser::Atari2600PagingModel::CBSRamPlus;
|
||||||
|
else
|
||||||
|
target.atari.uses_superchip = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StaticAnalyser::Atari::AddTargets(
|
void StaticAnalyser::Atari::AddTargets(
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
||||||
@ -33,37 +147,11 @@ void StaticAnalyser::Atari::AddTargets(
|
|||||||
if(!cartridges.empty())
|
if(!cartridges.empty())
|
||||||
{
|
{
|
||||||
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridges.front()->get_segments();
|
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridges.front()->get_segments();
|
||||||
|
|
||||||
if(segments.size() == 1)
|
if(segments.size() == 1)
|
||||||
{
|
{
|
||||||
uint16_t entry_address, break_address;
|
|
||||||
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
|
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
|
||||||
if(segment.data.size() < 4096)
|
DeterminePagingForCartridge(target, segment);
|
||||||
{
|
|
||||||
entry_address = (uint16_t)(segment.data[0x7fc] | (segment.data[0x7fd] << 8));
|
|
||||||
break_address = (uint16_t)(segment.data[0x7fe] | (segment.data[0x7ff] << 8));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entry_address = (uint16_t)(segment.data[0xffc] | (segment.data[0xffd] << 8));
|
|
||||||
break_address = (uint16_t)(segment.data[0xffe] | (segment.data[0xfff] << 8));
|
|
||||||
}
|
|
||||||
StaticAnalyser::MOS6502::Disassembly disassembly =
|
|
||||||
StaticAnalyser::MOS6502::Disassemble(segment.data, 0x1000, {entry_address, break_address}, 0x1fff);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,17 +16,18 @@ struct PartialDisassembly {
|
|||||||
std::vector<uint16_t> remaining_entry_points;
|
std::vector<uint16_t> remaining_entry_points;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<uint8_t> &memory, uint16_t start_address, uint16_t entry_point, uint16_t address_mask)
|
static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<uint8_t> &memory, const std::function<size_t(uint16_t)> &address_mapper, uint16_t entry_point)
|
||||||
{
|
{
|
||||||
uint16_t address = entry_point & address_mask;
|
disassembly.disassembly.internal_calls.insert(entry_point);
|
||||||
|
uint16_t address = entry_point;
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
uint16_t local_address = address - start_address;
|
size_t local_address = address_mapper(address);
|
||||||
if(local_address >= memory.size()) return;
|
if(local_address >= memory.size()) return;
|
||||||
|
|
||||||
struct Instruction instruction;
|
struct Instruction instruction;
|
||||||
instruction.address = address;
|
instruction.address = address;
|
||||||
address = (address + 1) & address_mask;
|
address++;
|
||||||
|
|
||||||
// get operation
|
// get operation
|
||||||
uint8_t operation = memory[local_address];
|
uint8_t operation = memory[local_address];
|
||||||
@ -234,7 +235,7 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
|
|||||||
case Instruction::IndexedIndirectX: case Instruction::IndirectIndexedY:
|
case Instruction::IndexedIndirectX: case Instruction::IndirectIndexedY:
|
||||||
case Instruction::Relative:
|
case Instruction::Relative:
|
||||||
{
|
{
|
||||||
uint16_t operand_address = address - start_address;
|
size_t operand_address = address_mapper(address);
|
||||||
if(operand_address >= memory.size()) return;
|
if(operand_address >= memory.size()) return;
|
||||||
address++;
|
address++;
|
||||||
|
|
||||||
@ -246,11 +247,12 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
|
|||||||
case Instruction::Absolute: case Instruction::AbsoluteX: case Instruction::AbsoluteY:
|
case Instruction::Absolute: case Instruction::AbsoluteX: case Instruction::AbsoluteY:
|
||||||
case Instruction::Indirect:
|
case Instruction::Indirect:
|
||||||
{
|
{
|
||||||
uint16_t operand_address = address - start_address;
|
size_t low_operand_address = address_mapper(address);
|
||||||
if(operand_address >= memory.size()-1) return;
|
size_t high_operand_address = address_mapper(address + 1);
|
||||||
|
if(low_operand_address >= memory.size() || high_operand_address >= memory.size()) return;
|
||||||
address += 2;
|
address += 2;
|
||||||
|
|
||||||
instruction.operand = memory[operand_address] | (uint16_t)(memory[operand_address + 1] << 8);
|
instruction.operand = memory[low_operand_address] | (uint16_t)(memory[high_operand_address] << 8);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -261,7 +263,8 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
|
|||||||
// TODO: something wider-ranging than this
|
// TODO: something wider-ranging than this
|
||||||
if(instruction.addressing_mode == Instruction::Absolute || instruction.addressing_mode == Instruction::ZeroPage)
|
if(instruction.addressing_mode == Instruction::Absolute || instruction.addressing_mode == Instruction::ZeroPage)
|
||||||
{
|
{
|
||||||
bool is_external = (instruction.operand&address_mask) < start_address || (instruction.operand&address_mask) >= start_address + memory.size();
|
size_t mapped_address = address_mapper(instruction.operand);
|
||||||
|
bool is_external = mapped_address >= memory.size();
|
||||||
|
|
||||||
switch(instruction.operation)
|
switch(instruction.operation)
|
||||||
{
|
{
|
||||||
@ -296,23 +299,23 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
|
|||||||
if(instruction.operation == Instruction::BRK) return; // TODO: check whether IRQ vector is within memory range
|
if(instruction.operation == Instruction::BRK) return; // TODO: check whether IRQ vector is within memory range
|
||||||
if(instruction.operation == Instruction::JSR)
|
if(instruction.operation == Instruction::JSR)
|
||||||
{
|
{
|
||||||
disassembly.remaining_entry_points.push_back(instruction.operand & address_mask);
|
disassembly.remaining_entry_points.push_back(instruction.operand);
|
||||||
}
|
}
|
||||||
if(instruction.operation == Instruction::JMP)
|
if(instruction.operation == Instruction::JMP)
|
||||||
{
|
{
|
||||||
if(instruction.addressing_mode == Instruction::Absolute)
|
if(instruction.addressing_mode == Instruction::Absolute)
|
||||||
disassembly.remaining_entry_points.push_back(instruction.operand & address_mask);
|
disassembly.remaining_entry_points.push_back(instruction.operand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(instruction.addressing_mode == Instruction::Relative)
|
if(instruction.addressing_mode == Instruction::Relative)
|
||||||
{
|
{
|
||||||
uint16_t destination = (uint16_t)(address + (int8_t)instruction.operand);
|
uint16_t destination = (uint16_t)(address + (int8_t)instruction.operand);
|
||||||
disassembly.remaining_entry_points.push_back(destination & address_mask);
|
disassembly.remaining_entry_points.push_back(destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Disassembly StaticAnalyser::MOS6502::Disassemble(const std::vector<uint8_t> &memory, uint16_t start_address, std::vector<uint16_t> entry_points, uint16_t address_mask)
|
Disassembly StaticAnalyser::MOS6502::Disassemble(const std::vector<uint8_t> &memory, const std::function<size_t(uint16_t)> &address_mapper, std::vector<uint16_t> entry_points)
|
||||||
{
|
{
|
||||||
PartialDisassembly partialDisassembly;
|
PartialDisassembly partialDisassembly;
|
||||||
partialDisassembly.remaining_entry_points = entry_points;
|
partialDisassembly.remaining_entry_points = entry_points;
|
||||||
@ -320,18 +323,26 @@ Disassembly StaticAnalyser::MOS6502::Disassemble(const std::vector<uint8_t> &mem
|
|||||||
while(!partialDisassembly.remaining_entry_points.empty())
|
while(!partialDisassembly.remaining_entry_points.empty())
|
||||||
{
|
{
|
||||||
// pull the next entry point from the back of the vector
|
// pull the next entry point from the back of the vector
|
||||||
uint16_t next_entry_point = partialDisassembly.remaining_entry_points.back() & address_mask;
|
uint16_t next_entry_point = partialDisassembly.remaining_entry_points.back();
|
||||||
partialDisassembly.remaining_entry_points.pop_back();
|
partialDisassembly.remaining_entry_points.pop_back();
|
||||||
|
|
||||||
// if that address has already bene visited, forget about it
|
// if that address has already bene visited, forget about it
|
||||||
if(partialDisassembly.disassembly.instructions_by_address.find(next_entry_point) != partialDisassembly.disassembly.instructions_by_address.end()) continue;
|
if(partialDisassembly.disassembly.instructions_by_address.find(next_entry_point) != partialDisassembly.disassembly.instructions_by_address.end()) continue;
|
||||||
|
|
||||||
// if it's outgoing, log it as such and forget about it; otherwise disassemble
|
// if it's outgoing, log it as such and forget about it; otherwise disassemble
|
||||||
if(next_entry_point < start_address || next_entry_point >= start_address + memory.size())
|
size_t mapped_entry_point = address_mapper(next_entry_point);
|
||||||
|
if(mapped_entry_point >= memory.size())
|
||||||
partialDisassembly.disassembly.outward_calls.insert(next_entry_point);
|
partialDisassembly.disassembly.outward_calls.insert(next_entry_point);
|
||||||
else
|
else
|
||||||
AddToDisassembly(partialDisassembly, memory, start_address, next_entry_point, address_mask);
|
AddToDisassembly(partialDisassembly, memory, address_mapper, next_entry_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move(partialDisassembly.disassembly);
|
return std::move(partialDisassembly.disassembly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::function<size_t(uint16_t)> StaticAnalyser::MOS6502::OffsetMapper(uint16_t start_address)
|
||||||
|
{
|
||||||
|
return [start_address](uint16_t argument) {
|
||||||
|
return (size_t)(argument - start_address);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -10,10 +10,11 @@
|
|||||||
#define Disassembler6502_hpp
|
#define Disassembler6502_hpp
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace StaticAnalyser {
|
namespace StaticAnalyser {
|
||||||
namespace MOS6502 {
|
namespace MOS6502 {
|
||||||
@ -64,11 +65,13 @@ struct Instruction {
|
|||||||
struct Disassembly {
|
struct Disassembly {
|
||||||
std::map<uint16_t, Instruction> instructions_by_address;
|
std::map<uint16_t, Instruction> instructions_by_address;
|
||||||
std::set<uint16_t> outward_calls;
|
std::set<uint16_t> outward_calls;
|
||||||
|
std::set<uint16_t> internal_calls;
|
||||||
std::set<uint16_t> external_stores, external_loads, external_modifies;
|
std::set<uint16_t> external_stores, external_loads, external_modifies;
|
||||||
std::set<uint16_t> internal_stores, internal_loads, internal_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);
|
Disassembly Disassemble(const std::vector<uint8_t> &memory, const std::function<size_t(uint16_t)> &address_mapper, std::vector<uint16_t> entry_points);
|
||||||
|
std::function<size_t(uint16_t)> OffsetMapper(uint16_t start_address);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ void StaticAnalyser::Oric::AddTargets(
|
|||||||
{
|
{
|
||||||
std::vector<uint16_t> entry_points = {file.starting_address};
|
std::vector<uint16_t> entry_points = {file.starting_address};
|
||||||
StaticAnalyser::MOS6502::Disassembly disassembly =
|
StaticAnalyser::MOS6502::Disassembly disassembly =
|
||||||
StaticAnalyser::MOS6502::Disassemble(file.data, file.starting_address, entry_points);
|
StaticAnalyser::MOS6502::Disassemble(file.data, StaticAnalyser::MOS6502::OffsetMapper(file.starting_address), entry_points);
|
||||||
|
|
||||||
int basic10_score = Basic10Score(disassembly);
|
int basic10_score = Basic10Score(disassembly);
|
||||||
int basic11_score = Basic11Score(disassembly);
|
int basic11_score = Basic11Score(disassembly);
|
||||||
|
@ -27,6 +27,7 @@ enum class Vic20MemoryModel {
|
|||||||
|
|
||||||
enum class Atari2600PagingModel {
|
enum class Atari2600PagingModel {
|
||||||
None,
|
None,
|
||||||
|
CommaVid,
|
||||||
Atari8k,
|
Atari8k,
|
||||||
Atari16k,
|
Atari16k,
|
||||||
Atari32k,
|
Atari32k,
|
||||||
|
Loading…
Reference in New Issue
Block a user