diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index e1a7b993c..76eedc4cd 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -269,10 +269,39 @@ void Machine::set_prg(const char *file_name, size_t length, const uint8_t *data) #pragma mar - Tape +void Machine::configure_as_target(const StaticAnalyser::Target &target) +{ + if(target.tapes.size()) + { + _tape.set_tape(target.tapes.front()); + } + + if(_should_automatically_load_media) + { + if(target.loadingCommand.length()) // TODO: and automatic loading option enabled + { + set_typer_for_string(target.loadingCommand.c_str()); + } + + switch(target.vic20.memory_model) + { + case StaticAnalyser::Vic20MemoryModel::Unexpanded: + set_memory_size(Default); + break; + case StaticAnalyser::Vic20MemoryModel::EightKB: + set_memory_size(ThreeKB); + break; + case StaticAnalyser::Vic20MemoryModel::ThirtyTwoKB: + set_memory_size(ThirtyTwoKB); + break; + } + } +} + void Machine::set_tape(std::shared_ptr tape) { - _tape.set_tape(tape); - if(_should_automatically_load_media) set_typer_for_string("LOAD\nRUN\n"); +// _tape.set_tape(tape); +// if(_should_automatically_load_media) set_typer_for_string("LOAD\nRUN\n"); } void Machine::tape_did_change_input(Tape *tape) diff --git a/Machines/Commodore/Vic-20/Vic20.hpp b/Machines/Commodore/Vic-20/Vic20.hpp index 59fec787b..8e6fe001b 100644 --- a/Machines/Commodore/Vic-20/Vic20.hpp +++ b/Machines/Commodore/Vic-20/Vic20.hpp @@ -21,6 +21,7 @@ #include "../../../Storage/Tape/Tape.hpp" #include "../../../Storage/Disk/Disk.hpp" +#include "../../../StaticAnalyser/StaticAnalyser.hpp" namespace Commodore { namespace Vic20 { @@ -260,6 +261,7 @@ class Machine: ~Machine(); void set_rom(ROMSlot slot, size_t length, const uint8_t *data); + void configure_as_target(const StaticAnalyser::Target &target); void set_prg(const char *file_name, size_t length, const uint8_t *data); void set_tape(std::shared_ptr tape); void set_disk(std::shared_ptr disk); diff --git a/OSBindings/Mac/Clock Signal/Documents/Vic20Document.swift b/OSBindings/Mac/Clock Signal/Documents/Vic20Document.swift index 6eb656b3b..a45cc8919 100644 --- a/OSBindings/Mac/Clock Signal/Documents/Vic20Document.swift +++ b/OSBindings/Mac/Clock Signal/Documents/Vic20Document.swift @@ -41,6 +41,10 @@ class Vic20Document: MachineDocument { return "Vic20Document" } + override func configureAs(analysis: CSStaticAnalyser) { + analysis.applyToMachine(vic20) + } + override func readFromURL(url: NSURL, ofType typeName: String) throws { if let pathExtension = url.pathExtension { switch pathExtension.lowercaseString { diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm index 7198aafe7..9dad2a4a7 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm @@ -46,6 +46,12 @@ using namespace Commodore::Vic20; [self setROM:rom slot:Drive]; } +- (void)applyTarget:(StaticAnalyser::Target)target { + @synchronized(self) { + _vic20.configure_as_target(target); + } +} + - (BOOL)openTAPAtURL:(NSURL *)URL { @synchronized(self) { try { diff --git a/StaticAnalyser/Commodore/CommodoreAnalyser.cpp b/StaticAnalyser/Commodore/CommodoreAnalyser.cpp index 7fce5cf3c..ce9890f20 100644 --- a/StaticAnalyser/Commodore/CommodoreAnalyser.cpp +++ b/StaticAnalyser/Commodore/CommodoreAnalyser.cpp @@ -36,12 +36,74 @@ void StaticAnalyser::Commodore::AddTargets( // continue if there are any files if(files.size()) { - // TODO: decide between ,1 (don't relocate; for machine code) and ,0 (relocate; for BASIC) - // TODO: decide memory model (based on extents and sizes) - // TODO: decide machine (disassemble?) + bool is_basic = true; + + // decide whether this is a BASIC file based on the proposition that: + // (1) they're always relocatable; and + // (2) they have a per-line structure of: + // [4 bytes: address of start of next line] + // [4 bytes: this line number] + // ... null-terminated code ... + // (with a next line address of 0000 indicating end of program)ß + if(files.front().type != File::RelocatableProgram) is_basic = false; + else + { + uint16_t line_address = 0; + int line_number = -1; + + uint16_t starting_address = files.front().starting_address; + line_address = starting_address; + is_basic = false; + while(1) + { + if(line_address - starting_address >= files.front().data.size() + 2) break; + + uint16_t next_line_address = files.front().data[line_address - starting_address]; + next_line_address |= files.front().data[line_address - starting_address + 1] << 8; + + if(!next_line_address) + { + is_basic = true; + break; + } + if(next_line_address < line_address + 5) break; + + if(line_address - starting_address >= files.front().data.size() + 5) break; + uint16_t next_line_number = files.front().data[line_address - starting_address + 2]; + next_line_number |= files.front().data[line_address - starting_address + 3] << 8; + + if(next_line_number <= line_number) break; + + line_number = (uint16_t)next_line_number; + line_address = next_line_address; + } + } + + target.vic20.memory_model = Vic20MemoryModel::Unexpanded; + if(is_basic) + { + target.loadingCommand = "LOAD\"\",1,0\nRUN\n"; + switch(files.front().starting_address) + { + case 0x1001: + default: break; + case 0x1201: + target.vic20.memory_model = Vic20MemoryModel::ThirtyTwoKB; + break; + case 0x0401: + target.vic20.memory_model = Vic20MemoryModel::EightKB; + break; + } + } + else + { + // TODO: this is machine code. So, ummm? + } + + target.tapes = tapes; } } if(target.tapes.size() || target.cartridges.size() || target.disks.size()) destination.push_back(target); -} \ No newline at end of file +} diff --git a/StaticAnalyser/StaticAnalyser.hpp b/StaticAnalyser/StaticAnalyser.hpp index 1e3b59a22..691d5e364 100644 --- a/StaticAnalyser/StaticAnalyser.hpp +++ b/StaticAnalyser/StaticAnalyser.hpp @@ -19,6 +19,12 @@ namespace StaticAnalyser { +enum class Vic20MemoryModel { + Unexpanded, + EightKB, + ThirtyTwoKB +}; + /*! 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. @@ -33,11 +39,7 @@ struct Target { union { struct { - enum class Vic20 { - Unexpanded, - EightKB, - ThirtyTwoKB - } memoryModel; + Vic20MemoryModel memory_model; bool has_c1540; } vic20;