samstyle / Xpeccy

Multiplatform emulator of retro computers
MIT License
71 stars 13 forks source link

Некорректное определение образов DSK #58

Closed ammehet closed 4 years ago

ammehet commented 5 years ago

Сейчас стандартный образ DSK определяется по сигнатуре MV - CPCEMU Disk-File\r\n

Однако, на практике встречаются и другие сигнатуры, в частности, MV - CPCEMU +3 Disk Image, MV - CPC format Disk Image

В описании формата DSK есть пояснение:

"MV - CPC" must be present, because it is used to identify the file as a disk image. It is sufficient to check this to identify the file as being a disk image.

Такая же история и с расширенным форматом. Сейчас проверяется сигнатура EXTENDED CPC DSK File\r\n

Про это в том же источнике тоже есть пояснение:

An extended DSK image is identified by the "EXTENDED" tag

Из-за такой мелочи некоторые образы не открываются, обидно.

samstyle commented 5 years ago

Ок, сокращу К слову, u765 ещё плохо отлажен, некоторые диски могут открываться, но не читаться.

ammehet commented 5 years ago

Ок, сокращу

Пропатчил, пересобрал, интересно же проверить. Выяснилось, что сократить мало, ещё и Disk-Info\r\n искать не надо вообще: вследствие произвола основной сигнатуры у Disk-Info нет фиксированной позиции внутри образа. Собственно, его может вообще не быть, и так иногда случается (есть пример). В документации по формату это часть большой сигнатуры, в которой значимы только первые 8 байт. В отличие от Track-Info\r\n, который обязателен и всегда по смещению 0x100, и это проверять надо ок, всё правильно сделано.

К слову, u765 ещё плохо отлажен, некоторые диски могут открываться, но не читаться.

Да, не читаются вообще все 80-дорожечные и некоторые 40-дорожечные. У меня под рукой есть образы, работающие везде там, но не здесь. Некоторые (40 дорожек) даже бодро начинают, читают загрузчик, меняют цвета бордюра и экрана, но затем устают независимо от крыжика турбо, даже бордюрный LED с дискеткой перестаёт.

Ещё один момент. Если в диске B не примонтировано ничего, то при ресете +3 даже не определяет, что дисководов двое. А если перед ресетом примонтировать образ, то таки да, видит двоих, но читать B отказывается, даже родной формат.

Ну и чтобы два раза не вставать, при сборке под макось (High Sierra 10.13.6) такая неприятность:

Make Error at CMakeLists.txt:199 (find_package):
  By not providing "FindQt5Widgets.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "Qt5Widgets", but CMake did not find one.

Чтобы победить, пришлось нагуглить и поменять в CMakeLists.txt

find_package(Qt5Widgets REQUIRED) на find_package(Qt5 COMPONENTS REQUIRED Widgets)
find_package(Qt5Network REQUIRED) на find_package(Qt5 COMPONENTS REQUIRED Network)

Ну и при по ходу паровоза нашлось немножко тоже (возможно, из-за того, что у меня SDL 1 и 2 одновременно, или хз. Для сборки приводил указатели к long, чтобы хоть как-то собралось для теста):

