From 2d75fbe1bfad5ed0cae19b34cd01ea937cc4e6ca Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 5 Dec 2023 10:46:06 -0500 Subject: [PATCH] Add nonfunctional FAT12 analyser. --- Analyser/Static/FAT12/StaticAnalyser.cpp | 138 ++++++++++++++++++ Analyser/Static/FAT12/StaticAnalyser.hpp | 22 +++ Analyser/Static/StaticAnalyser.cpp | 6 +- .../Clock Signal.xcodeproj/project.pbxproj | 16 ++ OSBindings/Qt/clksignal.pro | 2 + OSBindings/SDL/SConstruct | 1 + 6 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 Analyser/Static/FAT12/StaticAnalyser.cpp create mode 100644 Analyser/Static/FAT12/StaticAnalyser.hpp diff --git a/Analyser/Static/FAT12/StaticAnalyser.cpp b/Analyser/Static/FAT12/StaticAnalyser.cpp new file mode 100644 index 000000000..15014a9e0 --- /dev/null +++ b/Analyser/Static/FAT12/StaticAnalyser.cpp @@ -0,0 +1,138 @@ +// +// StaticAnalyser.cpp +// Clock Signal +// +// Created by Thomas Harte on 05/12/2023. +// Copyright 2023 Thomas Harte. All rights reserved. +// + +#include "StaticAnalyser.hpp" + +//#include "../AppleII/Target.hpp" +//#include "../AppleIIgs/Target.hpp" +//#include "../Oric/Target.hpp" +//#include "../Disassembler/6502.hpp" +//#include "../Disassembler/AddressMapper.hpp" + +#include "../../../Storage/Disk/Track/TrackSerialiser.hpp" +//#include "../../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp" + +//namespace { +// +//Analyser::Static::Target *AppleIITarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) { +// using Target = Analyser::Static::AppleII::Target; +// auto *const target = new Target; +// +// if(sector_zero && sector_zero->encoding == Storage::Encodings::AppleGCR::Sector::Encoding::FiveAndThree) { +// target->disk_controller = Target::DiskController::ThirteenSector; +// } else { +// target->disk_controller = Target::DiskController::SixteenSector; +// } +// +// return target; +//} +// +//Analyser::Static::Target *AppleIIgsTarget() { +// return new Analyser::Static::AppleIIgs::Target(); +//} +// +//Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *) { +// using Target = Analyser::Static::Oric::Target; +// auto *const target = new Target; +// target->rom = Target::ROM::Pravetz; +// target->disk_interface = Target::DiskInterface::Pravetz; +// target->loading_command = "CALL 800\n"; +// return target; +//} +// +//} + +Analyser::Static::TargetList Analyser::Static::FAT12::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) { + // This analyser can comprehend disks only. + if(media.disks.empty()) return {}; + +// auto &disk = media.disks.front(); + TargetList targets; + + // If the disk image is too large for a 5.25" disk, map this to the IIgs. +/* if(disk->get_maximum_head_position() > Storage::Disk::HeadPosition(40)) { + targets.push_back(std::unique_ptr(AppleIIgsTarget())); + targets.back()->media = media; + return targets; + } + + // Grab track 0, sector 0: the boot sector. + const auto track_zero = disk->get_track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0))); + const auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment( + Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000))); + + const Storage::Encodings::AppleGCR::Sector *sector_zero = nullptr; + for(const auto &pair: sector_map) { + if(!pair.second.address.sector) { + sector_zero = &pair.second; + break; + } + } + + // If there's no boot sector then if there are also no sectors at all, + // decline to nominate a machine. Otherwise go with an Apple as the default. + if(!sector_zero) { + if(sector_map.empty()) { + return targets; + } else { + targets.push_back(std::unique_ptr(AppleIITarget(nullptr))); + targets.back()->media = media; + return targets; + } + } + + // If the boot sector looks like it's intended for the Oric, create an Oric. + // Otherwise go with the Apple II. + + const auto disassembly = Analyser::Static::MOS6502::Disassemble(sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800}); + + bool did_read_shift_register = false; + bool is_oric = false; + + // Look for a tight BPL loop reading the Oric's shift register address of 0x31c. The Apple II just has RAM there, + // so the probability of such a loop is infinitesimal. + for(const auto &instruction: disassembly.instructions_by_address) { + // Is this a read of the shift register? + if( + ( + (instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDA) || + (instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDX) || + (instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDY) + ) && + instruction.second.addressing_mode == Analyser::Static::MOS6502::Instruction::Absolute && + instruction.second.address == 0x031c) { + did_read_shift_register = true; + continue; + } + + if(did_read_shift_register) { + if( + instruction.second.operation == Analyser::Static::MOS6502::Instruction::BPL && + instruction.second.address == 0xfb) { + is_oric = true; + break; + } + + did_read_shift_register = false; + } + } + + // Check also for calls into the 0x3xx page above 0x320, as that's where the Oric's boot ROM is. + for(const auto address: disassembly.outward_calls) { + is_oric |= address >= 0x320 && address < 0x400; + } + + if(is_oric) { + targets.push_back(std::unique_ptr(OricTarget(sector_zero))); + } else { + targets.push_back(std::unique_ptr(AppleIITarget(sector_zero))); + } + targets.back()->media = media;*/ + + return targets; +} diff --git a/Analyser/Static/FAT12/StaticAnalyser.hpp b/Analyser/Static/FAT12/StaticAnalyser.hpp new file mode 100644 index 000000000..eb672aee8 --- /dev/null +++ b/Analyser/Static/FAT12/StaticAnalyser.hpp @@ -0,0 +1,22 @@ +// +// StaticAnalyser.hpp +// Clock Signal +// +// Created by Thomas Harte on 05/12/2023. +// Copyright 2023 Thomas Harte. All rights reserved. +// + +#ifndef Analyser_Static_FAT12_StaticAnalyser_hpp +#define Analyser_Static_FAT12_StaticAnalyser_hpp + +#include "../StaticAnalyser.hpp" +#include "../../../Storage/TargetPlatforms.hpp" +#include + +namespace Analyser::Static::FAT12 { + +TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms); + +} + +#endif /* Analyser_Static_FAT12_StaticAnalyser_hpp */ diff --git a/Analyser/Static/StaticAnalyser.cpp b/Analyser/Static/StaticAnalyser.cpp index d0d91bbdf..1c57034ac 100644 --- a/Analyser/Static/StaticAnalyser.cpp +++ b/Analyser/Static/StaticAnalyser.cpp @@ -25,6 +25,7 @@ #include "Commodore/StaticAnalyser.hpp" #include "DiskII/StaticAnalyser.hpp" #include "Enterprise/StaticAnalyser.hpp" +#include "FAT12/StaticAnalyser.hpp" #include "Macintosh/StaticAnalyser.hpp" #include "MSX/StaticAnalyser.hpp" #include "Oric/StaticAnalyser.hpp" @@ -179,10 +180,10 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform:: Disk::DiskImageHolder, TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric | TargetPlatform::ZXSpectrum) // HFE (TODO: switch to AllDisk once the MSX stops being so greedy) - Format("ima", result.disks, Disk::DiskImageHolder, TargetPlatform::PCCompatible) // IMG (Enterprise/MS-DOS style) + Format("ima", result.disks, Disk::DiskImageHolder, TargetPlatform::PCCompatible) // IMG (MS-DOS style) Format("image", result.disks, Disk::DiskImageHolder, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2) Format("img", result.disks, Disk::DiskImageHolder, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2) - Format("img", result.disks, Disk::DiskImageHolder, TargetPlatform::Enterprise) // IMG (Enterprise/MS-DOS style) + Format("img", result.disks, Disk::DiskImageHolder, TargetPlatform::FAT12) // IMG (Enterprise or MS-DOS style) Format("img", result.disks, Disk::DiskImageHolder, TargetPlatform::PCCompatible) // IMG (PC raw booter) Format( "ipf", result.disks, @@ -290,6 +291,7 @@ TargetList Analyser::Static::GetTargets(const std::string &file_name) { Append(Commodore); Append(DiskII); Append(Enterprise); + Append(FAT12); Append(Macintosh); Append(MSX); Append(Oric); diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index b77825539..afd60578e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ 425739382B051EA800B7D1E4 /* PCCompatible.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 425739372B051EA800B7D1E4 /* PCCompatible.cpp */; }; 425739392B051EA800B7D1E4 /* PCCompatible.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 425739372B051EA800B7D1E4 /* PCCompatible.cpp */; }; 4281683A2A37AFB4008ECD27 /* DispatcherTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 428168392A37AFB4008ECD27 /* DispatcherTests.mm */; }; + 429B13602B1F7BDA006BB4CB /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 429B135F2B1F7BDA006BB4CB /* StaticAnalyser.cpp */; }; + 429B13612B1F7BDA006BB4CB /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 429B135F2B1F7BDA006BB4CB /* StaticAnalyser.cpp */; }; 42A5E80C2ABBE04600A0DD5D /* NeskellTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42A5E80B2ABBE04600A0DD5D /* NeskellTests.swift */; }; 42A5E8442ABBE16F00A0DD5D /* illegal_rmw_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 42A5E8332ABBE16F00A0DD5D /* illegal_rmw_test.bin */; }; 42A5E8452ABBE16F00A0DD5D /* arr_bcd_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 42A5E8342ABBE16F00A0DD5D /* arr_bcd_test.bin */; }; @@ -1164,6 +1166,8 @@ 4281572E2AA0334300E16AA1 /* Carry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Carry.hpp; sourceTree = ""; }; 428168372A16C25C008ECD27 /* LineLayout.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LineLayout.hpp; sourceTree = ""; }; 428168392A37AFB4008ECD27 /* DispatcherTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatcherTests.mm; sourceTree = ""; }; + 429B135E2B1F7BDA006BB4CB /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = ""; }; + 429B135F2B1F7BDA006BB4CB /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 42A5E80B2ABBE04600A0DD5D /* NeskellTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeskellTests.swift; sourceTree = ""; }; 42A5E8332ABBE16F00A0DD5D /* illegal_rmw_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = illegal_rmw_test.bin; sourceTree = ""; }; 42A5E8342ABBE16F00A0DD5D /* arr_bcd_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = arr_bcd_test.bin; sourceTree = ""; }; @@ -2402,6 +2406,15 @@ path = PCCompatible; sourceTree = ""; }; + 429B135D2B1F7BDA006BB4CB /* FAT12 */ = { + isa = PBXGroup; + children = ( + 429B135E2B1F7BDA006BB4CB /* StaticAnalyser.hpp */, + 429B135F2B1F7BDA006BB4CB /* StaticAnalyser.cpp */, + ); + path = FAT12; + sourceTree = ""; + }; 42A5E8322ABBE16F00A0DD5D /* Neskell Tests */ = { isa = PBXGroup; children = ( @@ -3605,6 +3618,7 @@ 4B894507201967B4007DE474 /* Disassembler */, 4BD67DC8209BE4D600AB2146 /* DiskII */, 4B051CA426781D6500CA44E8 /* Enterprise */, + 429B135D2B1F7BDA006BB4CB /* FAT12 */, 4BB4BFB622A4372E0069048D /* Macintosh */, 4B89450F201967B4007DE474 /* MSX */, 4B8944F6201967B4007DE474 /* Oric */, @@ -5866,6 +5880,7 @@ 4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */, 4B17B58C20A8A9D9007CCA8F /* StringSerialiser.cpp in Sources */, 4B055AA01FAE85DA0060FFFF /* MFMSectorDump.cpp in Sources */, + 429B13612B1F7BDA006BB4CB /* StaticAnalyser.cpp in Sources */, 4B1A1B1F27320FBC00119335 /* Disk.cpp in Sources */, 4BEBFB522002DB30000708CC /* DiskROM.cpp in Sources */, 4BC23A2D2467600F001A6030 /* OPLL.cpp in Sources */, @@ -6107,6 +6122,7 @@ 4B71368E1F788112008B8ED9 /* Parser.cpp in Sources */, 4B12C0ED1FCFA98D005BFD93 /* Keyboard.cpp in Sources */, 4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */, + 429B13602B1F7BDA006BB4CB /* StaticAnalyser.cpp in Sources */, 4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */, 4B051CA22676F52200CA44E8 /* Enterprise.cpp in Sources */, 4B7F1897215486A200388727 /* StaticAnalyser.cpp in Sources */, diff --git a/OSBindings/Qt/clksignal.pro b/OSBindings/Qt/clksignal.pro index c77ccee80..f121d8636 100644 --- a/OSBindings/Qt/clksignal.pro +++ b/OSBindings/Qt/clksignal.pro @@ -49,6 +49,7 @@ SOURCES += \ $$SRC/Analyser/Static/Disassembler/*.cpp \ $$SRC/Analyser/Static/DiskII/*.cpp \ $$SRC/Analyser/Static/Enterprise/*.cpp \ + $$SRC/Analyser/Static/FAT12/*.cpp \ $$SRC/Analyser/Static/Macintosh/*.cpp \ $$SRC/Analyser/Static/MSX/*.cpp \ $$SRC/Analyser/Static/Oric/*.cpp \ @@ -172,6 +173,7 @@ HEADERS += \ $$SRC/Analyser/Static/Disassembler/*.hpp \ $$SRC/Analyser/Static/DiskII/*.hpp \ $$SRC/Analyser/Static/Enterprise/*.hpp \ + $$SRC/Analyser/Static/FAT12/*.hpp \ $$SRC/Analyser/Static/Macintosh/*.hpp \ $$SRC/Analyser/Static/MSX/*.hpp \ $$SRC/Analyser/Static/Oric/*.hpp \ diff --git a/OSBindings/SDL/SConstruct b/OSBindings/SDL/SConstruct index af28fb3ef..f8c614a18 100644 --- a/OSBindings/SDL/SConstruct +++ b/OSBindings/SDL/SConstruct @@ -33,6 +33,7 @@ SOURCES += glob.glob('../../Analyser/Static/Commodore/*.cpp') SOURCES += glob.glob('../../Analyser/Static/Disassembler/*.cpp') SOURCES += glob.glob('../../Analyser/Static/DiskII/*.cpp') SOURCES += glob.glob('../../Analyser/Static/Enterprise/*.cpp') +SOURCES += glob.glob('../../Analyser/Static/FAT12/*.cpp') SOURCES += glob.glob('../../Analyser/Static/Macintosh/*.cpp') SOURCES += glob.glob('../../Analyser/Static/MSX/*.cpp') SOURCES += glob.glob('../../Analyser/Static/Oric/*.cpp')