Результаты поиска потегупрограммирование

Дополнительные фильтры
Теги:
программированиеновый тег
Автор поста
Рейтинг поста:
-∞050100200300400+
Найдено: 703
Сортировка:

Создана ОС для самодельных компьютеров на случай апокалипсиса

Операционная система Collapse OS, разработанная Вирджилом Дупрасом, способна работать на микроконтроллерах Z80. Их широкое распространение за счет использования в самой разной технике, по мнению автора проекта, позволит людям, пережившим апокалипсис (коллапс, как его называет Дупрас), собирать ПК на их основе, и работать на них посредством Collapse OS. Система наделена базовыми функциями, в том числе работой с внешними накопителями и редактированием текстовых файлов, и Дупрас призывает сторонних разработчиков присоединиться к ее дальнейшему развитию.


Постапокалиптическая ОС

Разработчик программного обеспечения Вирджил Дупрас (Virgil Dupras) создал операционную систему Collapse OS, способную, по его мнению, пережить апокалипсис (сам Дупрас называет возможное будущее человечества «коллапсом», collapse). Он утверждает, что его ОС сможет работать на компьютерах, которые люди будут собирать из компонентов, найденных ими на свалках.
Для распространения Collapse OS Дупрас создал сайт collapseos.org, на котором привел объяснение, зачем такая ОС вообще нужна. По мнению разработчика, в обозримом будущем, примерно к 2030 г., мировые цепочки поставок себя исчерпают и перестанут быть эффективными, а то и вовсе разорвутся. Это приведет сперва к резкому сокращению, а затем и вовсе к прекращению производства микроэлектроники, и в итоге людям придется искать компоненты для новых ПК в буквальном смысле в горах мусора.
Системные требования ОС на 10 октября 2019 г. опубликованы не были. Разработчик также не уточнил, на каком ядре базируется Collapse OS.


Главное преимущество ОС

Вирджил Дупрас подчеркнул, что главной проблемой постапокалиптических пользователей его ОС может стать поиск микроконтроллеров. Да, их можно раздобыть на материнских платах компьютеров и других устройств, но перепрограммировать их под новые нужды уже не получится. «Через несколько десятилетий компьютеры придут в такое состояние, что уже не будут подлежать ремонту. Люди больше не смогут программировать микроконтроллеры», - отметил Дупрас на посвященном его ОС сайте.
В этом, по словам разработчика, и заключается главная особенность Collapse OS, которая позволит ей пережить апокалипсис. Система может работать даже на восьмибитных микропроцессорах Z80, использующихся в сравнительно простых с точки зрения электроники устройствах. Их можно обнаружить в кассовых аппаратах и калькуляторах.
Дупрас специально готовил Collapse OS к работе на этих микропроцессорах – он уверен, что именно они, ввиду широкого их распространения, будут чаще всего попадаться «копателям», в отличие от 16- и 32-битных микросхем.


Что умеет Collapse OS

Проект Collapse OS еще находится в разработке, но на момент публикации материала Вирджил Дупрас интегрировал в нее массу базовых функций. За 10 лет до предполагаемой Дупрасом даты апокалипсиса его система научилась редактировать текстовые файлы, читать данные с внешнего накопителя и копировать информацию на носители, воспроизводить себя и заодно компилировать исходные файлы на языке ассемблера для целого спектра центральных процессоров и микроконтроллеров. Также система поддерживает ряд интерфейсов и привычное устройство ввода – клавиатуру. Разработчиком заявлена поддержка карт памяти стандарта SD.
Работоспособность системы
Collapse OS находится на одной из ранних стадий разработки, но, по заверениям Дупраса, она вполне может запускаться на самосборных ПК самого базового уровня. Актуальную версию своей СО он запустил на компьютере домашней сборки на базе микроконтроллеров Z80 под названием RC2014.
Девелопер отметил, что в теории Collapse OS должна запускаться даже на игровых приставках. В качестве примера он привел классическую консоль четвертого поколения Sega Genesis, выпущенную в 1988 г. и известную в России под названием Mega Drive. Управлять системой, запущенной на этой приставке, можно через комплектный джойстик или клавиатуру со специальным переходником.


Дальнейшие планы и поиск единомышленников

