1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-26 09:29:45 +00:00

Sketched out just enough classes to get through the get-contents-into-memory step of static analysis.

This commit is contained in:
Thomas Harte 2016-08-28 12:20:40 -04:00
parent 24938326ac
commit d9f0065154
10 changed files with 184 additions and 51 deletions

View File

@ -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;

View File

@ -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,25 +60,19 @@ 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(...) {}\
}
// A26
if(!strcmp(lowercase_extension, "a26"))
{
}
// BIN
if(!strcmp(lowercase_extension, "bin"))
{
TryInsert(list, class, platforms) \
}
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
@ -97,10 +92,7 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
}
// ROM
if(!strcmp(lowercase_extension, "rom"))
{
}
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)
@ -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;
}

View File

@ -19,14 +19,16 @@
namespace StaticAnalyser {
enum Machine {
/*!
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 {
enum {
Atari2600,
Electron,
Vic20
};
struct Target {
Machine machine;
} 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);
}

View File

@ -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;
};
}
}

View 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)
{
}

View 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 */

View 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)
{
}

View 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 */

View File

@ -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));
}

View File

@ -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;
};
}