Автор Тема: [ALL] Вопросы новичков  (Прочитано 21156 раз)

0 Пользователей и 3 Гостей просматривают эту тему.

Оффлайн drksnc

  • Пользователь
  • Сообщений: 10
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #120 : 10 Октябрь 2022, 12:53:47 »
Разве в этом хаке не изменены?
Или ты про город и Мистера Икс над ним?
Спасибо, этот хак я пропустил, смотрел другой с черепахами, а этот скипнул. Посмотрю. Но город и мистера Икса тоже было в планах заменить.

Оффлайн Nik Pi

  • Пользователь
  • Сообщений: 148
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #121 : 10 Октябрь 2022, 15:16:47 »
drksnc, попробуй найти этих людей, которые хакали игру, спроси у них. Поди, на ромхакинг.нет сидят. Может и утилиту какую-нить подгонят  ;)

Оффлайн drksnc

  • Пользователь
  • Сообщений: 10
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #122 : 12 Октябрь 2022, 23:17:52 »
Получилось найти оффсет через трейслог и заменить тайлы. Есть баги, но они понятные, нужно подменять тайлы. Честно говоря, так и не нашел никакого способа сбора мозайки, так что наделал своих костылей в виде утилиты, которая сравнивает цвета тайлов в мозайке и блоков 8х8 уже в готовой картинке, таким образом получил маску, наложив которую на картинку того же разрешения можно получить тайлсет. Всем спасибо за наводки, автор хака с черепашками дал ссылку на свой блог, что очень помогло.

Оффлайн anikeev.alexandr

  • Пользователь
  • Сообщений: 538
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #123 : 15 Январь 2023, 10:26:56 »
anikeev.alexandr, вот турнирный хак, где выход из боя сделан на Mode. Нужное тебе изменение можно найти вручную двоичным поиском отсекая: вставляешь половину оригинального рома и смотришь, на какой половине оказался нужный код. Снова делишь ту половину на половину...
Или найди патчер, дающий выбирать какие из изменений вносить. Так должно быть легче найти.

perfect_genius, огромнейшее спасибо за Вашу помощь и извиняюсь за очень долгую задержку! Скинутый Вами РОМ-файл - это то, что мне и было нужно! Буду пользоваться! :)

Оффлайн Vertigo

  • Пользователь
  • Сообщений: 2
  • Пол: Женский
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #124 : 24 Февраль 2023, 16:09:13 »
Добрый день.
Мне посоветовали обратиться сюда за помощью, надеюсь, что пишу в нужной теме.

Я пробую свои силы в редактировании текста в игре Animal Crossing Wild World на Nintendo DS. На данный момент получилось отрисовать кириллицу для текста и внутриигровой клавиатуры, сделать табличные файлы, также переведены и вставлены в игру некоторые небольшие файлы (имена персонажей, некоторые меню). Но с крупным переведённым текстом возникает проблема - он через несколько диалоговых окон зависает.
Текстовые файлы находятся в формате bmg, сжаты lz77. Крупные тексты при декомпрессии разделяются на несколько bin файлов, из которого собираю один целый.
Далее при помощи Cartographer получаю текст в txt (вместе с управляющими кодами), перевожу, далее при помощи Atlas пересчитываю указатели и вставляю новый текст.
Переведённый файл сжимаю обратно lz77, прописываю заголовок и при помощи Tinke вставляю в ром.

Я явно что-то делаю не так, но не могу разобраться, что именно. Что можно попробовать сделать или что почитать в таком случае? Пока подозреваю, что проблема со сжатием переведённого файла обратно - пробовала таким же образом распаковать и сжать оригинальный английский файл, также на том же месте зависает игра.

Прошу прощения, если моё сообщение выглядит сумбурно.

Программы, которые использую:

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5077
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #125 : 24 Февраль 2023, 16:47:14 »
Переведённый файл сжимаю обратно lz77, прописываю заголовок
В заголовке правильно указываете размеры? Здесь что-то про это: https://gbatemp.net/threads/acww-text-compression.335270/#post-4410911. Сжатие нужно тоже проверить, например: сжать оригинальный текст и сравнить с оригинальным сжатым файлом с этим текстом, в идеале должно совпасть, но иногда сжатие от разработчиков сделано хуже, чем от ромхакеров (у меня такое было с серией Sonic, которые в 3D) или наоборот, есть много корявых программ от ромхакеров, где могут быть ошибки сжатия иногда.

Оффлайн Yoti

  • Пользователь
  • Сообщений: 4460
  • Пол: Мужской
  • Не тро-гай ме-ня
    • Steam
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #126 : 24 Февраль 2023, 17:04:14 »
пробовала таким же образом распаковать и сжать оригинальный английский файл, также на том же месте зависает игра
Без изменений файла?

