Перейти к содержимому
Zone of Games Forum

Рекомендованные сообщения

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

вопрос к знающим: как изменить длинну строки?

Поделиться сообщением


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

вопрос к знающим: как изменить длинну строки?

Вниательно смотреть на окружение текста.

P.S. А что это за игры?

Поделиться сообщением


Ссылка на сообщение
вопрос к знающим: как изменить длинну строки?

Найти указатели на строки в IDA и изменить их.

Поделиться сообщением


Ссылка на сообщение
Вниательно смотреть на окружение текста.

P.S. А что это за игры?

NFS Underground например.

Найти указатели на строки в IDA и изменить их.

а можно подробней?

Поделиться сообщением


Ссылка на сообщение
а можно подробней?

А куда еще подробней? IDA - дизассемблер. Для соответствующей работы тебе естественно надо знать хотя бы основы ассемблера.

Грубо говоря, "указатель" в асм - это смещение (offset) на соответствующий адрес памяти. Тебе нужно найти к какому адресу обращается прога и заменить оригинальный адрес на свой, где-нить в конце файла, где и будет находиться уже непосредственно твой текст.

Поделиться сообщением


Ссылка на сообщение

В переводе игры Aztaka я сталкивался именно с такой проблемой, некоторые текстовые строки были в главном exe-шнике.

Перевод их (строк) на русский язык был длиннее оригинала и простой заменой байт не обойтись было.

Но перевод успешно завершён и сейчас всё отлично работает без ограничений на длину строк (//forum.zoneofgames.ru/index.php?showtopic=17260).

Раз уж подняли эту тему, попробую изложить свой метод на примере Aztak'и (вообще это первый мой подобный опыт и пока единственный, но метод вполне рабочий). :)

Началось всё с того, что я не знал как заменить шрифт в игре. Шрифт назвался Sirona и был он запакован в архив неизвестного формата. В главном exe-шнике с помощью Hex-редактора (на данный момент для меня самый лучший "010 Editor") я однаружил слово Sirona. Сразу пришла мысь изменить его например на Arial.

Оказалось не сложно: букв в Arial меньше, чем в Sirona, поэтому заменяем первые буквы на Arial, а вместо последней буквы вбиваем ноль. В большенстве случаев именно нулевой байт определяет конец строки (иногда длина строки определяется байтом в начале строки). Игра нормально запустилась, шрифт поменялся на Arial.

То как стал выглядеть текст с Arial'ом не понравилось, рашил заменить на Georgia. Букв здесь больше, чем в изначальном Sirona. Конечно, в ехе-шнике после Sirona стоял ещё один нулевой байт, но заменять его было нельзя, он определяет конец строки. Вот тут и встало дело (как и у автора темы).

Первым делом нужно найти свободное место в ехе-шнике куда запихать наше слово Georgia. Siron'у трогать уже бесполезно.

Небольшое отступление...

Каждый exe-шник строится из нескольких секций (частей). Есть секция кода (сами машинные кода программы), секция ресурсов (иконка, курсоры, картинки, "манифест", инфа о версии и т.д.) и ещё несколько секций. Как правило, при компиляции (грубо говря при складывании этих секций в единое целое) компилятор делает так, чтобы размер секций был например кратен 4 килобайтам. И чтобы этого добиться дописывает в конец секции нули, чтобы было кратно тем 4-м килобайтам (число 4 Кб взято только для примера).

Вот оно! свободное место. Как узнать сколько места и в какой секции свободно?

В каждом ехе-шнике есть теблица секций, содержащая информацию по каждой секции. Из этой таблицы мы узнаем смещение секции относительно начала файла и 2 размера - один указывает сколько в секции полезной информации, а второй указывает размер всей секции, который зачастую больше размера полезной информации. Вот разница между этими значениями заполнена нулями и представляет для нас непосредственный интерес.

Находим значит секцию с наибольшим свободным пространством (тут иногда ещё приходится учитывать атрибуты секции, но в данном случае не буду этим голову морочить). Записываем туда нушу Georgia и запоминаем смещение от начала файла.

Ну понятно, что игра всеравно будет читать именно Sirona, ведь где находится наша Georgia она не знает.

Следующим шагом нужно указать игре откуда (с какого адреса) брать название шрифта.

Ещё одно небольшое отступление...

Какм образом программа может использовать текст?

Например команда на Delphi "MessageBoxA('Привет!')" после компиляции выполняется примерно так:

push <адрес фразы "Привет!">

call <адрес функции MessageBoxA>

При этом в программе может быть несколько ссылок на эту фразу (например из разных мест программы вызывается эта функция).

В случае с Aztaka со шрифтом происходит примерно тоже самое, но вместо MessageBoxA вызывается другая функция...

Вот нам нужно заменить адрес фразы после команды push, чтобы он указывал не на Sirona а на Georgia.

Адрес (виртуальный) это не есть смещение от начала файла. Но перевести смещение в адрес и обратно вполне можно. Как это делать я здесь писать не буду (лично я для данной цели написал маленькую программку...). Просто допустим, вы умеете это делать. :)

