Код:
static UINT16 PPU_FDD_STATE; // Регистр состояния Floppy-диска
static struct { // Определить структуру, описывающую дисководы
UINT8 Track, // Номер трека (00..79, при over-позицировании > 79)
Side, // Сторона (0 - нижняя головка, 1 - верхняя головка)
Motor, // Мотор (00 - выключен, иначе включен)
PrevMotor, // Предыдущее состояние мотора (для иконок дискет)
Mode, // Режим (00 - нет чтения/записи, 01 - чтение, 02 - запись)
Ready; // Готовность данных (00 - нет данных, иначе есть данные)
UINT8 PosType, // Текущее положение на треке (00 - межсекторное пространство, иначе сектор)
Sector; // Текущий сектор (0..9)
UINT32 MotTimer; // Таймер остановки мотора (если 0, то мотор остановлен)
UINT32 CurrPos; // Текущая позиция в словах внутри сектора (0..511) либо внутри межсекторного пространства (0..nnnn)
UINT8 *ImagePTR; // Указатель на образ диска (образ 819200 байт)
UINT16 ControlSp[50];// Массив для размещения текущей межсекторной служебной информации
} Floppy[4];
static const MaxTrack = 79; // Максимальный разрешенный номер трека
for (i=3; i!=-1; i--) { // Для всех дисков
Floppy[i].Motor = 0; // Двигатель выключен
Floppy[i].Mode = 0; // Режим 'бездействие' (для цветовой индикации)
Floppy[i].Track = 0; // Трек 0
Floppy[i].Ready = 1; // Данные готовы
Floppy[i].MotTimer = 0; // Таймер мотора сброшен, мотор выключен
memset(Floppy[i].ControlSp,0,sizeof(Floppy[i].ControlSp)); // Заполнить пробелы
Floppy[i].ControlSp[0] = 0x1234; // Терминатор псевдо-пробела (если сектор заполнен нулями)
Floppy[i].ControlSp[1] = 0x1234; //
Floppy[i].ControlSp[20] = 0xA1A1; // Синхропоследовательность перед заголовком сектора
Floppy[i].ControlSp[21] = 0xA1FE; // (не менять положение, завязано с фунцией чтения)
Floppy[i].ControlSp[40] = 0xA1A1; // Синхропоследовательность перед сектором
Floppy[i].ControlSp[41] = 0xA1FB; //
}
UINT16 FASTC PPU_RdW_FDD_STATE(void) { // Регистр состояния Floppy-диска
UINT16 State = 0;
UINT8 Numb = 3 - (PPU_FDD_STATE & 0x3); // Numb - номер дисковода (0..3)
if (Floppy[Numb].Track == 0) // Если трек = 0, то
State |= 0x0001; // устанавливаем бит TR0
State |= 0x0002; // Дисковод готов к работе (всегда)
// State |= 0x0004; // [T] Запись на диск запрещена
if (Floppy[Numb].Ready) // Если есть готовность данных
State |= 0x0080;
else
{ // Иначе, если нет готовности данных, то синхронизация
if (Floppy[Numb].PosType) // Если находимся на секторе, то автоматом
{ // перепозицируемся на следующую за сектором
// первую синхропоследовательность $A1A1
// (синхро заголовка сектора)
Floppy[Numb].CurrPos = 20; // Позицируемся на первую $A1A1
Floppy[Numb].PosType = 0; // межсекторного пространства
if ((Floppy[Numb].Sector +=1) > 9) // Перейти к следующему сектору
Floppy[Numb].Sector = 0; // Если достигли сектора 10, то переход к сектору 0
Floppy[Numb].ControlSp[22] = (Floppy[Numb].Track << 8) | // Прописываем в служебное поле
Floppy[Numb].Side; // номер трека / головки
Floppy[Numb].ControlSp[23] = ((Floppy[Numb].Sector + 1) << 8) | // номер сектора / длина
2; //
// printf("Spaces found inside sector, jump to next marker\n");
}
else // Если находимся на межсекторном пространстве
{
// Доделать индекс для программы TS.SAV
//if ((Floppy[Numb].CurrPos == 20) && // Если находимся в самом начале межсекторного
// (Floppy[Numb].Sector == 1)) // пространства перед сектором 0, то
//{
// State |= 0x8000; // установить флаг INDEX
// printf("Index Marker\n");
//}
if (Floppy[Numb].ControlSp[Floppy[Numb].CurrPos] == 0xA1A1) // Если достигли синхропоследовательности
{
Floppy[Numb].Ready = 1; // то устанавливаем готовность данных
State |= 0x0080;
}
else
{
if ((Floppy[Numb].CurrPos += 1) > 41) // Если достигли конца служебной области
{
Floppy[Numb].CurrPos = 0; // Позицируемся на начало
Floppy[Numb].PosType = 1; // сектора
// printf("Marker not found, found data\n");
}
}
}
}
State |= 0x4000; // [T] Контрольная сумма всегда правильная
return(State);
}
UINT16 FASTC PPU_RdW_FDD_DATA(void) { // Регистр данных Floppy-диска
UINT16 Value;
UINT8 Numb = 3 - (PPU_FDD_STATE & 0x3); // Numb - номер дисковода (0..3)
if (Floppy[Numb].PosType) { // Если находимся на секторе (сектор 512 байт)
Value = *(UINT16*)(Floppy[Numb].ImagePTR + // Слово данных
((Floppy[Numb].Track << 1) + Floppy[Numb].Side) * 5120 +
(Floppy[Numb].CurrPos << 1) +
Floppy[Numb].Sector * 512);
Value = (Value >> 8) | ((Value & 0x00FF) << 8); // Обмен байтов в слове
Floppy[Numb].Mode = 1; // Режим 'чтение' (для цветовой индикации)
if ((Floppy[Numb].CurrPos += 1) > 255) // Если достигли конца сектора
{
// printf("Track: %d, Side %d, Sector %d\n",
// Floppy[Numb].Track, Floppy[Numb].Side, Floppy[Numb].Sector);
Floppy[Numb].CurrPos = 0; // Позицируемся на начало
Floppy[Numb].PosType = 0; // межсекторного пространства
if ((Floppy[Numb].Sector +=1) > 9) // Перейти к следующему сектору
Floppy[Numb].Sector = 0; // Если достигли сектора 10, то переход к сектору 0
Floppy[Numb].ControlSp[22] = (Floppy[Numb].Track << 8) | // Прописываем в служебное поле
Floppy[Numb].Side; // номер трека / головки
Floppy[Numb].ControlSp[23] = ((Floppy[Numb].Sector + 1) << 8) | // номер сектора / длина
2; //
Floppy[Numb].Mode = 0; // Режим 'бездействие' (для цветовой индикации)
}
}
else { // Иначе находимся на межсекторном пространстве
Value = Floppy[Numb].ControlSp[Floppy[Numb].CurrPos]; // Слово данных
if ((Floppy[Numb].CurrPos += 1) > 41) { // Если достигли конца служебной области
Floppy[Numb].CurrPos = 0; // Позицируемся на начало
Floppy[Numb].PosType = 1; // сектора
}
}
return(Value);
}
void FASTC PPU_WrW_FDD_STATE(UINT16 Data) { // Регистр состояния Floppy-диска
UINT8 Numb;
if (Data & 0x400) { // Если активен бит выбора дисковода (REZ)
Numb = 3 - (Data & 0x3); // Numb - номер дисковода (0..3)
if ((!(PPU_FDD_STATE & 0x200)) && (Data & 0x200)) { // Если смена бита WM 0->1,
Floppy[Numb].Mode = 2; // то включаем режим записи
Floppy[Numb].CurrPos = -1; // Текущая позиция в секторе -1 (для пропуска
// первого синхрослова $FBA1
}
PPU_FDD_STATE = Data;
if (PPU_FDD_STATE & 0x10) // Если включен двигатель дисковода
{
Floppy[Numb].Motor = 1; // то Motor = 1, иначе Motor = 0
Floppy[Numb].MotTimer = 200; // Таймер остановки мотора (только для GUI)
}
else
Floppy[Numb].Motor = 0; // Не используется? Мотор выключается сам
// через некоторое время?
Floppy[Numb].Side = (PPU_FDD_STATE & 0x20) >> 5; // Выбор номера головки
if (PPU_FDD_STATE & 0x80) // Если установлен бит шага (ST), то
{
PPU_FDD_STATE &= 0xFF7F; // Сбросить бит шага
Floppy[Numb].Mode = 0; // Режим 'перемещение' (для цветовой индикации)
if (PPU_FDD_STATE & 0x40) // Если направление шага к центру, то
{
if (Floppy[Numb].Track < MaxTrack)
Floppy[Numb].Track += 1;
else
printf("Wrong Track: %d\n", Floppy[Numb].Track + 1);
// printf("Step to -> %d\n", Floppy[Numb].Track);
}
else // Иначе направление от центра
{
if (Floppy[Numb].Track > 0)
Floppy[Numb].Track -= 1;
// printf("Step to -> %d\n", Floppy[Numb].Track);
}
}
Floppy[Numb].ControlSp[22] = (Floppy[Numb].Track << 8) | // Прописываем в служебное поле
Floppy[Numb].Side; // номер трека / головки
Floppy[Numb].ControlSp[23] = ((Floppy[Numb].Sector + 1) << 8) | // номер сектора / длина
2; // (необходимо после шага или смены стороны)
if (PPU_FDD_STATE & 0x100) { // Если установлен бит инициализации (GOR)
Floppy[Numb].Ready = 0; // Сбросить бит готовности данных
}
}
return;
}
void FASTC PPU_WrW_FDD_DATA(UINT16 Data) { // Регистр данных Floppy-диска
UINT8 Numb = 3 - (PPU_FDD_STATE & 0x3); // Numb - номер дисковода (0..3)
if (Floppy[Numb].Mode == 2) { // Если активен режим записи
if ((SINT32)Floppy[Numb].CurrPos >= 0) { // Если позиция внутри сектора >= 0
*(UINT16*)(Floppy[Numb].ImagePTR // Записать слово на образ
+ ((Floppy[Numb].Track << 1) + Floppy[Numb].Side) * 5120
+ (Floppy[Numb].CurrPos << 1)
+ Floppy[Numb].Sector * 512) = Data;
}
if ((Floppy[Numb].CurrPos += 1) > 255) { // Если достигли конца сектора
Floppy[Numb].CurrPos = 0; // Позицируемся на начало
Floppy[Numb].PosType = 0; // межсекторного пространства
if ((Floppy[Numb].Sector +=1) > 9) // Перейти к следующему сектору
Floppy[Numb].Sector = 0; // Если достигли сектора 10, то переход к сектору 0
Floppy[Numb].ControlSp[22] = (Floppy[Numb].Track << 8) | // Прописываем в служебное поле
Floppy[Numb].Side; // номер трека / головки
Floppy[Numb].ControlSp[23] = ((Floppy[Numb].Sector + 1) << 8) | // номер сектора / длина
2; //
Floppy[Numb].Mode = 0; // Режим 'бездействие'
}
}
return;
}