Базовыми функциями Дупрас ограничиваться не станет, так как его цель заключается в создании полноценной многогранной ОС, которой должно быть удобно пользоваться. Он разместил открытый исходный код на портале Github (принадлежит Microsoft) и призвал сторонних разработчиков присоединиться к работе над его проектом.
«Я думаю, что смогу закончить разработку сам, но мне кажется, что было бы веселее работать с парой других специалистов. Участие в проекте требует очень специфического набора склонностей (вера в апокалипсис) и навыков (электроника и сборка z80). Я думаю, на свете есть не очень много людей, соответствующих этим требованиям, но если таковые все же есть, я бы хотел их найти», – сказал Вирджил Дупрас.
Согласно «дорожной карте» разработки, в планы Дупраса на ближайшее будущее входит запуск Collapse OS на программируемых графических калькуляторах TI-83+ (выпущен в 1999 г.) TI-84+ (2004 г.), разработанных компанией Texas Instruments. Следующим шагом станет запуск системы на настольном микрокомпьютере TRS-80 model 1 образца начала 80 годов XX века. Также в систему будет добавлена поддержка широкого спектра LCD-дисплеев и панелей на электронных чернилах (Е Ink) и различных дискет, включая 3,5-дюймовые.

Программист
неудачник
Bug
Error
404
Bug
Error
Bug
Успешный
программист,программирование,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,it-юмор

Помогите чайнику

Дана задача с такими условиями
Посчитать сумму чисел от 1 до N. Значение N по модулю не превышает 10^{9} .
Входные данные содержат одно целое число — N.
Нужно вывести целое число — сумму чисел от 1 до N.

Мой "код" на Python выглядит так:

N=int(input())
d=1
rez=((2+d*(N-1))*N)/2
print(int(rez))

Из 8 вариантов переменной N, c 5 получается правильный результат, а два выдают неправильный. В чём может быть проблема?
,программирование,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор
//Простые вопросы из разных собеседований:

/******************/
/* СТРАННОСТИ КОДА */
/******************/

//Задача: Найдите все нечётные числа в промежутке от 0 до 100
for(int i = 1; i >=1 100; i++) {
i = i%1;
int result;
if (result = 1) { int output = result; }
if (result = 0) { i++; }
}
//Я заставил претендента внимательно пройтись по коду... дважды. Это не опечатки, ни "i%1", ни одиночные "=" в последних двух строчках. Это претендент у которого 8 лет опыта.

//Задача: Найдите все нечётные числа в промежутке от 0 до 100
let number = 100;
for(let i = 0; i < number; i++) {
console.log(number[i]);
}
//Претендент сказал, что находить только нечётные числа слишком сложно и таким способом мы находим ВСЕ числа, так что это должно сработать!

//Задача: Найдите все нечётные числа в промежутке от 0 до 100
⟨html⟩
1,3,5...99
⟨/html⟩
//Я сказал: "Это работает, но что если нам понадобится найти все нечётные числа между 0 и 1 миллионом?"
//Претендент, немного подумав: "Тогда писать придётся очень долго."

//Задача: Найдите все нечётные числа в промежутке от 0 до 100
int a = [10];
for(i = 0; i < 10; i++) {
if( (a[i]<0) || (a[i] > 100) ){
exit(0);
}
}
//Думайте сами, что это должно значить. Я и понятия не имею, что это должно делать.

//Задача: Найдите все нечётные числа в промежутке от 0 до 100
function (0,100)
echo odd
//Я спросил претендента, что код вообще должен был делать, на что он ответил: "Я не хочу отвечать как-то помимо этого."
//Я ещё раз попробовал. Тот же претендент, следующая задача: Найдите сумму всех целых чисел в промежутке от 0 до 100
echo sum(0,100)
//Я: "Ладно, и если мы хотим сделать это на Javascript?"
echo sum(0,100)
sum++
//Это был самый опытный претендент, с 19 годами профессионального стажа. Девятнадцать, это не опечатка.
Этот претендент программировал профессионально до того как многие из вас ещё родились.

//Задача: Предположим у вас два целых числа, x и y, y больше чем x. Сложите все числа от x до y.
Пример: Если x равно 1, и y равно 5, тогда сумма будет 1+2+3+4+5.