Итак, находим все ссылки на слово Sirona: переводим смещение в адрес (4 байта) и ищем, с помощью того же Hex-редактора, все места где встречаются эти 4 байта (не забыйте, перед поиском число нужно "переворачивать", т.е. если адрес = 041FE473, то ищем последовательность байт 73 E4 1F 04; "010 Editor" сам умеет переворачивать что надо).

В результате в файле Aztaka.exe уменя нашлось 4 таких ссылки. Вспоминаем смещение, по которому мы записали Georgia, переводим его в адрес и заменям им все 4 найденные ссылки (тоже не забывая "переворачивать").

После этого я запустил игру и всё заработало как надо, со шрифтом Georgia. :)

Ну вот, какбы уже этим можно обойтись и при переводе других игр. Это чем-то похоже на читерство в ArtMoney :)

--------

Но в случае с Aztaka в финальной версии русификатора я поступил чуть по-другому.

Менять в ехе-шнике пришлось довольно много текста (помимо названия шрифта) - нужно много свободного места в конце секции. И к тому же, в последней версии русика (1.04) я встроил свой шрифт (файл со шрифтом nogard.ttf ~170 КБ) прямо в ехе-шник. Откуда взять столько места?

Выход следующий: зачем искать свободное место в секциях ехе-шника, если можно добавить в конец ехе-шника свою новую секцию, которая будет содержать только наши данные, и сделать эту секцию именно таким размером, как нам надо (хоть десятки МБ)?

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

В итоге перевод ехе-шника Aztak'и я свёл к тому, что нахожу ссылки на текст нуждающийся в переводе, записываю эти ссылки и переведённый текст в текстовый файл следующим образом:

460C1

Уицило

^^^^^^^^^^Huitzilo

463D6

Айопа

^^^^^^^^^^Ayohpa

"Подсовываю" этот текстовик и файл шрифта Nogard.ttf моей программке (написанной специально для Aztaka), нажимаю кнопку и вуаля, получился переведённый на русский язык файл Aztaka.exe.

 

Spoiler

^^^^^^^^^^[1.04]

20C6A

Nogard

^^^^^^^^^^Крупный шрифт (диалоги, заголовки квестов, кнопки)

20CBF

Nogard

^^^^^^^^^^Самый крупный шрифт - AGP

20D14

Nogard

^^^^^^^^^^Шрифт среденго размера (меню, заголовки подсказок, текст квестов)

20D66

Nogard

^^^^^^^^^^Маленький шрифт (текст подсказок, цифры характеристик, названия квестов слева)

8A64

Copyright 2009 - Citeremis inc

Перевод - enz° & DotStudio

^^^^^^^^^^Copyright 2009 - Citeremis inc

45791

Уицило

^^^^^^^^^^Huitzilo (вторая ссылка из 2)

45DF5

Уицило -

^^^^^^^^^^Huitzilo -

45AA6

Айопа

^^^^^^^^^^Ayohpa (первая ссылка из 4)

45C05

Айопа -

^^^^^^^^^^Ayohpa -

azrus2.jpgazrus.jpgazrus3.jpg

