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
|
all: .obj/build.ninja
|
||||||
@ninja -C .obj test
|
@ninja -C .obj test
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf .obj
|
||||||
|
|
||||||
.obj/build.ninja:
|
.obj/build.ninja:
|
||||||
@mkdir -p .obj
|
@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;
|
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
|
Bytes Bytes::compress() const
|
||||||
{
|
{
|
||||||
uLongf destsize = compressBound(size());
|
uLongf destsize = compressBound(size());
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public:
|
|||||||
{ resize(0); return *this; }
|
{ resize(0); return *this; }
|
||||||
|
|
||||||
Bytes slice(unsigned start, unsigned len) const;
|
Bytes slice(unsigned start, unsigned len) const;
|
||||||
|
Bytes swab() const;
|
||||||
Bytes compress() const;
|
Bytes compress() const;
|
||||||
Bytes decompress() const;
|
Bytes decompress() const;
|
||||||
Bytes crunch() const;
|
Bytes crunch() const;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ void AbstractDecoder::decodeToSectors(Track& track)
|
|||||||
_sector = §or;
|
_sector = §or;
|
||||||
_fmr = &fmr;
|
_fmr = &fmr;
|
||||||
|
|
||||||
|
beginTrack();
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Fluxmap::Position recordStart = sector.position = fmr.tell();
|
Fluxmap::Position recordStart = sector.position = fmr.tell();
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public:
|
|||||||
{ return _fmr->seek(pos); }
|
{ return _fmr->seek(pos); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void beginTrack() {};
|
||||||
virtual RecordType advanceToNextRecord() = 0;
|
virtual RecordType advanceToNextRecord() = 0;
|
||||||
virtual void decodeSectorRecord() = 0;
|
virtual void decodeSectorRecord() = 0;
|
||||||
virtual void decodeDataRecord() {};
|
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')
|
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(
|
zilogmczdecoderlib = declare_dependency(
|
||||||
link_with:
|
link_with:
|
||||||
shared_library('zilogmczdecoderlib',
|
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-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-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-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-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-readvictor9k', ['src/fe-readvictor9k.cc'], dependencies: [fmtlib, felib, decoderlib, readerlib, victor9kdecoderlib])
|
||||||
executable('fe-rpm', ['src/fe-rpm.cc'], dependencies: [fmtlib, felib])
|
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