int num1 = x;
int num2 = y;
for( int i = num1; i>= num2; i++) {
int result = i + (i+1);
i++;
}
//Что тут происходит? Ваша догадка будет хороша настолько же насколько и моя. Претендент и понятия не имелчто этот код должен делать.

//Задача: Сосчитайте от 700 до 200 с помощью уменьшения на 13.
for(int x = 700; x < 700; x--) {
int start = 700;
int increment = 13;
double answer;
answer = start - increment;
if(answer < 0) {
break;
}
}
//Из любопытства я спросил: "А почему ответ это число двойной точности?"
//Претендент: "Потому что надо как-то содержать значение взятое из _двух_ переменных."

//Сделайте стандартную колоду карт. Перемешайте колоду и вытащите случайно две карты. Покажите две карты.
let cards = [
['1','2','3','4','5','6','7','8','9','10','11','12','13'],
['a1','a2','a3','a4','a5','a6','a7','a8','a9','a10','a11','a12','a13']
['b1','b2','b3','b4','b5','b6','b7','b8','b9','b10','b11','b12','b13']
['c1','c2','c3','c4','c5','c6','c7','c8','c9','c10','c11','c12','c13']
];
for(let count = 0; count <=1 ; count ++ ) {
let firstLoop = Math.random(0,3);
let secondLoop = Math. random(0,12);
console.log(cards[firstLoop] [secondLoop]);
}
//Это было медленно и вымученно написано прямо на моих глазах в codeshare. Я хотел спросить почему цикл был использовандля второй части, в которой было всего лишь две карты, в то время как ни одного цикла не было использованодля 52 карт... но я так и не решился.

//Задача: Найдите все нечётные числа между x и y, предпологая что y больше чем x.
var arr = [1, 3, 5, 7, 9];
var numLength = x.length;
var x = x.substr(numLength -1, 1);
var parsed = JSON.parse(x);

for (var i = 0; i < arr.length; i++) {
if(arr[i] === parsed) {
console.log('Starting with an odd number');
for (var i = x; i <= y; i+=2) {
console.log(i)
}
} else {
console.log('Starting with and even number');
var bb = x +1;
for (var i = x; i <= y; i+=2) {
console.log(i)
}
}
};
//Если это вас озадачило, то позвольте объяснить. Претендент берёт последнюю цифру числа x, и проверяет
равна ли она 1/3/5/7/9. Если это так, то к нему добавляется 2, пока вы не достигните числа y. Иначе добавляется 1, чтобы сделать число нечётным и уж потом добавляются 2 до тех пор пока не достигнет y.
//Несмотря на мелкие ошибки в коде, логика была вполне функциональной, но неэффективной до ужаса.

//Сделайте стандартную колоду карт. Перемешайте колоду и вытащите случайно две карты. Покажите две карты.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K'];
var arr1 = [];
var arr2 = [];
var arr3 = [];
var arr4 = [];

var one = 'D';
var two = 'H';
var three = 'C';
var four = 'S';

var position = 1;

for (var i = 0; i < arr.length; i++) {
if (position === 1) {
x = one;
} else if (position === 2) {
x = two;
} else if (position === 3) {
x = three;
} else if (position === 4) {
x = four;
}
arr[position].push(arr[i] * x);
position += 1;
};

var fr = math.random();
var finalArr = [];
var newArr = [];
var eeArr = [];

for (var 1 = 0; i < finalArr.length; i++) {
var fr = math.random();
newArr.push({name: finalArr[i], value: fr});
eeArr.push(fr);
};

eeArr.sort();
var yyArr = [];

for (var i = 0; i < newArr.length; i++) {
var index = eeArr.indexOf(newArr[i].value);
newArr.newPos = index;
};
//Узрите этот шедевр! Читайте его медленно и вкушайте каждую строчку, такая красота приходит только раз в жизни.

/*********************/
/* ИНТЕРЕСНЫЕ ЛИЧНОСТИ */
/*********************/

//Задача: Напишите код, который проверяет является ли число нечётным.
//Претендент: Ладно, дайте мне минутку. *звуки печатания*
//Претендент: Мой ответ *голос заметно меняется с говорящего на читающий*

