From ff49857f5c4ce1bd9437fbf54cdc6457a5f84d06 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 10 Jul 2016 10:17:53 -0400 Subject: [PATCH] Started sketching out support for the G64 file format. --- .../Clock Signal.xcodeproj/project.pbxproj | 14 +++ Storage/Disk/Formats/G64.cpp | 91 +++++++++++++++++++ Storage/Disk/Formats/G64.hpp | 41 +++++++++ 3 files changed, 146 insertions(+) create mode 100644 Storage/Disk/Formats/G64.cpp create mode 100644 Storage/Disk/Formats/G64.hpp diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 69ac802b5..36ad78477 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ 4B73C71D1D036C030074D992 /* Vic20Document.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B73C71B1D036C030074D992 /* Vic20Document.xib */; }; 4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */; }; 4BAB62AD1D3272D200DF5BA0 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */; }; + 4BAB62B51D327F7E00DF5BA0 /* G64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB62B31D327F7E00DF5BA0 /* G64.cpp */; }; 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 */; }; 4BB298F11B587D8400A49093 /* start in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E51B587D8300A49093 /* start */; }; @@ -419,6 +420,8 @@ 4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Disk.cpp; sourceTree = ""; }; 4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Disk.hpp; sourceTree = ""; }; 4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = ""; }; + 4BAB62B31D327F7E00DF5BA0 /* G64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = G64.cpp; sourceTree = ""; }; + 4BAB62B41D327F7E00DF5BA0 /* G64.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = G64.hpp; sourceTree = ""; }; 4BB297E01B587D8300A49093 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = ""; }; 4BB297E11B587D8300A49093 /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = AllSuiteA.bin; sourceTree = ""; }; 4BB297E51B587D8300A49093 /* start */ = {isa = PBXFileReference; lastKnownFileType = file; path = " start"; sourceTree = ""; }; @@ -978,12 +981,22 @@ 4BAB62AA1D3272D200DF5BA0 /* Disk */ = { isa = PBXGroup; children = ( + 4BAB62B21D327F7E00DF5BA0 /* Formats */, 4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */, 4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */, ); path = Disk; sourceTree = ""; }; + 4BAB62B21D327F7E00DF5BA0 /* Formats */ = { + isa = PBXGroup; + children = ( + 4BAB62B31D327F7E00DF5BA0 /* G64.cpp */, + 4BAB62B41D327F7E00DF5BA0 /* G64.hpp */, + ); + path = Formats; + sourceTree = ""; + }; 4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */ = { isa = PBXGroup; children = ( @@ -1850,6 +1863,7 @@ 4B2A53A11D117D36003C6002 /* CSAtari2600.mm in Sources */, 4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */, 4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */, + 4BAB62B51D327F7E00DF5BA0 /* G64.cpp in Sources */, 4BBF99141C8FBA6F0075DAFB /* CRTInputBufferBuilder.cpp in Sources */, 4B2409551C45AB05004DA684 /* Speaker.cpp in Sources */, 4B4DC8281D2C2470003C5BF8 /* C1540.cpp in Sources */, diff --git a/Storage/Disk/Formats/G64.cpp b/Storage/Disk/Formats/G64.cpp new file mode 100644 index 000000000..15bfd98a3 --- /dev/null +++ b/Storage/Disk/Formats/G64.cpp @@ -0,0 +1,91 @@ +// +// G64.cpp +// Clock Signal +// +// Created by Thomas Harte on 10/07/2016. +// Copyright © 2016 Thomas Harte. All rights reserved. +// + +#include "G64.hpp" + +using namespace Storage; + +G64::G64(const char *file_name) +{ + _file = fopen(file_name, "rb"); + + if(!_file) + throw ErrorNotGCR; + + // read and check the file signature + char signature[8]; + if(fread(signature, 1, 8, _file) != 12) + throw ErrorNotGCR; + + if(memcmp(signature, "GCR-1541", 8)) + throw ErrorNotGCR; + + // check the version number + int version = fgetc(_file); + if(version != 0) + { + throw ErrorUnknownVersion; + } + + // get the number of tracks and track size + _number_of_tracks = (uint8_t)fgetc(_file); + _maximum_track_size = (uint16_t)fgetc(_file); + _maximum_track_size |= (uint16_t)fgetc(_file) << 8; +} + +G64::~G64() +{ + if(_file) fclose(_file); +} + +unsigned int G64::get_head_position_count() +{ + // give at least 84 tracks, to yield the normal geometry but, + // if there are more, shove them in + return _number_of_tracks > 84 ? _number_of_tracks : 84; +} + +std::shared_ptr G64::get_track_at_position(unsigned int position) +{ + std::shared_ptr resulting_track; + + // if there's definitely no track here, return the empty track + // (TODO: should be supplying one with an index hole?) + if(position >= _number_of_tracks) return resulting_track; + + // seek to this track's entry in the track table + fseek(_file, SEEK_SET, (int)((position * 4) + 0xc)); + + // read the track offset + uint32_t track_offset; + track_offset = (uint32_t)fgetc(_file); + track_offset |= (uint32_t)fgetc(_file) << 8; + track_offset |= (uint32_t)fgetc(_file) << 16; + track_offset |= (uint32_t)fgetc(_file) << 24; + + // if the track offset is zero, this track doesn't exist, so... + if(!track_offset) return resulting_track; + + // seek to the track start + fseek(_file, SEEK_SET, (int)track_offset); + + // get the real track length + uint16_t track_length; + track_length = (uint16_t)fgetc(_file); + track_length |= (uint16_t)fgetc(_file) << 8; + + // grab the byte contents of this track + uint8_t track_contents[track_length]; + fread(track_contents, 1, track_length, _file); + + // check for speed-zone contents + + // TODO: package track_contents and speed_zones into a PCM track + + return resulting_track; +} diff --git a/Storage/Disk/Formats/G64.hpp b/Storage/Disk/Formats/G64.hpp new file mode 100644 index 000000000..0a6aa2c96 --- /dev/null +++ b/Storage/Disk/Formats/G64.hpp @@ -0,0 +1,41 @@ +// +// G64.hpp +// Clock Signal +// +// Created by Thomas Harte on 10/07/2016. +// Copyright © 2016 Thomas Harte. All rights reserved. +// + +#ifndef G64_hpp +#define G64_hpp + +#include "../Disk.hpp" + +namespace Storage { + +class PCMTrack: public Track { +}; + +class G64: public Disk { + public: + G64(const char *file_name); + ~G64(); + + enum { + ErrorNotGCR, + ErrorUnknownVersion + }; + + unsigned int get_head_position_count(); + std::shared_ptr get_track_at_position(unsigned int position); + + private: + FILE *_file; + + uint8_t _number_of_tracks; + uint16_t _maximum_track_size; +}; + +}; + +#endif /* G64_hpp */