Xpeccy-master/src/xcore/sound.cpp:126:10: error: ordered comparison between pointer and zero ('SDL_TimerID'
      (aka '_SDL_TimerID *') and 'int')
        if (tid < 0) {
            ~~~ ^ ~
1 error generated.
Xpeccy-master/src/xgui/options/setupwin.cpp:449:39: error: no matching function for call to 'SDL_JoystickName'
        ui.lePadName->setText(conf.joy.joy ? SDL_JoystickName(conf.joy.joy) : "none");
                                             ^~~~~~~~~~~~~~~~
/Library/Frameworks/SDL.framework/Headers/SDL_joystick.h:61:38: note: candidate function not viable: cannot convert argument of incomplete
      type 'SDL_Joystick *' (aka '_SDL_Joystick *') to 'int' for 1st argument
extern DECLSPEC const char * SDLCALL SDL_JoystickName(int device_index);
1 error generated.
samstyle commented 5 years ago

Конкретно по SDL есть ключик для cmake: -DSDL1BUILD=0 или 1, чтобы он не мешал одно с другим. У меня в debian тоже обе версии, но собирается без проблем что с одной, что с другой. Команду в CMakeLists поправил

samstyle commented 5 years ago

Насчет DSK. Есть ли возможность "развернуть" загруженный образ (там, где он работает) в udi, чтобы были видны дорожки целиком, с пробелами и заголовками. сравним с тем, что получается у меня, и определим - в загрузке dsk проблема или всё же в u765.

ammehet commented 5 years ago

Есть ли возможность "развернуть" загруженный образ (там, где он работает) в udi

Боюсь, такой возможности я не знаю. Если научите, сделаем. DSK и так сам по себе не совсем плоский формат с дорожками и хитровыпендренными последовательностями секторов. Я недавно весной собаку надкусил по этому поводу по взрослому, могу рассказать подробно с примерами, но надо предметно, иначе многабукаф.

samstyle commented 5 years ago

Внутри своего эмулятора я разворачиваю загруженные диски в полные образы дорожек - по 6250 байт - с пробелами, маркерами дорожки/заголовка/данных и полями данных заголовка/сектора. Если где-то делается что-то подобное, то для меня самый простой выхлоп для анализа (даже не udi) - сохранить эти развернутые образы в файл по порядку (дорожка 0 голова 0, дорожка 0 голова 1, дорожка 1 голова 0, итд). А сам dsk не так и сложен.

ammehet commented 5 years ago

С помощью некой магии удалось сделать udi. Не знаю, насколько он работоспособный, открыть ничем не получилось. А также слегка настораживает размер файла – он получился меньше оригинального dsk.

samstyle commented 5 years ago

Там действительно какая-то магия. На корректный udi по содержанию не похоже. Для 80-дорожечных 2-сторонних дисков он должен быть 1125620 байт ЗЫ:я больше склонен винить эмуляцию u765, чем загрузку dsk

ammehet commented 5 years ago

Там действительно какая-то магия.

Магии нет =( UDI только на TR-DOS придуман. Лайфхак с запуском виндового fuse в wine под макосью позволил сохранить неизвестно что, нативный такое не позволяет.

Внутри своего эмулятора я разворачиваю загруженные диски в полные образы дорожек - по 6250 байт - с пробелами, маркерами

Вот же я тупица сразу не сообразил, я же всю весну собаку ел на эту тему. Возможно, сейчас я открою англию, но DSK и есть UDI, образ с маркерами дорожки/сектора. Интересное в том, что все пробелы между секторами и прочие железные характеристики определяются неким набором констант, который не хранится на диске/образе, а прибит гвоздями к рому/биосу – так CP/M плодится и размножается на всё, где увидит 8 бит. Это безобразие называется XDPB и выглядит так:

typedef struct
{
    WORD SPT;       // Number of 128-byte records per track
    BYTE BSH;       // Block shift. 3 = 1k, 4 = 2k, 5 = 4k, etc (blocksize = 2^BSH * 128)
    BYTE BLM;       // Block mask. 7 = 1k, #0F = 2k, #1F => 4k, etc (BLM = blocksize / 128 - 1)
    BYTE EXM;       // Extent mask
    WORD DSM;       // (no. of blocks on the disc) - 1
    WORD DRM;       // (no. of directory entries) - 1
    BYTE AL0;       // Directory allocation bitmap, first byte
    BYTE AL1;       // Directory allocation bitmap, second byte
    WORD CKS;       // Checksum vector size, 0 or #8000 for a fixed disc, else No. directory entries/4, rounded up
    WORD OFF;       // Offset, number of reserved tracks
    BYTE PSH;       // Physical sector shift, 0 = 128-byte sectors, 1 = 256-byte sectors, 2 = 512-byte sectors etc (sector size = 2^PSH * 128)
    BYTE PHM;       // Physical sector shift, 0 = 128-byte sectors, 1 = 256-byte sectors, 3 = 512-byte sectors etc (= sector size / 128 - 1)
    BYTE Sides;
    BYTE TracksPerSide;
    BYTE SectorsPerTrack;
    BYTE FirstPhysicalSector;
    WORD SectorSize;
    BYTE ReadGap;   // uPD765A read/write gap
    BYTE FormatGap; // uPD765A format gap
    BYTE MFM;       // Bit 7 set = Multitrack else Single track
                    // Bit 6 set = MFM mode else FM mode
                    // Bit 5 set = Skip deleted data address mark
                    // Usually #60 (96) = MFM + Skip deleted data address mark
    BYTE Freeze;    // Set to nonzero value to force this format to be used - otherwise, attempt to determine format when a disc is logged in
} DskXDPB;

К спектруму +3 гвоздями прибиты три набора констант вот здесь. Но есть ещё некий гвоздодёр, который изредка может храниться прямо на диске/в образе и оверрайдить зашитые константы.

Расковырял половину рома от +3 и реализовал алгоритм определения форматов DSK, чтение каталога и выдёргивание файлов с метаданными от +3 или голый CP/M. Если будет полезно, с удовольствием поделюсь говнокодом на сях без плюсов.

samstyle commented 5 years ago

DSK не UDI, а скорее FDI - заголовки секторов отдельно, данные отдельно, маркеров и пробелов нет

ammehet commented 5 years ago

Другими словами, да, из тапки tzx не сделать. Но этого и не требуется, всё предефайнено константами в роме, их всего 3 разновидности. И (иногда, сам не встречал) нулевой дорожке. Этого достаточно, чтобы поступать как +3, а дальше он сам разберётся, нам только этого и надо.

Так, стоп. Или не разберётся, а надо наоборот научить? Я что-то упускаю

samstyle commented 5 years ago

Для разворачивания дорожки мне достаточно списка заголовков секторов и их данных. Величины пробелов рассчитываются автоматом. Все байты с развёрнутых дорожек CPU получает через u765 (пока грешу на его эмуляцию). А вот какими способами и что с этими данными потом происходит, эмулятор волновать не должно.

samstyle commented 4 years ago

Вернулся из отпуска и приступов лени. Немного покопал uPD765. Как минимум, нашёл, почему были ошибки при чтении со 2 стороны диска. Если есть возможность собрать из исходников, просьба потестировать. Баги всё ещё возможны

ammehet commented 4 years ago

Собирается кривовато (в дебаггере при вводе адреса цифры задваиваются, а энтер и стрелки ведут себя вообще неприлично). И хоткеи – выход вместо ⌘Q почему-то по Alt-F4.

Но да, 80-дорожечные читаются, ура! Хоть и скорость совсем не турбо. Буду ждать релиз, спасибо!

samstyle commented 4 years ago

Насчет глюков с клавиатурой - возможно, стоит пересобрать полностью (make clean && make), потому как я такого не наблюдаю.

ammehet commented 4 years ago

Собираю так (с чистого листа): по традиции правлю

Xpeccy-master/src/xcore/sound.cpp:126:10: error: ordered comparison between pointer and zero ('SDL_TimerID'
      (aka '_SDL_TimerID *') and 'int')
        if (tid < 0) {
            ~~~ ^ ~
1 error generated.

на

    if (tid == NULL) {

и

Xpeccy-master/src/xgui/options/setupwin.cpp:448:39: error: no matching function for call to 'SDL_JoystickName'
        ui.lePadName->setText(conf.joy.joy ? SDL_JoystickName(conf.joy.joy) : "none");
                                             ^~~~~~~~~~~~~~~~
/Library/Frameworks/SDL.framework/Headers/SDL_joystick.h:61:38: note: candidate function not viable: cannot convert argument of incomplete
      type 'SDL_Joystick *' (aka '_SDL_Joystick *') to 'int' for 1st argument
extern DECLSPEC const char * SDLCALL SDL_JoystickName(int device_index);
1 error generated.

на

//#ifdef HAVESDL2
//  ui.lePadName->setText(conf.joy.joy ? SDL_JoystickName(conf.joy.joy) : "none");
//#elif HAVESDL1
    ui.lePadName->setText(conf.joy.joy ? SDL_JoystickName(0) : "none");
//#endif

затем

mkdir build
cd build
cmake -DSDL1BUILD=0 -DQt5_DIR=$(brew --prefix qt5)/lib/cmake/Qt5 -L/usr/local/lib ..
make

cmake version 3.15.3 AppleClang 10.0.0.10001145 Qt 5.13.1

Ну и внешне интерфейс выглядит не так, как в официальных билдах. Видимо, версии Qt и компилятора и cmake и макоси не совпадают, как по очереди, так и все хором.

Ну и КДПВ image

samstyle commented 4 years ago

хоть это к теме уже не относится, но хз... нет у меня дублирования ввода Screenshot_20190914_223851 ПыСы: надо вообще это поле заблокировать для ввода ПыСыСы: подозрение падает только на шланг. Я у себя gcc собираю.

ammehet commented 4 years ago

Вот верю! У меня в официальных релизах тоже всё красивее, чем в самосборном. Видимо, где-то у нас инструменты различаются. Ну и пусть их, я подожду релиза. А если что не так, я знаю в какое спортлото жаловаться =)

Спасибо за качественный продукт и оперативную реакцию! Приятно прикоснуться к живому проекту и хоть как-то принять участие в улучшении.

ПыСы: не надо блокировать поле, иногда проще скопипастить втудой полный путь, чем шарахаться по папочкам мышкой ПыСыСы: скорее Qt, потому что интерфейс и кнопки в интерфейсе же (⌘Q vs Alt-F4). В самом эмуляторе ничего не двоится, и кнопки ок, и пиксели не разьезжаются 0 OK, 10:1 =)

samstyle commented 4 years ago

Пока что закрывать не буду, вдруг по работе uPD765 ещё какие-то баги вылезут. А они вылезут...

ammehet commented 4 years ago

Похоже, таки что-то вылезло. Пробовал разные ромы, в том числе те же самые, что и в fuse, пробовал с турбой и без турбы. Результат один:

Screen Shot 2019-12-25 at 21 43 24

(кстати, экран заметно потемнел по сравнению с прошлыми релизами. это где-то настраивается?)

+3BASIC.zip