if((i%2)==1) cout⟨⟨i;
//Я *подозреваю, что претендент просто нагуглил это*: Ладно, а можете ли вы объяснить что эта строчка обозначает?
//Претендент: Это означает, что мы находим процент от i в 2.
//Я: Процент? Зачем мы находим "процент"?
//Претендент: Ээээ... Я хотел... эмм.... уууу....
//Я *с приятным голоском, но злобными намерениями*: Я понимаю, что это сложно. Вы когда-нибудь использовали этот
"процентный" оператор раньше?
//Претендент *с заметным облегчением*: Нет, никогда! Это мой первый раз когда я его использовал!
//Я: ...
//Претендент *сообразил что он только что сказал*: Я имел в виду... имел в виду...

//Задача: Найдите все нечётные числа в промежутке от 0 до 100.
//Претендент: Я прошу прощения, но я забыл точную формулу для нахождения нечётных чисел.
//Я: Нечётные числа это 1, 3, 5, и так далее.
//Претендент: Я понял, но я не могу вспомнить формулу, соответственно я не смогу найти эти числа.

//Вопрос: Можете рассказать мне об истории своей профессии?
//Претендент: Я выкладываюсь по полной, чтобы быть уверенным, что в моём коде не так много ошибок, перед тем как он заработает.

//Задача: Сосчитайте от 700 до 200 с помощью уменьшения на 13.
*совсем непонятный код*
//Я: Вы думаете, что оно заработает если я это запущу?
//Претендент: Честно говоря, нет. Я не думаю, что это вообще заработает.
//Я: Почему же?
//Претендент: Там куча синтаксических ошибок.
//Я: Ну а что если мы их исправим, тогда оно заработает?
//Претендент: Все равно не.
//Я: С чего же это?
//Претендент: Там ещё и логические ошибки.

//Претендент: Я программировал на протяжение 10 лет. 5 лет в качестве хобби и 5 профессионально. Я знаю PHP, Ruby,
JS (включая node и angular) , MongoDB, MySQL, PostgreSQL, и много чего ещё.
//Я: Чудесно. Ради чего вы используете свои навыки?
//Претендент: В течение 5 лет, в те, что я работал профессионально, я работал в 4 компаниях в качестве вебдева.
У меня также множество сайтов, созданных с нуля. Некоторые разрабатывал в одиночку, а некоторые находясь в команде
Я занимался одновременно фронт-энд и бэк-энд разработкой. Я готов встретиться с любыми трудностями!
//Я: Ладно. Используя язык на ваш выбор, сможете ли вы найти все нечётные числа между 0 и 100?
//Претендент: *пытается где-то 3 минуты*
//Претендент: Я не могу сделать этого. Мои навыки в математике не столь сильны.

//Эта ситуация произошла с _двумя_ разными претендентами. Их ответы звучали по разному, но посыл был один и тот же.
//Я: Ладно, я хочу дать вам парочку задач по программированию. У вас есть с собой бумага и ручка?
//Претендент: Конечно.
//Я: Хорошо. Используя предпочитаемый вами язык программирования, найдите все нечётные числа между 0 и 100.
//Претендент: Что, прям на бумаге?
//Я: Да. Напишите ваш код сюда и когда закончите зачитайте его мне и тогда мы перейдём дальше.
//Претендент: Но это же невозможно! Как я могу написать код не используя компьютер?

//Задача: Найдите все нечётные числа между 0 и 100. Заметка: это было собеседование по телефону.
//Претендент: А гуглить можно?
//Я: Я пытаюсь оценить ваши умения по программированию, а не по использованию поиска в Google.
//Претендент: Хах, верно! Но если я использую Google, то как вы узнаете?
//Я: Я дам вам похожую задачу, когда наше собеседование будет происходить с глазу на глаз.
//Претендент: Ну тогда я не могу.