Всё выше написанное никак не претендует на профессиональный гайд по переводу ехе-шников, но основной принцип я попытался описать.

Удачи! :)

-------------------------------------------

Ещё, как вариант можно не менять ехе-файл, а использовать отдельную dll-ку и специальный загрузчик (launcher) для игры.

Этот вариант имеет свои плюсы и минусы.

Из минусов:

- "не хилое" программирование, вылавнивание ошибок, если чего-то не учесть, то работать будет только у вас, на другом компе не будет

- лишние файлы (лишняя dll и exe-шник, без ехе-шника иногда можно обойтись)

Из плюсов, например:

- не изменяются оригинальные файлы игры, а значит возможна дальнейшая установка патчей на игру

- в dll-ку можно "засунуть" сложную программную начинку, которая может "налету" (уже после запуска игры) сама искать и заменять необходимые ссылки, тем самым подстраиваясь под разные версии игры (нет привязки к какой-то версии)

- в dll-ку также можно добавить некоторые другие функции: например, как в случае с Aztaka когда я не смог распаковать архив с ресурсами игры и заменить там шрифт, тогда я решил программно загружать шрифт уже во время выполнения программы (игры). Просто в данном случае я обошёлся без dll и вставил необходимый код в дополнительную секцию, но с использованием dll-ки сделать можно гораздо больше.

С подобным методом я работал гораздо больше, чем с первым описанным мною (изменение секций exe-шника). В русификации не использовал, но был у меня 4-х летний проект по добавлению новых функций в чат для локальной сети Network Assistant, в котором я использовал именно метод с dll и ехе-загрузчиком (собственно с тех пор я и заинтересовался структурой ехе-файлов).

 

Spoiler

NAinjector

NAfwt

NAHevaequ

В NAfwt и NAHevaequ адреса настраиваются во время выполнения, т.е. они не зависят от версии Nassi.

-------------------------------------------

В некоторых случаях (В ИГРАХ ТАКОЕ ВЫ ВРЯТЛИ ВСТРЕТИТЕ) текст хранится в секции ресурсов ехе-шника. В этом случае можно обойтись без всяких ухищрений и отредактировать необходимые строки с помощью таких программ как Restorator. В данном случае на длину строки никаких ограничений не налагается.

Именно таким образом обычно переводят приложения (не игры). Насколько я знаю, все специальные программы по локализации работают по такому принципу. Т.е. работают только с секцией ресурсов, а в играх лично я такого не встречал (игры типа "минёр", "солитёр" и т.д. не в счёт).

Изменено пользователем enz°

Поделиться сообщением


Ссылка на сообщение

enz°, статья хорошая но людям не разбирающимся в аспектах низкоуровневого программирования (включая меня :D ) очень тяжело будет разобраться.

Во время перевода ехе Torchlight-а я пользовался очень классной программкой OgreGUI. Плюс этой маленькой и бесплатной проги, написанной на ассамблере заключается в том, что она делает все то что ты описывал в этой статье САМА (если слово не влазит, создает секцию куда и переносит весь переведенный материал делая на него ссылку), нам лишь остается находить слова и переводить... переводить ... переводить. Хотя, подозреваю, что в некоторых случаях без hex редактора не обойтись.

Поделиться сообщением


Ссылка на сообщение

mDimоn, да, заметил, OgreGUI делает примерно то же самое, тоже создаёт секцию, так же заменяет ссылки.

Но никто никогда не сможет гарантировать, что она случайно не заменила не ту ссылку, что она заменила все значения, на которые влияет длина строки. :)

В той же Aztaka если перевести имя спутницы глав.героя, Айопы, и заменить все ссылки, указывающие на это слово, а их там 4 штуки, то игра работать будет, имя будет переведено, НО у этой птички, Айопы, исчезают спецэффекты, мерцающие звёздочки и тень. И на самом деле нужно было менять только 2 ссылки, остальные две используются не для вывода текста на экран, это имена ресурсов. И никакая программа этого определить не сможет, только тщательное изучение игры под отладчиком!

Можно ли будет когда-то с увереностью сказать, что переведённый Огром Torchlight не выдаст однажды какой-нибудь крендель? :)