Оффлайн Vertigo

  • Пользователь
  • Сообщений: 2
  • Пол: Женский
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #127 : 24 Февраль 2023, 17:43:08 »
В заголовке правильно указываете размеры? Здесь что-то про это: https://gbatemp.net/threads/acww-text-compression.335270/#post-4410911. Сжатие нужно тоже проверить, например: сжать оригинальный текст и сравнить с оригинальным сжатым файлом с этим текстом, в идеале должно совпасть, но иногда сжатие от разработчиков сделано хуже, чем от ромхакеров (у меня такое было с серией Sonic, которые в 3D) или наоборот, есть много корявых программ от ромхакеров, где могут быть ошибки сжатия иногда.
Эту тему на ГБАтемпе тоже смотрела, она мне в целом помогла понять структуру заголовка для небольших файлов. Размеры новые указываю, если укажу неверно, то игра уже при запуске логотипа Нинтендо "подавится" файлом.
У меня в файле sequence3.bmg заголовок выглядит так:
Но я себя еще раз перепроверю.

С оригинальным текстом я пробовала сжатие делать, не всё совпадает. Пробовала обе программы для распаковки и сжатия, а также два формата: LZ77 и LZ77 vram safe (последний тоже рекомендовали на гбатемпе).


У меня почему-то не выходит вложением прикрепить оригинальный сжатый файл, даже зип архивом, выдаёт ошибку. Надеюсь, что можно ссылкой: https://dropmefiles.com/E4imy
Без изменений файла?
Да, текст внутри не меняла

Добавлено позже:
Но я себя еще раз перепроверю.
Нашла у себя ошибку в расчетах, теперь и английский текст вступления , и русский текст не зависают. Впредь буду внимательнее проверять свои расчёты. :)
Надеюсь, что проблема больше не побеспокоит, большое спасибо за ответы
« Последнее редактирование: 24 Февраль 2023, 19:10:34 от Vertigo »

Оффлайн FireFox Фан

  • Пользователь
  • Сообщений: 1544
  • Пол: Мужской
  • Огнелис
    • ВКонтакте
    • Youtube
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #128 : 03 Март 2023, 19:00:46 »
Доброго времени суток!

Напомните, чем открыть и заменить графику в NES\FDS и GB(C)?

Оффлайн Nik Pi

  • Пользователь
  • Сообщений: 148
    • Просмотр профиля
Re: [ALL] Вопросы новичков
« Ответ #129 : 03 Март 2023, 19:57:31 »
Доброго времени суток!

Напомните, чем открыть и заменить графику в NES\FDS и GB(C)?
Tie Molester/Tile Layer Pro/FaTilety в зубы, и ищи не запакованную графику

Оффлайн Turbo2000

  • Пользователь
  • Сообщений: 102
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #130 : 20 Март 2023, 22:07:54 »
Привет, пробую отладчик (gensida для Ida pro), можете помочь разобраться, может что не так с ромом, но он рабочий.
Во время отладки попадаю вот в такой бесконечный цикл (Самое интересное, что Ghidra это кусок кода точно так же интерпретирует)
* Screenshot 2023-03-20 225850.png (21.55 КБ. 828x178 - просмотрено 58 раз.)
Ghidra
* Screenshot 2023-03-20 230318.png (92.05 КБ. 1909x740 - просмотрено 61 раз.)
Но если поставить точку прерывания по адресу FE0, то тоже вывозится.
Смотрю регистры, и память, там одинаковые значения, и никак не выходит из цикла.
Подскажите, пожалуйста,
Версия Ghidra 10.1.5
Версия Ida Version 7.7.220118 Windows x64 (32-bit address size)

Добавлено позже:
Привет, пробую отладчик (gensida для Ida pro), можете помочь разобраться, может что не так с ромом, но он рабочий.
Во время отладки попадаю вот в такой бесконечный цикл (Самое интересное, что Ghidra это кусок кода точно так же интерпретирует)
(Ссылка на вложение)
Ghidra
(Ссылка на вложение)
Но если поставить точку прерывания по адресу FE0, то тоже вывозится.
Смотрю регистры, и память, там одинаковые значения, и никак не выходит из цикла.
Подскажите, пожалуйста,
Версия Ghidra 10.1.5
Версия Ida Version 7.7.220118 Windows x64 (32-bit address size)

Это какая-то ловушка или защита рома, или просто ошибка диззасмеблирования?

