1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Completed a first parse at the GCR parser, proving how incredibly slow my drive is.

This commit is contained in:
Thomas Harte 2016-09-15 07:54:42 -04:00
parent 9d6dcb80a7
commit 8992feb8cd
2 changed files with 97 additions and 19 deletions

View File

@ -9,6 +9,7 @@
#include "Disk.hpp"
#include "../../Storage/Disk/DiskDrive.hpp"
#include "../../Storage/Disk/Encodings/CommodoreGCR.hpp"
#include "Utilities.hpp"
#include <limits>
#include <vector>
@ -18,7 +19,11 @@ using namespace StaticAnalyser::Commodore;
class CommodoreGCRParser: public Storage::Disk::Drive {
public:
CommodoreGCRParser() : Storage::Disk::Drive(4000000, 4, 300), shift_register_(0) {}
CommodoreGCRParser() : Storage::Disk::Drive(4000000, 4, 300), shift_register_(0), track_(1)
{
// Make sure this drive really is at track '1'.
while(!get_is_track_zero()) step(-1);
}
struct Sector
{
@ -30,7 +35,24 @@ class CommodoreGCRParser: public Storage::Disk::Drive {
std::unique_ptr<Sector> get_sector(uint8_t track, uint8_t sector)
{
return nullptr;
int difference = (int)track - (int)track_;
track_ = track;
if(difference)
{
int direction = difference < 0 ? -1 : 1;
difference *= 2 * direction;
for(int c = 0; c < difference; c++) step(direction);
unsigned int zone = 3;
if(track >= 18) zone = 2;
else if(track >= 25) zone = 1;
else if(track >= 31) zone = 0;
set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(zone));
}
return get_sector(sector);
}
std::unique_ptr<Sector> get_sector(uint8_t sector)
@ -94,6 +116,7 @@ class CommodoreGCRParser: public Storage::Disk::Drive {
unsigned int shift_register_;
int index_count_;
int bit_count_;
uint8_t track_;
void process_input_bit(int value, unsigned int cycles_since_index_hole)
{
@ -155,29 +178,78 @@ std::list<File> StaticAnalyser::Commodore::GetFiles(const std::shared_ptr<Storag
// find any sector whatsoever to establish the current track
std::unique_ptr<CommodoreGCRParser::Sector> sector;
// attempt to grab a sector from track 0
while(!parser.get_is_track_zero()) parser.step(-1);
parser.set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(0));
sector = parser.get_next_sector();
if(!sector) return files;
// step out to track 18 (== 36)
for(int c = 0; c < 36; c++) parser.step(1);
// assemble disk contents, starting with sector 1
parser.set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(1));
// assemble directory
std::vector<uint8_t> directory;
sector = parser.get_sector(1);
while(sector)
uint8_t next_track = 18;
uint8_t next_sector = 1;
while(1)
{
sector = parser.get_sector(next_track, next_sector);
if(!sector) break;
directory.insert(directory.end(), sector->data.begin(), sector->data.end());
uint8_t next_track = sector->data[0];
uint8_t next_sector = sector->data[1];
next_track = sector->data[0];
next_sector = sector->data[1];
if(!next_track) break;
sector = parser.get_sector(next_sector);
}
// TODO: track changes. Allegedly not possible, but definitely happening.
// parse directory
size_t header_pointer = (size_t)-32;
while(header_pointer+32+31 < directory.size())
{
header_pointer += 32;
File new_file;
switch(directory[header_pointer + 2] & 7)
{
case 0: // DEL files
default: continue; // Unknown file types
case 1: new_file.type = File::DataSequence; break;
case 2: new_file.type = File::RelocatableProgram; break; // TODO: need a "don't know about relocatable" program?
case 3: new_file.type = File::User; break;
// case 4: new_file.type = File::Relative; break; // Can't handle REL files yet
}
next_track = directory[header_pointer + 3];
next_sector = directory[header_pointer + 4];
new_file.raw_name.reserve(16);
for(size_t c = 0; c < 16; c++)
{
new_file.raw_name.push_back(directory[header_pointer + 5 + c]);
}
new_file.name = petscii_from_bytes(&new_file.raw_name[0], 16, false);
size_t number_of_sectors = (size_t)directory[header_pointer + 0x1e] + ((size_t)directory[header_pointer + 0x1f] << 8);
new_file.data.reserve((number_of_sectors - 1) * 254 + 252);
bool is_first_sector = true;
while(next_track)
{
sector = parser.get_sector(next_track, next_sector);
if(!sector) break;
next_track = sector->data[0];
next_sector = sector->data[1];
if(is_first_sector)
{
new_file.starting_address = (uint16_t)sector->data[2] | (uint16_t)(sector->data[3] << 8);
}
if(next_track)
{
new_file.data.insert(new_file.data.end(), sector->data.begin() + (is_first_sector ? 4 : 2), sector->data.end());
}
else
{
new_file.data.insert(new_file.data.end(), sector->data.begin() + 2, sector->data.begin() + next_sector);
}
is_first_sector = false;
}
if(!next_track) files.push_back(new_file);
}
return files;

View File

@ -16,14 +16,20 @@ namespace StaticAnalyser {
namespace Commodore {
struct File {
File() : is_closed(false), is_locked(false) {}
std::wstring name;
std::vector<uint8_t> raw_name;
uint16_t starting_address;
uint16_t ending_address;
bool is_locked;
bool is_closed;
enum {
RelocatableProgram,
NonRelocatableProgram,
DataSequence,
User,
Relative
} type;
std::vector<uint8_t> data;