mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Wired up enough such that some basic attempt at parsing a UEF occurs.`
This commit is contained in:
parent
2779f0e569
commit
5a39e42413
@ -27,6 +27,7 @@
|
||||
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */; };
|
||||
4B69FB3D1C4D908A00B5F0AA /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB3B1C4D908A00B5F0AA /* Tape.cpp */; };
|
||||
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; };
|
||||
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; };
|
||||
4B92EACA1B7C112B00246143 /* TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* TimingTests.swift */; };
|
||||
4BB298EE1B587D8400A49093 /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E01B587D8300A49093 /* 6502_functional_test.bin */; };
|
||||
4BB298EF1B587D8400A49093 /* AllSuiteA.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E11B587D8300A49093 /* AllSuiteA.bin */; };
|
||||
@ -361,6 +362,7 @@
|
||||
4B69FB3C1C4D908A00B5F0AA /* Tape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Tape.hpp; sourceTree = "<group>"; };
|
||||
4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TapeUEF.cpp; sourceTree = "<group>"; };
|
||||
4B69FB431C4D941400B5F0AA /* TapeUEF.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TapeUEF.hpp; sourceTree = "<group>"; };
|
||||
4B69FB451C4D950F00B5F0AA /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
4B92EAC91B7C112B00246143 /* TimingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimingTests.swift; sourceTree = "<group>"; };
|
||||
4BAE587D1C447B7A005B9AF0 /* KeyCodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyCodes.h; sourceTree = "<group>"; };
|
||||
4BB297DF1B587D8200A49093 /* Clock SignalTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Clock SignalTests-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
@ -655,6 +657,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -796,6 +799,7 @@
|
||||
4B69FB411C4D941400B5F0AA /* Formats */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B69FB451C4D950F00B5F0AA /* libz.tbd */,
|
||||
4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */,
|
||||
4B69FB431C4D941400B5F0AA /* TapeUEF.hpp */,
|
||||
);
|
||||
|
@ -39,10 +39,11 @@ class ElectronDocument: MachineDocument {
|
||||
print(url)
|
||||
print(typeName)
|
||||
switch typeName {
|
||||
case "Electron/BBC Tape Image": // this somewhat implies I've misunderstood the info.plist, doesn't it?
|
||||
electron.openUEFAtURL(url)
|
||||
default:
|
||||
let fileWrapper = try NSFileWrapper(URL: url, options: NSFileWrapperReadingOptions(rawValue: 0))
|
||||
try self.readFromFileWrapper(fileWrapper, ofType: typeName)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
- (void)setOSROM:(nonnull NSData *)rom;
|
||||
- (void)setBASICROM:(nonnull NSData *)rom;
|
||||
- (void)setROM:(nonnull NSData *)rom slot:(int)slot;
|
||||
- (void)openUEFAtURL:(NSURL *)URL;
|
||||
|
||||
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#import "Electron.hpp"
|
||||
#import "CSMachine+Subclassing.h"
|
||||
#import "TapeUEF.hpp"
|
||||
|
||||
@implementation CSElectron {
|
||||
Electron::Machine _electron;
|
||||
@ -47,6 +48,11 @@
|
||||
_electron.get_crt()->set_delegate(delegate);
|
||||
}
|
||||
|
||||
- (void)openUEFAtURL:(NSURL *)URL {
|
||||
Storage::UEF tape([URL fileSystemRepresentation]);
|
||||
// _electron.
|
||||
}
|
||||
|
||||
- (BOOL)setSpeakerDelegate:(Outputs::Speaker::Delegate *)delegate sampleRate:(int)sampleRate {
|
||||
_electron.get_speaker()->set_output_rate(sampleRate, 512);
|
||||
_electron.get_speaker()->set_output_quality(15);
|
||||
|
@ -7,3 +7,97 @@
|
||||
//
|
||||
|
||||
#include "TapeUEF.hpp"
|
||||
#include <string.h>
|
||||
|
||||
Storage::UEF::UEF(const char *file_name) :
|
||||
_chunk_id(0), _chunk_length(0), _chunk_position(0),
|
||||
_time_base(1200)
|
||||
{
|
||||
_file = gzopen(file_name, "rb");
|
||||
|
||||
char identifier[10];
|
||||
int bytes_read = gzread(_file, identifier, 10);
|
||||
if(bytes_read < 10 || strcmp(identifier, "UEF File!"))
|
||||
{
|
||||
// exception?
|
||||
}
|
||||
|
||||
int minor, major;
|
||||
minor = gzgetc(_file);
|
||||
major = gzgetc(_file);
|
||||
|
||||
if(major > 0 || minor > 10 || major < 0 || minor < 0)
|
||||
{
|
||||
// exception?
|
||||
}
|
||||
|
||||
find_next_tape_chunk();
|
||||
}
|
||||
|
||||
Storage::UEF::~UEF()
|
||||
{
|
||||
gzclose(_file);
|
||||
}
|
||||
|
||||
void Storage::UEF::reset()
|
||||
{
|
||||
gzseek(_file, 12, SEEK_SET);
|
||||
}
|
||||
|
||||
Storage::Tape::Pulse Storage::UEF::get_next_pulse()
|
||||
{
|
||||
Pulse next_pulse;
|
||||
|
||||
return next_pulse;
|
||||
}
|
||||
|
||||
void Storage::UEF::find_next_tape_chunk()
|
||||
{
|
||||
int reset_count = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
// read chunk ID
|
||||
_chunk_id = (uint16_t)gzgetc(_file);
|
||||
_chunk_id |= (uint16_t)(gzgetc(_file) << 8);
|
||||
|
||||
_chunk_length = (uint32_t)(gzgetc(_file) << 0);
|
||||
_chunk_length |= (uint32_t)(gzgetc(_file) << 8);
|
||||
_chunk_length |= (uint32_t)(gzgetc(_file) << 16);
|
||||
_chunk_length |= (uint32_t)(gzgetc(_file) << 24);
|
||||
|
||||
printf("%04x: %d\n", _chunk_id, _chunk_length);
|
||||
|
||||
if (gzeof(_file))
|
||||
{
|
||||
reset_count++;
|
||||
if(reset_count == 2) break;
|
||||
reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_chunk_id)
|
||||
{
|
||||
case 0x0100: case 0x0102: // implicit and explicit bit patterns
|
||||
case 0x0112: case 0x0116: // gaps
|
||||
return;
|
||||
|
||||
case 0x0110: // carrier tone
|
||||
// TODO: read length
|
||||
return;
|
||||
case 0x0111: // carrier tone with dummy byte
|
||||
// TODO: read length
|
||||
return;
|
||||
case 0x0114: // security cycles
|
||||
// TODO: read number, Ps and Ws
|
||||
break;
|
||||
|
||||
case 0x113: // change of base rate
|
||||
break;
|
||||
|
||||
default:
|
||||
gzseek(_file, _chunk_length, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,30 @@
|
||||
#define TapeUEF_hpp
|
||||
|
||||
#include "../Tape.hpp"
|
||||
#include <zlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class UEF : public Storage::Tape {
|
||||
namespace Storage {
|
||||
|
||||
class UEF : public Tape {
|
||||
public:
|
||||
UEF(const char *file_name);
|
||||
Cycle get_next_cycle();
|
||||
~UEF();
|
||||
|
||||
Pulse get_next_pulse();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
gzFile _file;
|
||||
unsigned int _time_base;
|
||||
|
||||
uint16_t _chunk_id;
|
||||
uint32_t _chunk_length;
|
||||
uint32_t _chunk_position;
|
||||
|
||||
void find_next_tape_chunk();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* TapeUEF_hpp */
|
||||
|
@ -20,14 +20,14 @@ class Tape {
|
||||
unsigned int length, clock_rate;
|
||||
};
|
||||
|
||||
struct Cycle {
|
||||
struct Pulse {
|
||||
enum {
|
||||
High, Low, Zero
|
||||
} type;
|
||||
Time length;
|
||||
};
|
||||
|
||||
virtual Cycle get_next_cycle() = 0;
|
||||
virtual Pulse get_next_pulse() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void seek(Time seek_time);
|
||||
|
Loading…
Reference in New Issue
Block a user