1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Wired up enough such that some basic attempt at parsing a UEF occurs.`

This commit is contained in:
Thomas Harte 2016-01-18 17:06:09 -06:00
parent 2779f0e569
commit 5a39e42413
7 changed files with 128 additions and 5 deletions

View File

@ -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 */,
);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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