Оффлайн Марат

  • Пользователь
  • Сообщений: 556
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #131 : 20 Март 2023, 22:34:54 »
А что не так? Он ожидает пока что-то извне изменит память по адресу ffe006.
Это может быть одно из прерываний процессора: строчное, кадровое, переферийное(джойстик).

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1169
    • ВКонтакте
    • Steam
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #132 : 21 Март 2023, 00:30:34 »
В Дюне, вроде как, две копии игры в роме же? Не может ли быть так, что он попал в неработающую половину с какими-то его багами? :lol:
« Последнее редактирование: 21 Март 2023, 15:27:18 от perfect_genius »

Оффлайн Turbo2000

  • Пользователь
  • Сообщений: 102
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #133 : 21 Март 2023, 12:58:21 »
В Дюне, вроде как, две копии игры в роме же? Не может ли быть так, что он попал в неработающую половину со какими-то его багами? :lol:
Да, это версия Dune - The Battle for Arrakis (U) [!].gen, не самый лучший кандидат для исследования?

Оффлайн Turbo2000

  • Пользователь
  • Сообщений: 102
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #134 : 21 Март 2023, 13:05:57 »
А что не так? Он ожидает пока что-то извне изменит память по адресу ffe006.
Это может быть одно из прерываний процессора: строчное, кадровое, переферийное(джойстик).
То есть это просто ожидание на прерывание?
Тогда все понятнее. Но дождаться прерывание нет возможности, попадает в бесконечный цикл при отладке.
А здесь в чем смысл?

Судя по дебаггеру, A3 указывает на начало видео памяти, D0 пуст, D4 пару десятков, и получается, что постоянно пишется 0 в начало видеопамяти.
При этом регистры A3 и D0 никак не меняются, чего здесь я не понимаю, тоже могут быть изменения извне? Где про это можно почитать?

Оффлайн Марат

  • Пользователь
  • Сообщений: 556
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #135 : 21 Март 2023, 14:10:56 »
Обнуление какого-то места в видеопамяти. В a3 порт данных видеопамяти.  Он не в начало пишет. Адрес указывается изначально через адресный порт видеопамяти $C00000. после каждой записи адрес автоинкрементируется внутри видеопамяти. Здесь есть довольно много интересной информации http://tv-games.ru/media/open/igrovie_pristavki_remont.html

Оффлайн Turbo2000

  • Пользователь
  • Сообщений: 102
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #136 : 21 Март 2023, 23:24:49 »
Спасибо всем больше!
Еще очень помогли разобраться эти примеры, я как наивный думал, что можно менять видео память просто по адресу.  o_0

https://github.com/BigEvilCorporation/megadrive_samples

Добавлено позже:
А что не так? Он ожидает пока что-то извне изменит память по адресу ffe006.
Это может быть одно из прерываний процессора: строчное, кадровое, переферийное(джойстик).
Разобрался полностью, там действительно кадровое прерывание, там переменная в RAM, похожая на счетчик кадров.
« Последнее редактирование: 22 Март 2023, 00:06:44 от Turbo2000 »

Оффлайн Turbo2000

  • Пользователь
  • Сообщений: 102
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #137 : 29 Март 2023, 13:19:00 »
Привет, можете подсказать, как находить, когда отправляются таблицы тайлов в VDP_DATA?
Смотрел на примере заставки Sega в Дюне, с помощью дебаггера, запись в VDP_DATA идет всего пару раз, и не понятно, что там в DMA, длина данных 0x800, вроде похоже на правду, но диапазон адресов откуда писать странные 7F8000 - FF0000 (Ram).
Направьте так сказать, куда смотреть, вроде перечила мат. часть, но что-то не сходится.  :neznayu:

Оффлайн FireFox Фан

  • Пользователь
  • Сообщений: 1544
  • Пол: Мужской
  • Огнелис
    • ВКонтакте
    • Youtube
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #138 : 29 Март 2023, 18:29:41 »
Доброго времени суток!

Сложно ли перевести "LEGO Harry Potter: Years 1-4" для NDS?

Оффлайн Марат

  • Пользователь
  • Сообщений: 556
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #139 : 29 Март 2023, 21:55:58 »
Привет, можете подсказать, как находить, когда отправляются таблицы тайлов в VDP_DATA?
Смотрел на примере заставки Sega в Дюне, с помощью дебаггера, запись в VDP_DATA идет всего пару раз, и не понятно, что там в DMA, длина данных 0x800, вроде похоже на правду, но диапазон адресов откуда писать странные 7F8000 - FF0000 (Ram).
Направьте так сказать, куда смотреть, вроде перечила мат. часть, но что-то не сходится.  :neznayu:

