mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Add the prototype MX decoder.
This commit is contained in:
5
Makefile
5
Makefile
@@ -1,6 +1,9 @@
|
||||
all: .obj/build.ninja
|
||||
@ninja -C .obj test
|
||||
|
||||
clean:
|
||||
rm -rf .obj
|
||||
|
||||
.obj/build.ninja:
|
||||
@mkdir -p .obj
|
||||
meson .obj
|
||||
meson .obj --buildtype=debugoptimized
|
||||
|
||||
17
lib/bytes.cc
17
lib/bytes.cc
@@ -168,6 +168,23 @@ Bytes toBytes(
|
||||
return bytes;
|
||||
}
|
||||
|
||||
Bytes Bytes::swab() const
|
||||
{
|
||||
Bytes output;
|
||||
ByteWriter bw(output);
|
||||
ByteReader br(*this);
|
||||
|
||||
while (!br.eof())
|
||||
{
|
||||
uint8_t a = br.read_8();
|
||||
uint8_t b = br.read_8();
|
||||
bw.write_8(b);
|
||||
bw.write_8(a);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
Bytes Bytes::compress() const
|
||||
{
|
||||
uLongf destsize = compressBound(size());
|
||||
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
{ resize(0); return *this; }
|
||||
|
||||
Bytes slice(unsigned start, unsigned len) const;
|
||||
Bytes swab() const;
|
||||
Bytes compress() const;
|
||||
Bytes decompress() const;
|
||||
Bytes crunch() const;
|
||||
|
||||
@@ -22,6 +22,7 @@ void AbstractDecoder::decodeToSectors(Track& track)
|
||||
_sector = §or;
|
||||
_fmr = &fmr;
|
||||
|
||||
beginTrack();
|
||||
for (;;)
|
||||
{
|
||||
Fluxmap::Position recordStart = sector.position = fmr.tell();
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
{ return _fmr->seek(pos); }
|
||||
|
||||
protected:
|
||||
virtual void beginTrack() {};
|
||||
virtual RecordType advanceToNextRecord() = 0;
|
||||
virtual void decodeSectorRecord() = 0;
|
||||
virtual void decodeDataRecord() {};
|
||||
|
||||
75
lib/mx/decoder.cc
Normal file
75
lib/mx/decoder.cc
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "globals.h"
|
||||
#include "decoders.h"
|
||||
#include "mx.h"
|
||||
#include "crc.h"
|
||||
#include "fluxmap.h"
|
||||
#include "fluxmapreader.h"
|
||||
#include "sector.h"
|
||||
#include "record.h"
|
||||
#include "track.h"
|
||||
#include <string.h>
|
||||
|
||||
const int SECTOR_SIZE = 256;
|
||||
|
||||
/*
|
||||
* MX disks are a bunch of sectors glued together with no gaps or sync markers,
|
||||
* following a single beginning-of-track synchronisation and identification
|
||||
* sequence.
|
||||
*/
|
||||
|
||||
/* FM beginning of track marker:
|
||||
* 1010 1010 1010 1010 1111 1111 1010 1111
|
||||
* a a a a f f a f
|
||||
*/
|
||||
const FluxPattern ID_PATTERN(32, 0xaaaaffaf);
|
||||
|
||||
void MxDecoder::beginTrack()
|
||||
{
|
||||
_currentSector = -1;
|
||||
_clock = 0;
|
||||
}
|
||||
|
||||
AbstractDecoder::RecordType MxDecoder::advanceToNextRecord()
|
||||
{
|
||||
if (_currentSector == -1)
|
||||
{
|
||||
/* First sector in the track: look for the sync marker. */
|
||||
const FluxMatcher* matcher = nullptr;
|
||||
_sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
|
||||
readRawBits(32); /* skip the ID mark */
|
||||
readRawBits(32); /* skip the track number */
|
||||
}
|
||||
else if (_currentSector == 10)
|
||||
{
|
||||
/* That was the last sector on the disk. */
|
||||
return UNKNOWN_RECORD;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise we assume the clock from the first sector is still valid.
|
||||
* The decoder framwork will automatically stop when we hit the end of
|
||||
* the track. */
|
||||
_sector->clock = _clock;
|
||||
}
|
||||
|
||||
_currentSector++;
|
||||
return SECTOR_RECORD;
|
||||
}
|
||||
|
||||
void MxDecoder::decodeSectorRecord()
|
||||
{
|
||||
auto bits = readRawBits((SECTOR_SIZE+2)*16);
|
||||
auto bytes = decodeFmMfm(bits).slice(0, SECTOR_SIZE+2).swab();
|
||||
|
||||
uint16_t gotChecksum = 0;
|
||||
ByteReader br(bytes);
|
||||
for (int i=0; i<(SECTOR_SIZE/2); i++)
|
||||
gotChecksum += br.read_le16();
|
||||
uint16_t wantChecksum = br.read_le16();
|
||||
|
||||
_sector->logicalTrack = _track->physicalTrack;
|
||||
_sector->logicalSide = _track->physicalSide;
|
||||
_sector->logicalSector = _currentSector;
|
||||
_sector->data = bytes.slice(0, SECTOR_SIZE);
|
||||
_sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
}
|
||||
20
lib/mx/mx.h
Normal file
20
lib/mx/mx.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef MX_H
|
||||
#define MX_H
|
||||
|
||||
#include "decoders.h"
|
||||
|
||||
class MxDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
virtual ~MxDecoder() {}
|
||||
|
||||
void beginTrack();
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
|
||||
private:
|
||||
nanoseconds_t _clock;
|
||||
int _currentSector;
|
||||
};
|
||||
|
||||
#endif
|
||||
10
meson.build
10
meson.build
@@ -214,6 +214,15 @@ macdecoderlib = declare_dependency(
|
||||
include_directories('lib/macintosh')
|
||||
)
|
||||
|
||||
mxdecoderlib = declare_dependency(
|
||||
link_with:
|
||||
shared_library('mxdecoderlib',
|
||||
[ 'lib/mx/decoder.cc', ],
|
||||
dependencies: [fmtlib, felib, decoderlib]),
|
||||
include_directories:
|
||||
include_directories('lib/mx')
|
||||
)
|
||||
|
||||
zilogmczdecoderlib = declare_dependency(
|
||||
link_with:
|
||||
shared_library('zilogmczdecoderlib',
|
||||
@@ -246,6 +255,7 @@ executable('fe-readf85', ['src/fe-readf85.cc'], dependencies
|
||||
executable('fe-readfb100', ['src/fe-readfb100.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, fb100decoderlib])
|
||||
executable('fe-readibm', ['src/fe-readibm.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, ibmdecoderlib])
|
||||
executable('fe-readmac', ['src/fe-readmac.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, macdecoderlib])
|
||||
executable('fe-readmx', ['src/fe-readmx.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, mxdecoderlib])
|
||||
executable('fe-readzilogmcz', ['src/fe-readzilogmcz.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, zilogmczdecoderlib])
|
||||
executable('fe-readvictor9k', ['src/fe-readvictor9k.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, victor9kdecoderlib])
|
||||
executable('fe-rpm', ['src/fe-rpm.cc'], dependencies: [fmtlib, felib])
|
||||
|
||||
27
src/fe-readmx.cc
Normal file
27
src/fe-readmx.cc
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "reader.h"
|
||||
#include "fluxmap.h"
|
||||
#include "decoders.h"
|
||||
#include "mx.h"
|
||||
#include "image.h"
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "record.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
static StringFlag outputFilename(
|
||||
{ "--output", "-o" },
|
||||
"The output image file to write to.",
|
||||
"mx.img");
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
setReaderDefaultSource(":t=0-79:s=0-1");
|
||||
Flag::parseFlags(argc, argv);
|
||||
|
||||
MxDecoder decoder;
|
||||
readDiskCommand(decoder, outputFilename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user