OgreGUI действительно классная программа, но примечательна она больше тем, что кто-то вообще посмел попытаться подобную работу перевести в полностью автоматический режим. И, к сожалению, для многих доступен только такой метод. Но не останавливайтесь на этом ни в коем случае!

Изменено пользователем enz°

Поделиться сообщением


Ссылка на сообщение

enz°

Но никто никогда не сможет гарантировать, что она случайно не заменила не ту ссылку, что она заменила все значения, на которые влияет длина строки.

В той же Aztaka если перевести имя спутницы глав.героя, Айопы, и заменить все ссылки, указывающие на это слово, а их там 4 штуки, то игра работать будет, имя будет переведено, НО у этой птички, Айопы, исчезают спецэффекты, мерцающие звёздочки и тень. И на самом деле нужно было менять только 2 ссылки, остальные две используются не для вывода текста на экран, это имена ресурсов. И никакая программа этого определить не сможет, только тщательное изучение игры под отладчиком!

полностью согласен :smile: , ни что и ни когда не заменит "ручную работу" хорошего специалиста :smile: . В Torchlight-е тоже были ситуации когда вроде бы слово одно, а в ехе штук пять. Вот и приходилось методом тыка и проверки подбирать, чтобы глюков в игре не было.

Можно ли будет когда-то с увереностью сказать, что переведённый Огром Torchlight не выдаст однажды какой-нибудь крендель?

конечно нельзя :smile: , и проблемы с пропадающими квестовыми вещами в прошлом русификаторе (1.4) этому подтверждение.

Изменено пользователем mDimоn

Поделиться сообщением


Ссылка на сообщение

Ну ка, знающие люди, а особенно enz°. =)

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

Имеем exe игры Plants vs. Zombies.

Имеем фразу "Music" (00268370h), в ту же секцию .rdata запишем "Музыка" (допустим сюда: 00298FF0h).

Переводим смещения в виртуальные адреса (пока что при помощи Stud PE. На эту тему мы ещё потом поболтаем если не разберусь сам. =)) (Оригинал 70836600h и русский вариант F08F6900h тут) Нашли. Заменяем. Всё сделано верно и работает.

Правда перенос строки в другое место ничего не дал, игра на отведенном месте не отображает больше 5 символов.

"Музык" и всё. Да и рядом с оригинальной строкой для новой буквы "а" есть место (4D 75 73 69 63 00 00 00 00 00 00 C7 E2 F3 EA E8) Между "Music" и "Звуки" есть куча нолей, и лишь первый из них после слова определяет конец фразы. Т.е. даже не перенося слово можно было смело написать "Музыка" и теоретически игра должна была отобразить всё верно, так? Посчитав концом строки нулевой байт уже после "а".

Сделал всё руками, чтобы уж точно быть уверенным.

OgreGUI тоже пробовал, и даже работал ранее с ним. (Удобная штука, да вот доработать надо бы ещё. Короткие слова им не найти, лимит в 10000 слов обычно превышается моментально. =() Результат тот же, когда получалось.

Помогите-подскажите если можете. Насколько я понял тут косяк в том, что где-то на игровом CheckBox'е стоит ограничение на длину отображаемой строки? Right?

Изменено пользователем Den Em

Поделиться сообщением


Ссылка на сообщение

Найди переменную, отвечающую за ширину поля и увеличь её. Мне пришлось в первой The Legend of Kyrandia и C&C: Tiberian Sun почти весь интерфейс перекраивать, чтобы и влезло всё и выглядело красиво. Например, если пришлось увеличить размер кнопки, а она одна из нескольких одинаковых стоящих в столбец, то придётся и размер всех остальных подгонять.

Поделиться сообщением


Ссылка на сообщение

Переводим слово MUSIC в опциях игры Plants vs Zombies (по заявкам наших читателей).

Шаг 1 поиск строки

Находим в EXE слово MUSIC.

у меня получилось смещение - 268378h

Переводим смещение в виртуальный адрес. (см. приложение)

у меня получился адрес - 00668378h

по этому адресу игра будет обращаться к строке

Шаг 2 поиск ссылки на строку

Ищем в EXE число ( Unsigned Int (ui32) ), равное виртуальному адресу строки.

я искал 00668378h, нашлось по смещению 5CBDDh

Вот кусок из EXE, в котором нашлось это число:

8D 44 24 20 E8 F6 77 10 00 6A 05 68 78 83 66 00 8D 4C 24 54

Шаг 3 понимаем что к чему

Перед этим числом идёт байт 68 - код команды push (аргумент 4 байта), следом за ней идёт наш адрес.

Перед этой командой - 6A 05 - код команды push (аргумент 1 байт) и число 05

8D 44 24 20 E8 F6 77 10 00 6A 05 68 78 83 66 00 8D 4C 24 54

Если теперь глянем в дизассемблере на это место, увидим следующее:

713fa2fcbac118dad7c5e82b2a99275d.png

Задаются аргументы для функции и происходит её вызов (call), ну как ShowText( "MUSIC", 5 )

Шаг 4 вносим изменения

тут должно быть всё понятно ;)