Ну как бы вот написано DMA_SRC = 0x4A320 , DMA_LEN = 0x2C80, VDP_DST = 0x4000



Добавлено позже:
Это в IDA показывает так.

Оффлайн Turbo2000

  • Пользователь
  • Сообщений: 102
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #140 : 30 Март 2023, 00:53:58 »
Ну как бы вот написано DMA_SRC = 0x4A320 , DMA_LEN = 0x2C80, VDP_DST = 0x4000



Добавлено позже:
Это в IDA показывает так.

Мерси,
еще немного покопал, https://segaretro.org/Sega_Mega_Drive/VDP_registers#10
Здесь нашел много полезной, хотя и сжатой информации.
Спасибо за наводку, буду разбираться дальше, постараюсь ограничиться предыдущими глупыми вопросами.

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1169
    • ВКонтакте
    • Steam
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #141 : 31 Март 2023, 15:58:41 »
Turbo2000, а ты читал первые посты этой темы? Если нет, то тоже могут помочь :)
(и тогда тема зациклится)

Оффлайн Turbo2000

  • Пользователь
  • Сообщений: 102
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #142 : 03 Апрель 2023, 13:22:13 »
Turbo2000, а ты читал первые посты этой темы? Если нет, то тоже могут помочь :)
(и тогда тема зациклится)
Я попробую :)
На самом деле вы мне очень помогли, уже все получилось, немного направили + очень много разных источников в интернете, и отличный лоадер + инструменты от МефистО.
Удалось написать распаковщик, найти нужные адреса для графики, наборов тайлов и палитр.
Теперь интересно разобраться в синтезаторе, но думаю, это надолго.

Добавлено позже:
Перечитал, смешно, да  :lol:

Сейчас вопросов по графике, тайлам и палитрам нет.
У меня спортивный интерес использовать ресурсы игры в собственной реализации игры на другом движке, в общем, что-то похожее на демку сделать.

Добавлено позже:
Ну как бы вот написано DMA_SRC = 0x4A320 , DMA_LEN = 0x2C80, VDP_DST = 0x4000



Добавлено позже:
Это в IDA показывает так.

Ида все правильно показывала, я до этого не знал, что длина данных для DMA вычисляется по два байта, после этого все встало на свои места.
Просто был удивлен, как это так, что один раз пишется 0x800 байт в plane 128x32 и записывается полностью, оказывается дело в том, что это для двух байт.
« Последнее редактирование: 03 Апрель 2023, 13:32:26 от Turbo2000 »

Оффлайн Zzmey

  • Пользователь
  • Сообщений: 277
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #143 : 03 Апрель 2023, 18:28:38 »
Помогите плиз, думал сам справлюсь, но нет.

изучаю статьи по написанию игр для nes на Си
https://habr.com/ru/post/348022/

автор пишет:
"Надо помнить об ограничениях. Поддерживается не больше 64 спрайтов, и не более 8 на одной строке экрана. При превышении лимита будут отрисованы только спрайты с большим приоритетом. Если менять приоритет спрайта между кадрами, он будет мигать. Этот способ часто используется в играх."

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

в общем, мне не хватает количества 64 спрайтов, мне надо больше.
пробовал 1 способ - моргающий, не совсем разобрался в том что такое атрибут приоритета, просто менял атрибуты как попало, и спрайты при этом моргают, но моргают по уродски, как то некрасиво.

пробовал 2 способ, при дорисовке тайлов весь экран дрыгается, проскакивают какие то левые артефакты.

Помогите, как сделать плавную графику тайлами, или хотя бы как увеличить количество спрайтов сменой атрибутов, но чтобы моргание было красивым. И объясните, плиз, что такое приоритет спрайта, какой спрайт будет приоритетным?

Прилагаю тренировочный проект. Там по нажатии кнопки Б видно как дергаются тайлы, а при нажатии кнопки А реализовано моргание спрайтов, но уж больно коряво.

« Последнее редактирование: 03 Апрель 2023, 21:11:20 от Zzmey »

Оффлайн Cyneprepou4uk

  • Пользователь
  • Сообщений: 206
  • Пол: Мужской
  • Самый лысый ромхакер
    • ВКонтакте
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #144 : 04 Апрель 2023, 12:09:06 »
Zzmey, можно перевести спрайты в режим 8x16, тогда в теории получится вывести вдвое больше спрайтов на экране. Режим контролируется регистром 2000. Демонстрацию режима смотри в Tutorial 9 https://nesrocks.com/blog/nes-graphics/