//Худшее из худших собеседований, что у меня было и которое действительно заставило меня почувствовать себя плохо, было именно этим. Я пытался запечатлить _настрой_ того, как это проходило, так как мне не довелось увидеть хоть какой-нибудь код.
Некоторые из действий, которые я описываю, это то, что предположительно происходило на другом конце телефона, основываясь на том, что я услышал.
//Я: Здравствуйте! Благодарю, что позволили мне провести собеседование с вами. Вы подготовились? Готовы?
//Претендент: Я готов.
//Я: Отлично! Давайте начнём. *вступление и немного расслабляющей беседы, претендент очень клёвый* Ладно, так
ваше резюме перечисляет около 5 разных языков программирования. Вы хороши во всех из них?
//Претендент: Я хорош в Javascript и PHP, и неплох в Java.
//Я: Хорошо, какой ваш любимый язык?
//Претендент: Конечно же Javascript! Я много проработал на Javascript!
//Я: Это хорошо. Могу ли я дать вам пару задач по Javascript?
//Претендент: *молчит 10 секунд*
//Я: Алло? Вы всё ещё на линии?
//Претендент: Да, да. Я всё ещё на линии!
//Я: Так не возражаете если я дам парочку задач по Javascript?
//Претендент *с нервной дрожью в голосу*: Да, я думаю, я могу попробовать приложить все усилия, чтобы ответить.
//Я *вспоминая себя, не пытаюсь уничижить претендента*: Хорошо, так вы знаете что такое нечётные числа, верно? Ну 1, 3, 5 и так далее?
//Претендент *голос слегка подуспокоился*: Да! Да, я знаю что такое нечётные числа!
//Я: Ладно, моя задача такова. Используя ваш любимый язык, Javascript, сможете ли вы найти все нечётные числа в промежутке от 0 до 100?
//Претендент: *слышимые тяжёлые вздохи, но никаких слов на протяжении 10 секунд*
//Я: Алло?
//Претендент *говорит с большим усилием, голос в сейчас-точно-запаникует режиме*: Я э... Я... нахожу... а... нечётные...
Я... нечётные числа... ухх...
//Я *стараюсь немного проконтроллировать ситуацию*: Всё хорошо. Почему бы вам не потратить несколько минут, чтобы
записать ответ, и уж тогда зачтёте мне, когда закончите и будете готовы?
//Претендент *весь взволнованный и бездыханный*: ДА! Да, да! Я сначала запишу. Ладно! Ладно, я сейчас записываю это!
//На этом моменте, я убедился, что претендент действительно отложил трубку и начал писать. Я мог слышать лёгкие поскрябывания около двух минут, затем более жёсткие поскрябывания в течение минуты, а затем *чёёёёёёрк* *чёёёёёрк* звуки, будто бы кто-то расчерчивает кучу линий на бумаге. Затем наступила минута очень тяжёлого, очень быстрого дыхания, но никаких звуков записывания.
//Претендент *голос совершенно сломлен*: Я думаю я... я... нечётные числа... ааа... Я думаю... эммм...
//Я *совершаю критическую ошибку в суждении вопросом*: Там всё в порядке?
//Претендент: Нет. Нет! НЕТ! Я не могу! Это... не! Как это... нечётные... нечётные числа? Я... Я не могу делать это.
Я не могу это БОЛЬШЕ делать! Простите меня, мне надо идти. Надо идти, сейчас же! Прямо сейчас! Мне НУЖНО идти!
//Я: Ладно, без проблем. Может мы сможем продолжить это попозже.
//Претендент: Да, может завтра. *пииип*
//Претендент *в спокойном, вежливом электронном сообщении, гораздо позже в тот же день*: В этот момент я сожалею, что мне придётся отказаться от собеседования. Тем не менее может найдётся подходящее время когда-нибудь в будущем.

Уроки ОСдева №1

В прошлом посте я представил свою операционку и игру, которую пишу под неё в свободное время. Там же я сделал несколько заявок на будущие посты. Среди прочего я сказал, что, возможно, сделаю серию образовательных постов про разработку операционных систем и низкоуровневое программирование. Сегодня будет первый такой пост. Для понимания материала не нужно знать ассемблер или разбираться в устройстве ОС - про всё это я буду рассказывать. Нужно иметь представление об архитектуре компьютера в общих чертах: понимать, что такое BIOS, процессор, материнская плата, оперативная память, видео-, звуковая и сетевая карты, жёсткий диск, оптические и флоппи-приводы и как примерно всё это между собой скрепляется. Неплохо бы знать, что такое бит, байт и слово. Вообще супер, если вы в курсе, чем десятичная система счисления отличается от двоичной и шестнадцатеричной и умеете переводить из одной в другую. Поехали.

