Вот работа с FDD из моего эмулятора УКНЦ EmuStudio. Написано еще в 2006, и с тех пор не менялось. Не смотря на то, что эмуляция не побитная, ни одной программы, не работающей с ним пока что не встречалось.
Код: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; }




Ответить с цитированием
Размещение рекламы на форуме способствует его дальнейшему развитию 

