diff --git a/StaticAnalyser/Atari/StaticAnalyser.cpp b/StaticAnalyser/Atari/StaticAnalyser.cpp index 231b40e6b..abce4327d 100644 --- a/StaticAnalyser/Atari/StaticAnalyser.cpp +++ b/StaticAnalyser/Atari/StaticAnalyser.cpp @@ -8,6 +8,8 @@ #include "StaticAnalyser.hpp" +#include "../Disassembler/Disassembler6502.hpp" + using namespace StaticAnalyser::Atari; void StaticAnalyser::Atari::AddTargets( @@ -24,5 +26,31 @@ void StaticAnalyser::Atari::AddTargets( target.disks = disks; target.tapes = tapes; target.cartridges = cartridges; + target.atari.paging_model = Atari2600PagingModel::None; + + // try to figure out the paging scheme +/* if(!cartridges.empty()) + { + const std::list &segments = cartridges.front()->get_segments(); + if(segments.size() == 1) + { + uint16_t entry_address, break_address; + const Storage::Cartridge::Cartridge::Segment &segment = segments.front(); + if(segment.data.size() < 4096) + { + 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); + printf("%p", &disassembly); + } + }*/ + destination.push_back(target); } diff --git a/StaticAnalyser/Disassembler/Disassembler6502.cpp b/StaticAnalyser/Disassembler/Disassembler6502.cpp index 3b773f10e..bb50ddf33 100644 --- a/StaticAnalyser/Disassembler/Disassembler6502.cpp +++ b/StaticAnalyser/Disassembler/Disassembler6502.cpp @@ -16,9 +16,9 @@ struct PartialDisassembly { std::vector remaining_entry_points; }; -static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector &memory, uint16_t start_address, uint16_t entry_point) +static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector &memory, uint16_t start_address, uint16_t entry_point, uint16_t address_mask) { - uint16_t address = entry_point; + uint16_t address = entry_point & address_mask; while(1) { uint16_t local_address = address - start_address; @@ -26,7 +26,7 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector< struct Instruction instruction; instruction.address = address; - address++; + address = (address + 1) & address_mask; // get operation uint8_t operation = memory[local_address]; @@ -250,7 +250,7 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector< if(operand_address >= memory.size()-1) return; address += 2; - instruction.operand = memory[operand_address] | (uint16_t)(memory[operand_address+1] << 8); + instruction.operand = memory[operand_address] | (uint16_t)(memory[operand_address + 1] << 8); } break; } @@ -259,7 +259,7 @@ 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.operand < start_address || instruction.operand >= start_address + memory.size())) + if((instruction.addressing_mode == Instruction::Absolute || instruction.addressing_mode == Instruction::ZeroPage) && (instruction.operand < start_address || instruction.operand >= start_address + memory.size())) { if( instruction.operation == Instruction::STY || instruction.operation == Instruction::STX || @@ -276,23 +276,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::JSR) { - disassembly.remaining_entry_points.push_back(instruction.operand); + disassembly.remaining_entry_points.push_back(instruction.operand & address_mask); } if(instruction.operation == Instruction::JMP) { if(instruction.addressing_mode == Instruction::Absolute) - disassembly.remaining_entry_points.push_back(instruction.operand); + disassembly.remaining_entry_points.push_back(instruction.operand & address_mask); return; } if(instruction.addressing_mode == Instruction::Relative) { uint16_t destination = (uint16_t)(address + (int8_t)instruction.operand); - disassembly.remaining_entry_points.push_back(destination); + disassembly.remaining_entry_points.push_back(destination & address_mask); } } } -Disassembly StaticAnalyser::MOS6502::Disassemble(const std::vector &memory, uint16_t start_address, std::vector entry_points) +Disassembly StaticAnalyser::MOS6502::Disassemble(const std::vector &memory, uint16_t start_address, std::vector entry_points, uint16_t address_mask) { PartialDisassembly partialDisassembly; partialDisassembly.remaining_entry_points = entry_points; @@ -300,7 +300,7 @@ Disassembly StaticAnalyser::MOS6502::Disassemble(const std::vector &mem while(!partialDisassembly.remaining_entry_points.empty()) { // pull the next entry point from the back of the vector - uint16_t next_entry_point = partialDisassembly.remaining_entry_points.back(); + uint16_t next_entry_point = partialDisassembly.remaining_entry_points.back() & address_mask; partialDisassembly.remaining_entry_points.pop_back(); // if that address has already bene visited, forget about it @@ -310,7 +310,7 @@ Disassembly StaticAnalyser::MOS6502::Disassemble(const std::vector &mem if(next_entry_point < start_address || next_entry_point >= start_address + memory.size()) partialDisassembly.disassembly.outward_calls.insert(next_entry_point); else - AddToDisassembly(partialDisassembly, memory, start_address, next_entry_point); + AddToDisassembly(partialDisassembly, memory, start_address, next_entry_point, address_mask); } return std::move(partialDisassembly.disassembly); diff --git a/StaticAnalyser/Disassembler/Disassembler6502.hpp b/StaticAnalyser/Disassembler/Disassembler6502.hpp index 139542777..aff96ba63 100644 --- a/StaticAnalyser/Disassembler/Disassembler6502.hpp +++ b/StaticAnalyser/Disassembler/Disassembler6502.hpp @@ -67,7 +67,7 @@ struct Disassembly { std::set external_stores, external_loads, external_modifies; }; -Disassembly Disassemble(const std::vector &memory, uint16_t start_address, std::vector entry_points); +Disassembly Disassemble(const std::vector &memory, uint16_t start_address, std::vector entry_points, uint16_t address_mask = 0xffff); } } diff --git a/StaticAnalyser/StaticAnalyser.hpp b/StaticAnalyser/StaticAnalyser.hpp index ffef83a23..1aabae662 100644 --- a/StaticAnalyser/StaticAnalyser.hpp +++ b/StaticAnalyser/StaticAnalyser.hpp @@ -25,6 +25,16 @@ enum class Vic20MemoryModel { ThirtyTwoKB }; +enum class Atari2600PagingModel { + None, + Atari8k, + Atari16k, + Atari32k, + ActivisionStack, + ParkerBros, + Tigervision +}; + /*! A list of disks, tapes and cartridges plus information about the machine to which to attach them and its configuration, and instructions on how to launch the software attached, plus a measure of confidence in this target's correctness. @@ -39,21 +49,25 @@ struct Target { float probability; union { - struct { - Vic20MemoryModel memory_model; - bool has_c1540; - } vic20; - struct { bool has_adfs; bool has_dfs; bool should_shift_restart; } acorn; + struct { + Atari2600PagingModel paging_model; + } atari; + struct { bool use_atmos_rom; bool has_microdisc; } oric; + + struct { + Vic20MemoryModel memory_model; + bool has_c1540; + } vic20; }; std::string loadingCommand;