mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Sketched out just enough classes to get through the get-contents-into-memory step of static analysis.
This commit is contained in:
parent
24938326ac
commit
d9f0065154
@ -26,6 +26,8 @@
|
||||
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 */; };
|
||||
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 */; };
|
||||
@ -406,6 +408,10 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -1545,6 +1551,10 @@
|
||||
children = (
|
||||
4BEE0A6D1D72496600532C7B /* PRG.cpp */,
|
||||
4BEE0A6E1D72496600532C7B /* PRG.hpp */,
|
||||
4B37EE7D1D734596006A09A4 /* A26.cpp */,
|
||||
4B37EE7E1D734596006A09A4 /* A26.hpp */,
|
||||
4B37EE801D7345A6006A09A4 /* AcornROM.cpp */,
|
||||
4B37EE811D7345A6006A09A4 /* AcornROM.hpp */,
|
||||
);
|
||||
path = Formats;
|
||||
sourceTree = "<group>";
|
||||
@ -1972,6 +1982,7 @@
|
||||
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 */,
|
||||
@ -2010,6 +2021,7 @@
|
||||
4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */,
|
||||
4BC91B831D1F160E00884B76 /* CommodoreTAP.cpp in Sources */,
|
||||
4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */,
|
||||
4B37EE821D7345A6006A09A4 /* AcornROM.cpp in Sources */,
|
||||
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../Storage/Cartridge/Formats/A26.hpp"
|
||||
#include "../Storage/Cartridge/Formats/AcornROM.hpp"
|
||||
#include "../Storage/Cartridge/Formats/PRG.hpp"
|
||||
|
||||
#include "../Storage/Disk/Formats/D64.hpp"
|
||||
@ -26,7 +28,6 @@ enum class TargetPlatform: TargetPlatformType {
|
||||
Commodore = 1 << 2
|
||||
};
|
||||
|
||||
|
||||
using namespace StaticAnalyser;
|
||||
|
||||
std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
|
||||
@ -59,27 +60,21 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
|
||||
list.emplace_back(new Storage::class(file_name));\
|
||||
potential_platforms |= (TargetPlatformType)(platforms);\
|
||||
|
||||
#define TryInsert(list, class, platforms) \
|
||||
try {\
|
||||
Insert(list, class, platforms) \
|
||||
} catch(...) {}
|
||||
|
||||
#define Format(extension, list, class, platforms) \
|
||||
if(!strcmp(lowercase_extension, extension)) \
|
||||
{ \
|
||||
try { \
|
||||
list.emplace_back(new Storage::class(file_name));\
|
||||
potential_platforms |= (TargetPlatformType)(platforms);\
|
||||
} catch(...) {}\
|
||||
TryInsert(list, class, platforms) \
|
||||
}
|
||||
|
||||
// A26
|
||||
if(!strcmp(lowercase_extension, "a26"))
|
||||
{
|
||||
}
|
||||
|
||||
// BIN
|
||||
if(!strcmp(lowercase_extension, "bin"))
|
||||
{
|
||||
}
|
||||
|
||||
Format("d64", disks, Disk::D64, TargetPlatform::Commodore) // D64
|
||||
Format("g64", disks, Disk::G64, TargetPlatform::Commodore) // G64
|
||||
Format("a26", cartridges, Cartridge::A26, TargetPlatform::Atari2600) // A26
|
||||
Format("bin", cartridges, Cartridge::A26, TargetPlatform::Atari2600) // BIN
|
||||
Format("d64", disks, Disk::D64, TargetPlatform::Commodore) // D64
|
||||
Format("g64", disks, Disk::G64, TargetPlatform::Commodore) // G64
|
||||
|
||||
// PRG
|
||||
if(!strcmp(lowercase_extension, "prg"))
|
||||
@ -97,12 +92,9 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
|
||||
}
|
||||
|
||||
// ROM
|
||||
if(!strcmp(lowercase_extension, "rom"))
|
||||
{
|
||||
}
|
||||
|
||||
Format("tap", tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP
|
||||
Format("uef", tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
||||
Format("rom", cartridges, Cartridge::AcornROM, TargetPlatform::Acorn) // ROM
|
||||
Format("tap", tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP
|
||||
Format("uef", tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
||||
|
||||
#undef Format
|
||||
#undef Insert
|
||||
@ -110,8 +102,6 @@ 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)
|
||||
|
||||
printf("Lowercase extension: %s", lowercase_extension);
|
||||
|
||||
free(lowercase_extension);
|
||||
return targets;
|
||||
}
|
||||
|
@ -19,14 +19,16 @@
|
||||
|
||||
namespace StaticAnalyser {
|
||||
|
||||
enum Machine {
|
||||
Atari2600,
|
||||
Electron,
|
||||
Vic20
|
||||
};
|
||||
|
||||
/*!
|
||||
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.
|
||||
*/
|
||||
struct Target {
|
||||
Machine machine;
|
||||
enum {
|
||||
Atari2600,
|
||||
Electron,
|
||||
Vic20
|
||||
} machine;
|
||||
float probability;
|
||||
|
||||
union {
|
||||
@ -59,6 +61,11 @@ struct Target {
|
||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
|
||||
};
|
||||
|
||||
/*!
|
||||
Attempts, through any available means, to return a list of potential targets for the file with the given name.
|
||||
|
||||
@returns The list of potential targets, sorted from most to least probable.
|
||||
*/
|
||||
std::list<Target> GetTargets(const char *file_name);
|
||||
|
||||
}
|
||||
|
@ -9,10 +9,53 @@
|
||||
#ifndef Storage_Cartridge_hpp
|
||||
#define Storage_Cartridge_hpp
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace Storage {
|
||||
namespace Cartridge {
|
||||
|
||||
class Cartridge {};
|
||||
/*!
|
||||
Provides a base class for cartridges; the bus provided to cartridges and therefore
|
||||
the interface they support is extremely machine-dependent so unlike disks and tapes,
|
||||
no model is imposed; this class seeks merely to be a base class for fully-descriptive
|
||||
summaries of the contents of emulator files that themselves describe cartridges.
|
||||
|
||||
Consumers will almost certainly seek to dynamic_cast to something more appropriate,
|
||||
however some cartridge container formats have no exposition beyond the ROM dump,
|
||||
making the base class 100% descriptive.
|
||||
*/
|
||||
class Cartridge {
|
||||
public:
|
||||
struct Segment {
|
||||
Segment(int start_address, int end_address, std::vector<uint8_t> data) :
|
||||
start_address(start_address), end_address(end_address), data(std::move(data)) {}
|
||||
|
||||
/// Indicates that an address is unknown.
|
||||
static const int UnknownAddress;
|
||||
|
||||
/// The initial CPU-exposed starting address for this segment; may be @c UnknownAddress.
|
||||
int start_address;
|
||||
/*!
|
||||
The initial CPU-exposed ending address for this segment; may be @c UnknownAddress. Not necessarily equal
|
||||
to start_address + data_length due to potential paging.
|
||||
*/
|
||||
int end_address;
|
||||
|
||||
/*!
|
||||
The data contents for this segment. If @c start_address and @c end_address are suppled then
|
||||
the first end_address - start_address bytes will be those initially visible. The size will
|
||||
not necessarily be the same as @c end_address - @c start_address due to potential paging.
|
||||
*/
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
const std::list<Segment> &get_segments() { return _segments; }
|
||||
|
||||
protected:
|
||||
std::list<Segment> _segments;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
15
Storage/Cartridge/Formats/A26.cpp
Normal file
15
Storage/Cartridge/Formats/A26.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
}
|
30
Storage/Cartridge/Formats/A26.hpp
Normal file
30
Storage/Cartridge/Formats/A26.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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 */
|
15
Storage/Cartridge/Formats/AcornROM.cpp
Normal file
15
Storage/Cartridge/Formats/AcornROM.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// AcornROM.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 28/08/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "AcornROM.hpp"
|
||||
|
||||
using namespace Storage::Cartridge;
|
||||
|
||||
AcornROM::AcornROM(const char *file_name)
|
||||
{
|
||||
}
|
29
Storage/Cartridge/Formats/AcornROM.hpp
Normal file
29
Storage/Cartridge/Formats/AcornROM.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
//
|
||||
// AcornROM.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
|
||||
|
||||
#include "../Cartridge.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Cartridge {
|
||||
|
||||
class AcornROM : public Cartridge {
|
||||
public:
|
||||
AcornROM(const char *file_name);
|
||||
|
||||
enum {
|
||||
ErrorNotAcornROM
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* AcornROM_hpp */
|
@ -13,7 +13,7 @@
|
||||
|
||||
using namespace Storage::Cartridge;
|
||||
|
||||
PRG::PRG(const char *file_name) : _contents(nullptr)
|
||||
PRG::PRG(const char *file_name)
|
||||
{
|
||||
struct stat file_stats;
|
||||
stat(file_name, &file_stats);
|
||||
@ -32,8 +32,9 @@ PRG::PRG(const char *file_name) : _contents(nullptr)
|
||||
int loading_address = fgetc(file);
|
||||
loading_address |= fgetc(file) << 8;
|
||||
|
||||
_contents = new uint8_t[file_stats.st_size - 2];
|
||||
fread(_contents, 1, (size_t)(file_stats.st_size - 2), file);
|
||||
size_t data_length = (size_t)file_stats.st_size - 2;
|
||||
std::vector<uint8_t> contents(data_length);
|
||||
fread(&contents[0], 1, (size_t)(data_length), file);
|
||||
fclose(file);
|
||||
|
||||
// accept only files intended to load at 0xa000
|
||||
@ -42,15 +43,12 @@ PRG::PRG(const char *file_name) : _contents(nullptr)
|
||||
|
||||
// also accept only cartridges with the proper signature
|
||||
if(
|
||||
_contents[4] != 0x41 ||
|
||||
_contents[5] != 0x30 ||
|
||||
_contents[6] != 0xc3 ||
|
||||
_contents[7] != 0xc2 ||
|
||||
_contents[8] != 0xcd)
|
||||
contents[4] != 0x41 ||
|
||||
contents[5] != 0x30 ||
|
||||
contents[6] != 0xc3 ||
|
||||
contents[7] != 0xc2 ||
|
||||
contents[8] != 0xcd)
|
||||
throw ErrorNotROM;
|
||||
}
|
||||
|
||||
PRG::~PRG()
|
||||
{
|
||||
delete[] _contents;
|
||||
_segments.emplace_back(0xa000, 0xa000 + data_length, std::move(contents));
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
#ifndef Storage_Cartridge_PRG_hpp
|
||||
#define Storage_Cartridge_PRG_hpp
|
||||
|
||||
#include <vector>
|
||||
#include "../Cartridge.hpp"
|
||||
|
||||
namespace Storage {
|
||||
@ -18,15 +17,10 @@ namespace Cartridge {
|
||||
class PRG : public Cartridge {
|
||||
public:
|
||||
PRG(const char *file_name);
|
||||
~PRG();
|
||||
|
||||
enum {
|
||||
ErrorNotROM
|
||||
};
|
||||
|
||||
private:
|
||||
uint8_t *_contents;
|
||||
uint16_t _size;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user