Подобная PopCa'p наверно есть во всех играх на этом движке (например, в Pahelika). "Огр" не поможет.

Команда Push <длина строки> не всегда находится непосредственно перед Push <адрес строки>

Приложение: моя программка для перевода смещений в виртуальные адреса и обратно + исходники на Delphi (2010).

Поделиться сообщением


Ссылка на сообщение

Siberian GRemlin

Легко сказать, но слава богу это не потребовалось. Хотел прийти домой да написать "ЖЖЖЖЖ", чтобы удостоверится, что это действительно проблема размера поля, а не какая-то другая. Буду знать на будущее о таких прецендентах. Спасибо.

enz°

Помимо решения этой проблемы открыл глаза ещё на кое-что.

От благодарных читателей огромное спасибо. =)

И за исходники тоже отдельное спасибо.

Поделиться сообщением


Ссылка на сообщение

Решил таки наконец научиться модифицировать экзешники под нужды перевода. Естественно столкнулся с рядом проблем. Теоретически все понятно из сообщений enz°, но все уперлось в то, что я не могу узнать "смещение"... А раз нет смещения, то и прога по вычислению виртуального адреса ничего не дает.

В инете ничего вразумительного так и не нашел.

Куда смотреть то ? :D

Использую 010 Editor.

вот скриншот

DFzu03.png

Ткните, пожалуйста, носом, где увидеть смещение для фразы Continue (выделено синим)?

Или это те самые 16:D9E0h ... но если оно, тогда смещение для "Exit to main menu" такое же?

PS: Если спрашиваю совсем элементарные вещи, то пожалуйста дайте ссылку на какую-нибудь книгу или мануал... в инетренете ничего не нашел.

Поделиться сообщением


Ссылка на сообщение

Ну если я все правильно понял, то смещение для Continue - это: 16D9E8

А вообще у тебя как то немного не стандартно группы байт разбиты, обычно по 16 байт на строку, а у тебя по 32, но это не важно, кому как удобнее. :)

И если тебе просто смещения искать и заменять текст, то ты слишком навороченный хекс редактор выбрал. я для таких целей использую HxD.

вот сайт: http://www.mh-nexus.de/

оч простой, никаких лишних наворотов.

Изменено пользователем MeteoraMan

Поделиться сообщением


