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:
parent
9d6dcb80a7
commit
8992feb8cd
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user