mirror of
https://github.com/dbalsom/x86_microcode.git
synced 2026-06-16 13:07:07 +03:00
288 lines
8.9 KiB
C++
288 lines
8.9 KiB
C++
#include "alfe/main.h"
|
|
#include "zlib/zlib.h"
|
|
|
|
#ifndef INCLUDED_RDIF_H
|
|
#define INCLUDED_RDIF_H
|
|
|
|
class DiskImage
|
|
{
|
|
public:
|
|
DiskImage() : _version(0) { }
|
|
~DiskImage() { _blocks.release(); }
|
|
void clear()
|
|
{
|
|
_blocks.release();
|
|
_isRaw = false;
|
|
_version = 0;
|
|
_compressed = false;
|
|
_creator = "";
|
|
_label = "";
|
|
_description = "";
|
|
_medium = miniFloppy;
|
|
_tracksPerInch = 48;
|
|
_writeEnable = true;
|
|
_rotationsPerMinute = 300;
|
|
_bitsPerSecond = 250000;
|
|
_encoding = modifiedFrequencyModulation;
|
|
_heads = 2;
|
|
_defaultBytesPerSector = 512;
|
|
_defaultSectorsPerTrack = 9;
|
|
_blockCount = 0;
|
|
}
|
|
void load(String data)
|
|
{
|
|
_blocks.release();
|
|
int l = data.length();
|
|
create(l);
|
|
int magic = readInt(data, 0);
|
|
if (magic != 0x46494452)
|
|
_isRaw = true;
|
|
if (_isRaw) {
|
|
Block* block = new Block;
|
|
_blocks.add(block);
|
|
block->_size = l;
|
|
block->_cylinder = 0;
|
|
block->_head = 0;
|
|
block->_position = 0;
|
|
block->_dataRate = _bitsPerSecond * 60 / _rotationsPerMinute;
|
|
block->_type = Block::justData;
|
|
block->_trackWidth = 0x100;
|
|
block->_initialFlux = 0x40;
|
|
block->_compressed = false;
|
|
block->_data.allocate(l);
|
|
for (int i = 0; i < l; ++i)
|
|
block->_data[i] = data[i];
|
|
return;
|
|
}
|
|
_version = readInt(data, 4);
|
|
if (_version != 0)
|
|
throw Exception("Unknown RDIF version");
|
|
_compressed = (readInt(data, 8) != 0);
|
|
_creator = data.subString(readInt(data, 12), readInt(data, 16));
|
|
_label = data.subString(readInt(data, 20), readInt(data, 24));
|
|
_description = data.subString(readInt(data, 28), readInt(data, 32));
|
|
switch (readInt(data, 36)) {
|
|
case 0: _medium = eightInch; break;
|
|
case 1: _medium = miniFloppy; break;
|
|
case 2: _medium = microFloppy; break;
|
|
default:
|
|
throw Exception("Unknown media type");
|
|
}
|
|
_tracksPerInch = readInt(data, 40);
|
|
_writeEnable = (readInt(data, 44) != 0);
|
|
_rotationsPerMinute = readInt(data, 48);
|
|
_bitsPerSecond = readInt(data, 52);
|
|
switch (readInt(data, 56)) {
|
|
case 0: _encoding = frequencyModulation; break;
|
|
case 1: _encoding = modifiedFrequencyModulation; break;
|
|
default:
|
|
throw Exception("Unknown encoding type");
|
|
}
|
|
_heads = readInt(data, 60);
|
|
_defaultBytesPerSector = readInt(data, 64);
|
|
_defaultSectorsPerTrack = readInt(data, 68);
|
|
_blockCount = readInt(data, 72);
|
|
for (int i = 0; i < _blockCount; ++i) {
|
|
Block* block = new Block(data, i);
|
|
_blocks.add(block);
|
|
}
|
|
}
|
|
String save()
|
|
{
|
|
// TODO
|
|
}
|
|
void create(int length)
|
|
{
|
|
clear();
|
|
switch (length) {
|
|
case 160*1024:
|
|
_isRaw = true;
|
|
_defaultSectorsPerTrack = 8;
|
|
_heads = 1;
|
|
break;
|
|
case 180*1024:
|
|
_isRaw = true;
|
|
_heads = 1;
|
|
break;
|
|
case 320*1024:
|
|
_isRaw = true;
|
|
_defaultSectorsPerTrack = 8;
|
|
break;
|
|
case 360*1024:
|
|
_isRaw = true;
|
|
break;
|
|
case 720*1024:
|
|
_isRaw = true;
|
|
_medium = microFloppy;
|
|
break;
|
|
case 1200*1024:
|
|
_isRaw = true;
|
|
_defaultSectorsPerTrack = 15;
|
|
_tracksPerInch = 96;
|
|
_rotationsPerMinute = 360;
|
|
_bitsPerSecond = 500000;
|
|
break;
|
|
case 1440*1024:
|
|
_isRaw = true;
|
|
_defaultSectorsPerTrack = 18;
|
|
_medium = microFloppy;
|
|
_bitsPerSecond = 500000;
|
|
break;
|
|
case 2880*1024:
|
|
_isRaw = true;
|
|
_defaultSectorsPerTrack = 36;
|
|
_medium = microFloppy;
|
|
_bitsPerSecond = 1000000;
|
|
break;
|
|
default:
|
|
_isRaw = false;
|
|
}
|
|
if (_medium == microFloppy)
|
|
_tracksPerInch = 135;
|
|
}
|
|
|
|
// For XT Server.
|
|
void bios(Array<Byte>* data, Byte* hostBytes)
|
|
{
|
|
if (hostBytes[19] != 0)
|
|
return;
|
|
Byte sectorCount = hostBytes[1];
|
|
Byte operation = hostBytes[2];
|
|
Byte sector = hostBytes[3] & 0x3f;
|
|
Word track = hostBytes[4] | ((hostBytes[3] & 0xc0) << 2);
|
|
Byte head = hostBytes[6];
|
|
int sectorSize = 128 << hostBytes[10];
|
|
Byte sectorsPerTrack = hostBytes[11];
|
|
Byte gapLength = hostBytes[12];
|
|
Byte dataLength = hostBytes[13];
|
|
Byte formatGapLength = hostBytes[14];
|
|
Byte formatFillByte = hostBytes[15];
|
|
Block* block;
|
|
switch (operation) {
|
|
case 2:
|
|
// Read
|
|
{
|
|
block = _blocks.getNext();
|
|
int offset = _defaultBytesPerSector*((track*_heads + head)*_defaultSectorsPerTrack + sector - 1);
|
|
int bytes = sectorSize * sectorCount;
|
|
if (offset < 0 || offset + bytes >= block->_size) {
|
|
hostBytes[18] = 0;
|
|
hostBytes[19] = 4; // Sector not found
|
|
return;
|
|
}
|
|
data->allocate(bytes);
|
|
memcpy(&(*data)[0], &block->_data[offset], bytes);
|
|
hostBytes[18] = sectorCount;
|
|
hostBytes[19] = 0;
|
|
hostBytes[20] = 2;
|
|
}
|
|
break;
|
|
case 3:
|
|
// Write
|
|
break;
|
|
case 4:
|
|
// Verify
|
|
break;
|
|
case 5:
|
|
// Format
|
|
break;
|
|
default:
|
|
hostBytes[19] = 1;
|
|
return;
|
|
}
|
|
}
|
|
|
|
private:
|
|
static int readInt(String data, int p)
|
|
{
|
|
return static_cast<int>(readSInt32(data, p));
|
|
}
|
|
static SInt32 readSInt32(String data, int p)
|
|
{
|
|
return static_cast<SInt32>(readUInt32(data, p));
|
|
}
|
|
static UInt32 readUInt32(String data, int p)
|
|
{
|
|
return readUInt16(data, p) | (readUInt16(data, p + 2) << 16);
|
|
}
|
|
static UInt16 readUInt16(String data, int p)
|
|
{
|
|
return readUInt8(data, p) | (readUInt8(data, p + 1) << 8);
|
|
}
|
|
static UInt16 readUInt8(String data, int p)
|
|
{
|
|
if (p >= data.length())
|
|
return 0;
|
|
return data[p];
|
|
}
|
|
//void findBlock(SInt32 track, int head)
|
|
//{
|
|
// Block* b = _blocks.getNext();
|
|
// Block* p = b;
|
|
// while (b != 0) {
|
|
// SInt32 start = b->_cylinder - (b->_trackWidth / 2);
|
|
// if (track >= start && track < start + b->_trackWidth && _he)
|
|
|
|
// }
|
|
//}
|
|
class Block : public LinkedListMember<Block>
|
|
{
|
|
public:
|
|
Block() { }
|
|
Block(String data, int i)
|
|
{
|
|
int p = i*36 + 76;
|
|
_size = readInt(data, p + 4);
|
|
_data.allocate(_size);
|
|
int offset = readInt(data, p);
|
|
for (int j = 0; j < _size; ++j)
|
|
_data[j] = data[offset + j];
|
|
_cylinder = readSInt32(data, p + 8);
|
|
_head = readInt(data, p + 12);
|
|
_position = readSInt32(data, p + 16);
|
|
_dataRate = readUInt32(data, p + 20);
|
|
switch (readInt(data, p + 24)) {
|
|
case 0: _type = justData; break;
|
|
case 1: _type = fluxReversals; break;
|
|
case 2: _type = rawFlux; break;
|
|
default:
|
|
throw Exception("Unknown RDIF data type");
|
|
}
|
|
_trackWidth = readSInt32(data, p + 28);
|
|
_initialFlux = readSInt32(data, p + 32);
|
|
_compressed = (readSInt32(data, p + 36) != 0);
|
|
}
|
|
|
|
int _size;
|
|
SInt32 _cylinder;
|
|
int _head;
|
|
SInt32 _position;
|
|
UInt32 _dataRate;
|
|
enum Type { justData, fluxReversals, rawFlux } _type;
|
|
SInt32 _trackWidth;
|
|
SInt32 _initialFlux;
|
|
bool _compressed;
|
|
Array<Byte> _data;
|
|
};
|
|
|
|
bool _isRaw;
|
|
int _version;
|
|
bool _compressed;
|
|
String _creator;
|
|
String _label;
|
|
String _description;
|
|
enum Medium { eightInch, miniFloppy, microFloppy } _medium;
|
|
int _tracksPerInch;
|
|
bool _writeEnable;
|
|
int _rotationsPerMinute; // Nominal (0 = variable; CLV or zone bit recording)
|
|
int _bitsPerSecond;
|
|
enum Encoding { frequencyModulation, modifiedFrequencyModulation } _encoding;
|
|
int _heads;
|
|
int _defaultBytesPerSector;
|
|
int _defaultSectorsPerTrack;
|
|
LinkedList<Block> _blocks;
|
|
int _blockCount;
|
|
};
|
|
|
|
#endif // INCLUDED_RDIF_H
|