Ссылка на сообщение

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас популярно

  • Продвигаемые темы

  • Последние сообщения

    • Ну я так и сделал,оказалось рил копейки…Но этот чел всё равно звездабол
    • Точный смысл можно передать, не использую слова 1 в 1
    • Я так и сказал без точного отображения текста искажается смысла в результате и получаются всякие переводы дурацкие и неточные.
    • @Jimmi Hopkins , зря ты затеял это. С матами, без матов...  Человек который переводит, видит, что можно, а что нужно перевести так, либо этак, что подходило бы, либо было более уместно. А делать разделение с матами, без матов - это мартышкин труд, тем более, текста не мало. Другое дело, если делали бы озвучку, тогда ещё можно подискутировать. Лучше перевод как следует отшлифовать. 
    • Всем доброго времени суток.

      Скоро должна выйти Super Robot Wars Y и уже доступна демка для Switch, а сама игра выйдет в Steam 28 августа. Непосредственно Steam версия игры будет распространяться с денувой на запуск до 5 устройств в сутки.

      Начиная с этой части разработчики перешли на Unity, так что я решил попробовать вскрыть ресурсы демки с целью поиска возможности перевести игру в будущем. До этого Unity игры ни разу не модифицировал. За день у меня вышло узнать следующее:
      1) Через uTinyRipper можно полностью распаковать файлы игры исключая огромный массив кода и некоторые единичные моменты. Игра разработана на базе Unity 2022.3.44f1
      2) Какой распаковщик ни бери, они не могут взять этот код на распаковку.
      3) Среди всего кода лежат .txt файлы с миссиями демки, через которые я узнал, что они возможно всё ещё пишут текст для сценариев (миссий) на ПО, которое написано на Lua ещё в 2013 году (то есть на этапе зарождения обновлённого старого движка). Можно ознакомиться здесь. Все lua_1.txt это английская локаль.
      4) Когда я только начинал искать местоположение текста в файлах, то смог определить, что часть реплики из начала игры “The masked leader of the" в d70367e443ab137f06103dbf41f51a88.bundle и resources.assets.resS, но если первое распаковать, то сам текст непосредственно не вытаскивает, а второе не поддаётся на распаковку. Использовал метод поиска через Total Commander.  Сейчас начал это всё шерудить, чтобы понять, возможно ли сделать перевод в перспективе. Буду рад любой информации и любой помощи.

      PS: Нет, не предлагайте UnityEX. Я проверил это ПО и не могу быть уверенным, что его полная версия сможет мне хоть немного лучше помочь, чем прочее ПО из свободного доступа, а бесплатная версия не поддерживает проекты 2022 версии. Да и пока я не готов выбрасывать на это 10000р.
    • Проект ещё жив?
    •  i 
          Уведомление:
          В игре есть официальная полная русская локализация
    • Есть официальная полная русская локализация: Aggression: Europe Under Fire (2008)
      (тема на форуме)
    • Тяжело это признавать (шучу, как камень с души свалился на самом деле) меня обошли добрые люди в создании НОРМАЛЬНОГО перевода.
      У них есть группа в телеге, где доступен русификатор TQ2: https://t.me/tq_grace Что есть у них, чего нет у меня: Ручной перевод всего текста Перевод части пропущенных в locres строк Шрифты почти как в EN-оригинале Я всё, что сегодня делал для своего перевода — выложил, но это уже так, малозначимо.
    • Он должен точно отражать смысл.
  • Изменения статусов

    • Дмитрий Соснов  »  Tirniel

      Привет! ты разбираешься в компьютерном железе, сможешь помочь с советом по апгрейду старого компа?
      · 1 ответ
    • SHAMAH

      Куда вход на сайт убрали и ЗАЧЕМ? Хотел файл скачать, там только медленная загрузка и “зарегистрируйтесь”. Все. Пришлось вручную страницу входа прописывать.
      · 0 ответов
    • Nosferatu  »  behar

      Добрый вечер.
      Подскажите пожалуйста, у вас не осталось случайно исходников для фикса на широкоформатные мониторы для игры Vampire The Masquerade Redemption?
      Если да, то не могли бы вы ими поделиться, а если нет, то прошу прощенья что побеспокоил.
      Заранее спасибо.
      · 0 ответов
    • AlcoKolyic  »  makc_ar

      Здраствуйте! Извините, а можно попросить ссылку на место где можно взять перевод (патч или образ игры с переводом) El Shaddai: Ascension of the Metatron для ps3, пожалуйста? А то в теме к этой игре у меня не получилось найти работающие ссылки… Первая ведет в группу в которой удалены большинство постов, а пост с этой игрой ведет на сайт https://psnext.ru который сейчас не имеет отношения к видеоиграм. 
      · 0 ответов
    • oleg72  »  Boor

      https://www.skidrowcodex.net/fate-reawakened-goldberg/
      · 0 ответов
  • Лучшие авторы


Zone of Games © 2003–2025 | Реклама на сайте.

×