P.S.: если знаете английский, советую зайти сюда. Это довольно старая серия уроков по ОСдеву для новичков. Я в своё время почерпнул там очень много и в своих постах наверняка буду невольно цитировать оттуда.


Часть 1, теоретическая.

С чего начать? Вопрос, который возникает в голове любого, кто собрался писать ОС с нуля. В интернете полно тематических ресурсов, но не так много обучающих, где бы задача написания операционной системы разбивалась на небольшие последовательные этапы-уроки. Например, на OSDev.org очень много информации, распределённой по тематическим разделам, но составить на её основе у себя в голове необходимую последовательность действий для новичка будет очень сложно.

Я думаю, стоит начать с включения компьютера. Это не шутка: чтобы создать свою операционную систему, надо до определённой степени понимать как работает компьютер. Что происходит, когда вы нажимаете кнопку POWER на системном блоке и как у вас на экране оказывается ваш заваленный ярлыками и "новыми папками" рабочий стол? Для того, чтобы программа (а наша ОС - это, конечно же, программа) начала исполняться, она должна сначала попасть в оперативную память. Содержимое оперативной памяти же на момент включения пусто. Если среди читающих есть инженеры, советую зажмуриться и пропустить до следующего абзаца: сейчас будет упрощённая модель.

1. Нажатая кнопка POWER посылает электрический сигнал на материнскую плату.
2. Сигнал доходит до материнской платы и отправляется к блоку питания.
3. Блок питания просыпается и начинает подавать энергию подключенным устройствам.
4. Блок питания посылает сигнал на материнскую плату, начинает исполняться программа BIOS.
5. BIOS проводит POST (power-on self-test), посылая сигналы разным устройствам и получая (или не получая) от них ответ. Если устройство не отправило ответ, оно помечается как нерабочее или отсутствующее. Тут же BIOS определяет количество оперативной памяти и некоторые другие параметры системы.
6. Если POST окончен и никаких критических поломок не выявлено, BIOS сверяется со списком загрузочных устройств. Наверняка вы хоть раз его видели, если устанавливали Windows: его обычно можно настроить через интерфейс BIOS, выбрав, с чего загружать ОС (floppy, HDD, USB, ...).

Вот тут начинается часть, которая интересует нас. Предположим, мы вставили дискету с нашей ОС в привод и настроили приоритет загрузки следующим образом: CD-ROM, флоппи-привод, жёсткий диск, USB. Как BIOS определит, что на одном из носителей есть операционная система для загрузки? Физическое устройство цифровых носителей и способы доступа к информации на них это тема для отдельного урока или даже нескольких, так что пока удовольствуемся упрощённой схемой: BIOS считывает с 0 по 511 байты носителя и проверяет, чему равны байты 510 и 511. Если они равны 170 и 85 (AAh и 55h в шестнадцатеричной системе), BIOS считает, что нашёл программу-загрузчик. После этого считанный участок носителя размером в 512 байт загружается в оперативную память и запускается центральный процессор компьютера, который начинает выполнять загруженную программу. Программа-загрузчик догружает остальные файлы ОС и располагает их в памяти нужным образом, а потом говорит процессору, откуда нужно начать выполнение ОС.

Какие выводы можно сделать из полученной информации?

1. Помимо операционной системы на носителе должна быть программа-загрузчик, т.к. компьютер не знает, как именно структурированы файлы ОС и куда их надо загружать. Загрузка ОС - тоже задача разработчика.
2. Загрузчик должен быть не больше 510 байт, ведь BIOS считывает 512 и последние два из них заняты меткой загрузчика.
3. Последние два байта программы-загрузчика должны быть равны AA55h.
3. Загрузчик должен занимать строго определённое место на носителе: с 0 по 511 байты. Думаю, вы замечали, что когда копируете файлы на носитель обычными методами, никто не спрашивает вас, в какой именно участок памяти вы хотите их поместить. Значит, копировать загрузчик нужно каким-то особенным способом.

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


Продолжать?
Да
306(59,77%)
Единая Россия
206(40,23%)
Здесь мы собираем самые интересные картинки, арты, комиксы, мемасики по теме (+703 постов - )