Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
ammehet opened this issue Jun 21, 2019 · 20 comments
Closed

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

ammehet opened this issue Jun 21, 2019 · 20 comments

Comments

@ammehet
Copy link

ammehet commented Jun 21, 2019

Сейчас стандартный образ 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
Copy link
Owner

samstyle commented Jun 22, 2019

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

@ammehet
Copy link
Author

ammehet commented Jun 22, 2019

Ок, сокращу

Пропатчил, пересобрал, интересно же проверить. Выяснилось, что сократить мало, ещё и 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
Copy link
Owner

samstyle commented Jun 22, 2019

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

@samstyle
Copy link
Owner

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

@ammehet
Copy link
Author

ammehet commented Jun 23, 2019

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

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

@samstyle
Copy link
Owner

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

@ammehet
Copy link
Author

ammehet commented Jun 24, 2019

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

@samstyle
Copy link
Owner

samstyle commented Jun 24, 2019

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

@ammehet
Copy link
Author

ammehet commented Jul 13, 2019

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

Магии нет =( 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
Copy link
Owner

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

@ammehet
Copy link
Author

ammehet commented Jul 13, 2019

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

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

@samstyle
Copy link
Owner

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

@samstyle
Copy link
Owner

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

@ammehet
Copy link
Author

ammehet commented Sep 13, 2019

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

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

@samstyle
Copy link
Owner

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

@ammehet
Copy link
Author

ammehet commented Sep 13, 2019

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

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
Copy link
Owner

samstyle commented Sep 14, 2019

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

@ammehet
Copy link
Author

ammehet commented Sep 14, 2019

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

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

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

@samstyle
Copy link
Owner

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

@ammehet
Copy link
Author

ammehet commented Dec 25, 2019

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

Screen Shot 2019-12-25 at 21 43 24

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

+3BASIC.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants