mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Addressed my dithering here: the file format containers themselves should do nothing but inspect the data to find out whether it is of the correct format. The machine steps are there for machine-specific validation. So it's probably easier to treat a binary ROM image just as a binary ROM image. Therefore, the Acorn-specific .rom detection is now in an Acorn-specific area.
This commit is contained in:
parent
29c972f4b8
commit
d1abfc040c
@ -26,8 +26,7 @@
|
||||
4B2E2D951C399D1200138695 /* ElectronDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E2D931C399D1200138695 /* ElectronDocument.xib */; };
|
||||
4B2E2D9A1C3A06EC00138695 /* Atari2600.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D971C3A06EC00138695 /* Atari2600.cpp */; };
|
||||
4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D9B1C3A070400138695 /* Electron.cpp */; };
|
||||
4B37EE7F1D734596006A09A4 /* A26.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B37EE7D1D734596006A09A4 /* A26.cpp */; };
|
||||
4B37EE821D7345A6006A09A4 /* AcornROM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B37EE801D7345A6006A09A4 /* AcornROM.cpp */; };
|
||||
4B37EE821D7345A6006A09A4 /* BinaryDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B37EE801D7345A6006A09A4 /* BinaryDump.cpp */; };
|
||||
4B3BA0C31D318AEC005DD7A7 /* C1540Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0C21D318AEB005DD7A7 /* C1540Tests.swift */; };
|
||||
4B3BA0CE1D318B44005DD7A7 /* C1540Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0C61D318B44005DD7A7 /* C1540Bridge.mm */; };
|
||||
4B3BA0CF1D318B44005DD7A7 /* MOS6522Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0C91D318B44005DD7A7 /* MOS6522Bridge.mm */; };
|
||||
@ -341,6 +340,7 @@
|
||||
4BC9DF451D044FCA00F44158 /* ROMImages in Resources */ = {isa = PBXBuildFile; fileRef = 4BC9DF441D044FCA00F44158 /* ROMImages */; };
|
||||
4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9DF4D1D04691600F44158 /* 6560.cpp */; };
|
||||
4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */; };
|
||||
4BD14B111D74627C0088EAD6 /* AcornAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD14B0F1D74627C0088EAD6 /* AcornAnalyser.cpp */; };
|
||||
4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.m */; };
|
||||
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6A1D72496600532C7B /* Cartridge.cpp */; };
|
||||
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6D1D72496600532C7B /* PRG.cpp */; };
|
||||
@ -408,10 +408,8 @@
|
||||
4B2E2D991C3A06EC00138695 /* Atari2600Inputs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atari2600Inputs.h; sourceTree = "<group>"; };
|
||||
4B2E2D9B1C3A070400138695 /* Electron.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Electron.cpp; path = Electron/Electron.cpp; sourceTree = "<group>"; };
|
||||
4B2E2D9C1C3A070400138695 /* Electron.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Electron.hpp; path = Electron/Electron.hpp; sourceTree = "<group>"; };
|
||||
4B37EE7D1D734596006A09A4 /* A26.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = A26.cpp; sourceTree = "<group>"; };
|
||||
4B37EE7E1D734596006A09A4 /* A26.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = A26.hpp; sourceTree = "<group>"; };
|
||||
4B37EE801D7345A6006A09A4 /* AcornROM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AcornROM.cpp; sourceTree = "<group>"; };
|
||||
4B37EE811D7345A6006A09A4 /* AcornROM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AcornROM.hpp; sourceTree = "<group>"; };
|
||||
4B37EE801D7345A6006A09A4 /* BinaryDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BinaryDump.cpp; sourceTree = "<group>"; };
|
||||
4B37EE811D7345A6006A09A4 /* BinaryDump.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = BinaryDump.hpp; sourceTree = "<group>"; };
|
||||
4B3BA0C21D318AEB005DD7A7 /* C1540Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = C1540Tests.swift; sourceTree = "<group>"; };
|
||||
4B3BA0C51D318B44005DD7A7 /* C1540Bridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = C1540Bridge.h; sourceTree = "<group>"; };
|
||||
4B3BA0C61D318B44005DD7A7 /* C1540Bridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = C1540Bridge.mm; sourceTree = "<group>"; };
|
||||
@ -767,6 +765,8 @@
|
||||
4BC9DF4E1D04691600F44158 /* 6560.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6560.hpp; sourceTree = "<group>"; };
|
||||
4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6502InterruptTests.swift; sourceTree = "<group>"; };
|
||||
4BCA98C21D065CA20062F44C /* 6522.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6522.hpp; sourceTree = "<group>"; };
|
||||
4BD14B0F1D74627C0088EAD6 /* AcornAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AcornAnalyser.cpp; path = ../../StaticAnalyser/Acorn/AcornAnalyser.cpp; sourceTree = "<group>"; };
|
||||
4BD14B101D74627C0088EAD6 /* AcornAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = AcornAnalyser.hpp; path = ../../StaticAnalyser/Acorn/AcornAnalyser.hpp; sourceTree = "<group>"; };
|
||||
4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = "<group>"; };
|
||||
4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CSBestEffortUpdater.m; path = Updater/CSBestEffortUpdater.m; sourceTree = "<group>"; };
|
||||
4BEE0A6A1D72496600532C7B /* Cartridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cartridge.cpp; sourceTree = "<group>"; };
|
||||
@ -1519,6 +1519,15 @@
|
||||
path = 6560;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4BD14B121D7462810088EAD6 /* Acorn */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BD14B0F1D74627C0088EAD6 /* AcornAnalyser.cpp */,
|
||||
4BD14B101D74627C0088EAD6 /* AcornAnalyser.hpp */,
|
||||
);
|
||||
name = Acorn;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4BD5F1961D1352A000631CD1 /* Updater */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1551,10 +1560,8 @@
|
||||
children = (
|
||||
4BEE0A6D1D72496600532C7B /* PRG.cpp */,
|
||||
4BEE0A6E1D72496600532C7B /* PRG.hpp */,
|
||||
4B37EE7D1D734596006A09A4 /* A26.cpp */,
|
||||
4B37EE7E1D734596006A09A4 /* A26.hpp */,
|
||||
4B37EE801D7345A6006A09A4 /* AcornROM.cpp */,
|
||||
4B37EE811D7345A6006A09A4 /* AcornROM.hpp */,
|
||||
4B37EE801D7345A6006A09A4 /* BinaryDump.cpp */,
|
||||
4B37EE811D7345A6006A09A4 /* BinaryDump.hpp */,
|
||||
);
|
||||
path = Formats;
|
||||
sourceTree = "<group>";
|
||||
@ -1565,6 +1572,7 @@
|
||||
4BF1354A1D6D2C300054B2EA /* StaticAnalyser.cpp */,
|
||||
4BF1354B1D6D2C300054B2EA /* StaticAnalyser.hpp */,
|
||||
4BC830D21D6E7C6D0000A26F /* Commodore */,
|
||||
4BD14B121D7462810088EAD6 /* Acorn */,
|
||||
);
|
||||
name = StaticAnalyser;
|
||||
sourceTree = "<group>";
|
||||
@ -1979,10 +1987,10 @@
|
||||
4BAB62AD1D3272D200DF5BA0 /* Disk.cpp in Sources */,
|
||||
4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */,
|
||||
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */,
|
||||
4BD14B111D74627C0088EAD6 /* AcornAnalyser.cpp in Sources */,
|
||||
4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */,
|
||||
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,
|
||||
4BB697C71D4B558F00248BDF /* Factors.cpp in Sources */,
|
||||
4B37EE7F1D734596006A09A4 /* A26.cpp in Sources */,
|
||||
4B55CE591C3B7D360093A61B /* ElectronDocument.swift in Sources */,
|
||||
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
|
||||
4BC3B74F1CD194CC00F86E85 /* Shader.cpp in Sources */,
|
||||
@ -2021,7 +2029,7 @@
|
||||
4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */,
|
||||
4BC91B831D1F160E00884B76 /* CommodoreTAP.cpp in Sources */,
|
||||
4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */,
|
||||
4B37EE821D7345A6006A09A4 /* AcornROM.cpp in Sources */,
|
||||
4B37EE821D7345A6006A09A4 /* BinaryDump.cpp in Sources */,
|
||||
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -17,7 +17,7 @@
|
||||
- (void)setROM:(nonnull NSData *)rom slot:(int)slot;
|
||||
- (BOOL)openUEFAtURL:(nonnull NSURL *)URL;
|
||||
|
||||
- (void)analyse:(NSURL *)url;
|
||||
- (void)analyse:(nonnull NSURL *)url;
|
||||
|
||||
@property (nonatomic, assign) BOOL useFastLoadingHack;
|
||||
@property (nonatomic, assign) BOOL useTelevisionOutput;
|
||||
|
67
StaticAnalyser/Acorn/AcornAnalyser.cpp
Normal file
67
StaticAnalyser/Acorn/AcornAnalyser.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// AcornAnalyser.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "AcornAnalyser.hpp"
|
||||
|
||||
using namespace StaticAnalyser::Acorn;
|
||||
|
||||
static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
|
||||
AcornCartridgesFrom(const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges)
|
||||
{
|
||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> acorn_cartridges;
|
||||
|
||||
for(std::shared_ptr<Storage::Cartridge::Cartridge> cartridge : cartridges)
|
||||
{
|
||||
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridge->get_segments();
|
||||
|
||||
// only one mapped item is allowed
|
||||
if(segments.size() != 1) continue;
|
||||
|
||||
// which must be 16 kb in size
|
||||
Storage::Cartridge::Cartridge::Segment segment = segments.front();
|
||||
if(segment.data.size() != 0x4000) continue;
|
||||
|
||||
// is a copyright string present?
|
||||
uint8_t copyright_offset = segment.data[7];
|
||||
if(
|
||||
segment.data[copyright_offset] != 0x00 ||
|
||||
segment.data[copyright_offset+1] != 0x28 ||
|
||||
segment.data[copyright_offset+2] != 0x43 ||
|
||||
segment.data[copyright_offset+3] != 0x29
|
||||
) continue;
|
||||
|
||||
// is the language entry point valid?
|
||||
if(!(
|
||||
(segment.data[0] == 0x00 && segment.data[1] == 0x00 && segment.data[2] == 0x00) ||
|
||||
(segment.data[0] != 0x00 && segment.data[2] >= 0x80 && segment.data[2] < 0xc0)
|
||||
)) continue;
|
||||
|
||||
// is the service entry point valid?
|
||||
if(!(segment.data[5] >= 0x80 && segment.data[5] < 0xc0)) continue;
|
||||
|
||||
// probability of a random binary blob that isn't an Acorn ROM proceeding to here:
|
||||
// 1/(2^32) *
|
||||
// ( ((2^24)-1)/(2^24)*(1/4) + 1/(2^24) ) *
|
||||
// 1/4
|
||||
// = something very improbable — around 1/16th of 1 in 2^32, but not exactly.
|
||||
acorn_cartridges.push_back(cartridge);
|
||||
}
|
||||
|
||||
return acorn_cartridges;
|
||||
}
|
||||
|
||||
void StaticAnalyser::Acorn::AddTargets(
|
||||
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::Cartridge::Cartridge>> &cartridges,
|
||||
std::list<StaticAnalyser::Target> &destination)
|
||||
{
|
||||
// strip out inappropriate cartridges
|
||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> acornCartridges = AcornCartridgesFrom(cartridges);
|
||||
}
|
||||
|
27
StaticAnalyser/Acorn/AcornAnalyser.hpp
Normal file
27
StaticAnalyser/Acorn/AcornAnalyser.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// AcornAnalyser.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef AcornAnalyser_hpp
|
||||
#define AcornAnalyser_hpp
|
||||
|
||||
#include "../StaticAnalyser.hpp"
|
||||
|
||||
namespace StaticAnalyser {
|
||||
namespace Acorn {
|
||||
|
||||
void AddTargets(
|
||||
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::Cartridge::Cartridge>> &cartridges,
|
||||
std::list<Target> &destination
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* AcornAnalyser_hpp */
|
@ -10,13 +10,18 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../Storage/Cartridge/Formats/A26.hpp"
|
||||
#include "../Storage/Cartridge/Formats/AcornROM.hpp"
|
||||
// Analysers
|
||||
#include "Acorn/AcornAnalyser.hpp"
|
||||
|
||||
// Cartridges
|
||||
#include "../Storage/Cartridge/Formats/BinaryDump.hpp"
|
||||
#include "../Storage/Cartridge/Formats/PRG.hpp"
|
||||
|
||||
// Disks
|
||||
#include "../Storage/Disk/Formats/D64.hpp"
|
||||
#include "../Storage/Disk/Formats/G64.hpp"
|
||||
|
||||
// Tapes
|
||||
#include "../Storage/Tape/Formats/CommodoreTAP.hpp"
|
||||
#include "../Storage/Tape/Formats/TapePRG.hpp"
|
||||
#include "../Storage/Tape/Formats/TapeUEF.hpp"
|
||||
@ -71,8 +76,8 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
|
||||
TryInsert(list, class, platforms) \
|
||||
}
|
||||
|
||||
Format("a26", cartridges, Cartridge::A26, TargetPlatform::Atari2600) // A26
|
||||
Format("bin", cartridges, Cartridge::A26, TargetPlatform::Atari2600) // BIN
|
||||
Format("a26", cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26
|
||||
Format("bin", cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // BIN
|
||||
Format("d64", disks, Disk::D64, TargetPlatform::Commodore) // D64
|
||||
Format("g64", disks, Disk::G64, TargetPlatform::Commodore) // G64
|
||||
|
||||
@ -92,7 +97,7 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
|
||||
}
|
||||
|
||||
// ROM
|
||||
Format("rom", cartridges, Cartridge::AcornROM, TargetPlatform::Acorn) // ROM
|
||||
Format("rom", cartridges, Cartridge::BinaryDump, TargetPlatform::Acorn) // ROM
|
||||
Format("tap", tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP
|
||||
Format("uef", tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
||||
|
||||
@ -101,6 +106,10 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
|
||||
|
||||
// Hand off to platform-specific determination of whether these things are actually compatible and,
|
||||
// if so, how to load them. (TODO)
|
||||
if(potential_platforms & (TargetPlatformType)TargetPlatform::Acorn)
|
||||
{
|
||||
Acorn::AddTargets(disks, tapes, cartridges, targets);
|
||||
}
|
||||
|
||||
free(lowercase_extension);
|
||||
return targets;
|
||||
|
@ -7,3 +7,5 @@
|
||||
//
|
||||
|
||||
#include "Cartridge.hpp"
|
||||
|
||||
const int Storage::Cartridge::Cartridge::Segment::UnknownAddress = -1;
|
||||
|
@ -1,15 +0,0 @@
|
||||
//
|
||||
// A26.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 28/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "A26.hpp"
|
||||
|
||||
using namespace Storage::Cartridge;
|
||||
|
||||
A26::A26(const char *file_name)
|
||||
{
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
//
|
||||
// A26.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 28/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Storage_Cartridge_A26_hpp
|
||||
#define Storage_Cartridge_A26_hpp
|
||||
|
||||
#include "../Cartridge.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Cartridge {
|
||||
|
||||
class A26 : public Cartridge {
|
||||
public:
|
||||
A26(const char *file_name);
|
||||
|
||||
enum {
|
||||
ErrorNotAcornROM
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* A26_hpp */
|
@ -1,59 +0,0 @@
|
||||
//
|
||||
// AcornROM.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 28/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "AcornROM.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace Storage::Cartridge;
|
||||
|
||||
AcornROM::AcornROM(const char *file_name)
|
||||
{
|
||||
// the file should be exactly 16 kb
|
||||
struct stat file_stats;
|
||||
stat(file_name, &file_stats);
|
||||
if(file_stats.st_size != 0x4000) throw ErrorNotAcornROM;
|
||||
|
||||
// grab contents
|
||||
FILE *file = fopen(file_name, "rb");
|
||||
if(!file) throw ErrorNotAcornROM;
|
||||
size_t data_length = (size_t)file_stats.st_size;
|
||||
std::vector<uint8_t> contents(data_length);
|
||||
fread(&contents[0], 1, (size_t)(data_length), file);
|
||||
fclose(file);
|
||||
|
||||
// perform sanity checks...
|
||||
|
||||
// is a copyright string present?
|
||||
uint8_t copyright_offset = contents[7];
|
||||
if(
|
||||
contents[copyright_offset] != 0x00 ||
|
||||
contents[copyright_offset+1] != 0x28 ||
|
||||
contents[copyright_offset+2] != 0x43 ||
|
||||
contents[copyright_offset+3] != 0x29
|
||||
) throw ErrorNotAcornROM;
|
||||
|
||||
// is the language entry point valid?
|
||||
if(!(
|
||||
(contents[0] == 0x00 && contents[1] == 0x00 && contents[2] == 0x00) ||
|
||||
(contents[0] != 0x00 && contents[2] >= 0x80 && contents[2] < 0xc0)
|
||||
)) throw ErrorNotAcornROM;
|
||||
|
||||
// is the service entry point valid?
|
||||
if(!(contents[5] >= 0x80 && contents[5] < 0xc0)) throw ErrorNotAcornROM;
|
||||
|
||||
// probability of a random binary blob that isn't an Acorn ROM proceeding to here:
|
||||
// 1/(2^32) *
|
||||
// ( ((2^24)-1)/(2^24)*(1/4) + 1/(2^24) ) *
|
||||
// 1/4
|
||||
// = something very improbable — around 1/16th of 1 in 2^32, but not exactly.
|
||||
|
||||
// enshrine
|
||||
_segments.emplace_back(0x8000, 0xc000, std::move(contents));
|
||||
}
|
35
Storage/Cartridge/Formats/BinaryDump.cpp
Normal file
35
Storage/Cartridge/Formats/BinaryDump.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// BinaryDump.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 28/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BinaryDump.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace Storage::Cartridge;
|
||||
|
||||
BinaryDump::BinaryDump(const char *file_name)
|
||||
{
|
||||
// the file should be exactly 16 kb
|
||||
struct stat file_stats;
|
||||
stat(file_name, &file_stats);
|
||||
|
||||
// grab contents
|
||||
FILE *file = fopen(file_name, "rb");
|
||||
if(!file) throw ErrorNotAccessible;
|
||||
size_t data_length = (size_t)file_stats.st_size;
|
||||
std::vector<uint8_t> contents(data_length);
|
||||
fread(&contents[0], 1, (size_t)(data_length), file);
|
||||
fclose(file);
|
||||
|
||||
// enshrine
|
||||
_segments.emplace_back(
|
||||
::Storage::Cartridge::Cartridge::Segment::UnknownAddress,
|
||||
::Storage::Cartridge::Cartridge::Segment::UnknownAddress,
|
||||
std::move(contents));
|
||||
}
|
@ -1,25 +1,25 @@
|
||||
//
|
||||
// AcornROM.hpp
|
||||
// BinaryDump.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 28/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Storage_Cartridge_AcornROM_hpp
|
||||
#define Storage_Cartridge_AcornROM_hpp
|
||||
#ifndef Storage_Cartridge_BinaryDump_hpp
|
||||
#define Storage_Cartridge_BinaryDump_hpp
|
||||
|
||||
#include "../Cartridge.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Cartridge {
|
||||
|
||||
class AcornROM : public Cartridge {
|
||||
class BinaryDump : public Cartridge {
|
||||
public:
|
||||
AcornROM(const char *file_name);
|
||||
BinaryDump(const char *file_name);
|
||||
|
||||
enum {
|
||||
ErrorNotAcornROM
|
||||
ErrorNotAccessible
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user