Насчет приоритета спрайтов. Допустим у тебя для спрайтов выделена область 0200-02FF в RAM. Данные спрайта с наивысшим приоритетом находятся в 0200-0203, а с самым низким приоритетом в 02FC-02FF.

Оффлайн Zzmey

  • Пользователь
  • Сообщений: 277
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #145 : 04 Апрель 2023, 23:02:31 »
контролируется регистром 2000

что это за команда должна быть, для включения режима? хотя бы в принципе?

Вот это вот нашел в вики:

7  bit  0
---- ----
VPHB SINN
|||| ||||
|||| ||++- Base nametable address
|||| ||    (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00)
|||| |+--- VRAM address increment per CPU read/write of PPUDATA
|||| |     (0: add 1, going across; 1: add 32, going down)
|||| +---- Sprite pattern table address for 8x8 sprites
||||       (0: $0000; 1: $1000; ignored in 8x16 mode)
|||+------ Background pattern table address (0: $0000; 1: $1000)
||+------- Sprite size (0: 8x8 pixels; 1: 8x16 pixels – see PPU OAM#Byte 1)
|+-------- PPU master/slave select
|          (0: read backdrop from EXT pins; 1: output color on EXT pins)
+--------- Generate an NMI at the start of the
           vertical blanking interval (0: off; 1: on)

значит это пятый бит

у меня в программке было прописано
#define PPU_CTRL      *((unsigned char*)0x2000)

и далее

PPU_CTRL = 0x90
если перевести 16 в двоичный, это будет
10010000
ага, пятый бит был пустой...

попробуем записать в пятый бит единицу - 10110000
это будет  0xB0

пишу PPU_CTRL = 0xB0,
запускаю, ничего не работает, порядок спрайтов не меняется с виду.
пробую b4, ff, без изменений.

где же я ошибаюсь? как же это включить?

Оффлайн Cyneprepou4uk

  • Пользователь
  • Сообщений: 206
  • Пол: Мужской
  • Самый лысый ромхакер
    • ВКонтакте
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #146 : 04 Апрель 2023, 23:50:32 »
Zzmey, все верно, 90 -> B0. Но у тебя там несколько записей в этот регистр. Как минимум самая последняя из них, которая выполняется ежекадрово, должна включать этот режим.

Оффлайн Zzmey

  • Пользователь
  • Сообщений: 277
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #147 : 27 Апрель 2023, 11:17:19 »
Подскажите, плиз, как избежать моргания при перерисовке тайлов?

Прилагается пример, проект на С, там при нажатии А или Б тайлы моргают.
Перебрал все варианты, которые в голову пришли, менял PPUMASK и PPUCTRL, переставлял местами, запускал и в цикле и без цикла, не помогает.

Оффлайн Марат

  • Пользователь
  • Сообщений: 556
  • Пол: Мужской
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #148 : 27 Апрель 2023, 16:40:38 »
Надо выключать экран при перерисовке
При нажатии клавиш, у вас вызываются функции top и top2, в этих функциях у вас почему-то закомментированы функции All_Off, All_On. Надо их раскомментировать.
void top (void){
//All_Off(); // turn off screen
//Load_Palette();
summ_tile();
//All_On(); // turn on screen
}


void top2 (void){
//All_Off(); // turn off screen
//Load_Palette();
summ_tile2();
//All_On(); // turn on screen
}

Оффлайн Zzmey

  • Пользователь
  • Сообщений: 277
    • Просмотр профиля
[ALL] Вопросы новичков
« Ответ #149 : 28 Апрель 2023, 10:00:56 »
дрыганье устранено, на дрыганье влияло два фактора

1) цикл присваивания PPU_DATA
2) отсутствие Reset_Scroll

по первой проблеме - убедился что одинокая переменная выводится без дрыгания, а цикл выводится с дрыганьем, взял и тупо вывел все переменные без цикла.
по второй проблеме - включаю Reset_Scroll - не дрыгается, выключаю - снова дрыгается.


Еще другие аспекты:

- обязательно нужен вот этот счетчик, его положение в процедуре менял произвольно, положение не влияет ни на что, похоже.
   while (NMI_flag == 0); // wait till NMI
      NMI_flag = 0;

- к удивлению, оказывается не стало нужно включать и выключать экран.

- еще автор писал по поводу моргания вот что:
В идеале, надо ждать V-blank перед вызовом All_On(), иначе один кадр после него будет искажен, и экран будет мерцать.
я даже нашел пример такого кода
   Wait_Vblank();   // don't turn on screen until in v-blank
   All_On();

но он почему-то не понадобился.

прилагется код без дрыганий.
« Последнее редактирование: 28 Апрель 2023, 11:51:33 от Zzmey »