Задать вопрос
  • Процесс вывода кадра из Front buffer на матрицу монитора. Как это работает?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Инициирует видяха, и вообще поток данных для ЖК очень напоминает данные для ЭЛТ-монитора: между строчками пауза, между кадрами пауза побольше. Я это называю «виртуальная развёртка».

    2. Цифровое буферизируется ВСЕГДА. Эра небуферизированного цифрового осталась где-то в первых телетайпах, у которых были раздельные команды CR и LF… просто чтобы телетайп успел вернуть каретку и прокрутить барабан. И то телетайп вынужден преобразовывать последовательный код в N постоянно и одновременно «горящих» битов, и на это нужен буфер по ширине кода — 5 битов или сколько там нужно.

    Большинство мониторов хранит весь кадр, как минимум для работы всяких там ШИМов, овердрайвов и улучшайзеров, но желательно уж передавать данные из буфера на матрицу как можно быстрее.

    3. Хорошо, поднимаем схему первого попавшегося монитора и смотрим. Большая часть монитора — это огромная микросхема производства PixelWorks, которая выполняет все эти штуки с видеопотоком — разбор протокола, апскейлинг, улучшайзинг, овердрайв, генерацию команд для ЖК-панели — аппаратно.

    Где-то рядом находится самый обычный микроконтроллер с ПЗУ, который занимается чтением кнопок, инициализацией здоровенной микросхемы и вмешательством в её видеопоток, чтобы показывать экранное меню. Потому, кстати, в большинстве мониторов меню такое корявое — им занимается не могучая специализированная микросхема, а несчастный 32-битный микроконтроллер.

    Я не настолько разбираюсь в электронике, но сумел идентифицировать схему подсветки (диодной), главную микросхему, микроконтроллер с ПЗУ, обвязку клавиатуры (сколько там кнопочек — шесть?) и блок питания — каждое на своём листе.
    Ответ написан
    64 комментария
  • Почему длина long int 4 байта?

    @Mercury13
    Программист на «си с крестами» и не только
    Это особенность конкретного ABI (двоичного интерфейса).

    16-битные машины: 1/2/2/4/ (char/short/int/long/long long)
    Win32/64, Linux32: 1/2/4/4/8
    Linux64: 1/2/4/8/8

    И догадываюсь, почему так — это оказался лучший способ пофиксить некоторые старые API Си: таймеры (эпоха Unix, 0=1 янв 1970 00:00) и файлы.
    Ответ написан
    Комментировать
  • Как работают переводы на другие языки в играх?

    @Mercury13
    Программист на «си с крестами» и не только
    А теперь расскажу как человек, который давно и плотно интересуется локализацией, но в глаза Unity не видел.
    Локализация ДОЛЖНА храниться в простенькой базе «ключ-значение», это может быть INI, CSV, XML или что-то ещё. А то часто бывают половинчатые решения, когда общие строки локализуются, а прописанные где-то в скриптах — через зад (StarCraft первый). Или одна и та же строка служит и ключом чего-то, и выводимой локализованной строкой (Atreides/Ordos/Harkonnen в Dune II).

    Существуют два основных подхода к локализации.

    1. Есть так называемый «основной» язык, прописанный ПРЯМО в EXE-файле, ПРЯМО в скриптах игры и так далее. Локализация имеет вид
    «Open»,cmd → «Открыть»
    «The door is locked.»,level1 → «Дверь закрыта.»

    Как вы видите, ключ состоит из двух частей: строки-оригинала и уточнения. Если ключ совпадает, а уточнение — нет, берём строку без уточнения, а если и таковой нет — то что угодно. А если и ключ не совпадает — берём непереведённую.

    Адепты этого подхода — Gettext и Qt.

    2. Даже первый язык наравне с остальными.
    Cmd.Open → «Открыть»
    Level1.Locked → «Дверь закрыта.»

    Вариант 2.1: первый язык (обычно английский) используется как резервный, если локализации не нашлось.

    Сам я в пользу второго подхода, но он сложнее.

    САМАЯ простая база ключ-значение, чаще всего использовавшаяся на Java ME, где с памятью швах,— это простой линейный массив.
    [0] Открыть
    [1] Дверь закрыта.
    Всё преобразование из человекочитаемых идентификаторов S_CMD_OPEN в номера происходит на машине разработчика, генерацией файла
    constexpr unsigned S_CMD_OPEN = 0;

    Какой из методов брать?
    1. Насколько много локализации?
    2. Есть ли скрипты, GUI-формы и прочие ресурсы, способные содержать строки локализации?
    3. Насколько много больших текстов?
    4. Если программа параллельно разрабатывается и переводится: насколько тексты стабильны? Первый подход совершенно не выдерживает ситуации, когда исходные тексты меняются.
    5. Возможны ли неофициальные локализации? Метод 2 без уточнения 2.1, если программа «живая», исключает их.
    6. Что поддерживается вашим движком из коробки?
    7. Локализация встроена изначально, или приходится переводить неготовую к этому прогу?
    8. Насколько много интерфейса? У интерфейса есть противная фишка: нужно расщеплять строки, то есть давать одинаковым строкам разный ID (Open=«Открыть», «Открыто» и т.д.), и первый поход по умолчанию объединяет, второй по умолчанию расщепляет.

    И ма-ахонький апдейт. Есть ещё такое понятие, как сегмент — кусок МЕНЬШЕ локализуемого текста. То есть сегменты есть только на уровне комплекта локализации, в экспортированных текстах они склеиваются в единый текст. Обычно предложение или абзац. Сегментация используется в переводе больших текстов, особенно в интерфейсах, с такими целями.
    • Существуют тексты-«козы», которые могут найтись в памяти переводов. Например: «Серп и молот символизирует крестьян и рабочих. Осторожно, в вашем законодательстве эта символика может быть запрещена.»
    • Из-за недостатков интерфейса проги перевода можно пропустить целое предложение. Да, бывает!
    • В «живых» программах — можно помечать плохо переведённым кусок меньший, чем целый текст.
    (Живой я называю программу, которая параллельно разрабатывается и переводится. Благо методика «аджайл» предполагает частые небольшие выпуски.)
    Ответ написан
    Комментировать
  • Почему методы writeReplace и readResolve не работают в Externalizable?

    @Mercury13
    Программист на «си с крестами» и не только
    Потому что вы не предоставили места для вызова этих функций.
    А говорит оно вот о чём. При стандартном механизме записи объектов средствами ObjectOuputStream/Serializable система проверяет, объект Externalizable или нет, и если он Externalizable, то использует его методы.

    Надо использовать oos.writeObject(p), и аналогично для второй части.

    Externalizable — редкий класс, и обычно используется в таких случаях:
    • Чтобы сэкономить место — стандартная сериализация методом рефлексии, прописанная в ObjOutStream, создаёт много метаданных.
    • Чтобы зашифровать критические данные.
    Ответ написан
    Комментировать
  • В чем суть логической ошибки, продемонстрированной в старинном учебнике?

    @Mercury13
    Программист на «си с крестами» и не только
    Теорема Пифагора, но в обратную сторону. Не знаю, как она зовётся.
    Если a²+b²=c² при положительных a, b и c, то треугольник прямоугольный.
    Ответ написан
    Комментировать
  • Поле private суперкласса может быть доступно подклассу?

    @Mercury13
    Программист на «си с крестами» и не только
    class C {
      public static class Inner1 {
        private static int x = 0;
      }  
      public static class Inner2 {
        static void foo() {
          ++Inner1.x;
        }
      }
    }
    
    class D extends C.Inner1 {
       static void bar() {
         //++x;  не работает
       }
    }
    Ответ написан
    Комментировать
  • Возможно ли перегрузить с помощью ограничений?

    @Mercury13
    Программист на «си с крестами» и не только
    Через концепции работает отлично. Через enable_if не вижу способа. Через if constexpr вот так.
    #include <iostream>
    #include <concepts>
    
    class A {};
    class AA : public A {
    public:
        static constexpr const char* AData = "AA";
    };
    
    class B {};
    class BB : public B {
    public:
        static constexpr const char* BData = "BB";
    };
    
    // Через концепции
    template <class T>
    concept ASon = std::derived_from<T, A>;
    
    template <class T>
    concept BSon = std::derived_from<T, B>;
    
    template <ASon T>
    void foo(const T&) {
        std::cout << T::AData << std::endl;
    }
    
    template <BSon T>
    void foo(const T&) {
        std::cout << T::BData << std::endl;
    }
    
    template <class T> constexpr bool FALSE_V = false;
    
    // Через if consexpr
    template <class T>
    void bar(const T&) {
        if constexpr (std::is_base_of_v<A, T>) {
            std::cout << T::AData << std::endl;
        } else if constexpr (std::is_base_of_v<B, T>) {
            std::cout << T::BData << std::endl;
        } else {
            static_assert(FALSE_V<T>);
        }
    }
    
    int main()
    {
        foo(AA());
        foo(BB());
        bar(AA());
        bar(BB());
        return 0;
    }
    Ответ написан
  • Как корректно использовать функцию system при компиляции из GCC?

    @Mercury13
    Программист на «си с крестами» и не только
    system("call file.bat");
    Ответ написан
    Комментировать
  • Могут ли возникнуть проблемы при одновременном чтении и записи в разных потоках переменной?

    @Mercury13
    Программист на «си с крестами» и не только
    Сильно зависит от того, что такое size_t, но на распространённых платформах, где size_t совпадает с разрядностью машины, может или расти скачками, или вообще висеть в одном состоянии.
    Ответ написан
    Комментировать
  • Можно ли написать template deduction guide только для второго аргумента?

    @Mercury13
    Программист на «си с крестами» и не только
    Пока получилось через функцию.

    #include <utility>
    #include <iostream>
    
    class Cursor {
    public:
        Cursor(int aShape) noexcept : fShape(aShape) {}
        int shape() const noexcept { return fShape; }
    private:
        int fShape;
    };
    
    template <typename T, typename TFactory>
    class Lazy {
    public:
        Lazy(TFactory&& x) : factory(std::move(x)) {}
        Lazy(const TFactory& x) : factory(x) {}
        T operator()() const { return factory(); }
    private:
        mutable TFactory factory;
    };
    
    template <typename T, typename TFactory>
    inline auto lazy(TFactory&& factory)
    {
        return Lazy<T, std::decay_t<TFactory>>(std::forward<TFactory>(factory));
    }
    
    int main()
    {
        auto arrow = lazy<Cursor>([] { return Cursor(42); } );
        std::cout << arrow().shape() << '\n';
        return 0;
    }


    Может, шаблонного полиморфизма вам хватит, но я бы довольно быстро прикрутил виртуальный полиморфизм.
    Ответ написан
    Комментировать
  • Как записать все найденные слова в массив?

    @Mercury13
    Программист на «си с крестами» и не только
    У вас тут ожидается результат неопределённого размера.
    Лучше использовать динамический список вроде ArrayList.
    Ответ написан
    4 комментария
  • Почему адаптеры из range функторы?

    @Mercury13
    Программист на «си с крестами» и не только
    Для реализаций из STL — просто чтобы программист не закладывался на то, что он функция (иначе можно сделать код, привязанный к конкретной реализации), а писал шаблон.

    Если же это точка, где вы сами должны что-то дописать — что вам мешает сделать именно функцию? Функтор — это не только функция, а что угодно, что можно вызывать как функцию.
    Ответ написан
    6 комментариев
  • Почему bool оператор возвращает false, хотя на деле условия для true соблюдены?

    @Mercury13
    Программист на «си с крестами» и не только
    Стандартная ошибка наплюсника, аж две штуки.

    МАКРО-УРОВЕНЬ: вы пишете свою строку, но вместо того, чтобы сделать её отдельным объектом, инкапсулируете внутри Overcoat.

    Рисунок кода Си++ в точности обратный — всё, что умеет удерживать-отдавать ресурсы, переносится в отдельный объект небольшого размера. К тому же использование таких вот небольших объектов позволяет идиому «by-value+move»: если параметр — временная our::String, она просто переносится, а если нет — ну йок так йок.

    НЕПОСРЕДСТВЕННАЯ ПРИЧИНА: сравниваете указатели на буфера, а не содержимое строк.
    Ответ написан
    1 комментарий
  • Может ли быть общая точка у стягивающейся системы интервалов?

    @Mercury13
    Программист на «си с крестами» и не только
    Условие, когда имеет общую точку: последовательности a[n] и b[n] нестационарны: для любого a[n] найдётся другое a[N] большее, для b[n] аналогично меньшее.
    НЕОБХОДИМОСТЬ: они имеют общую точку — это значит, что общая точка x = lim a[n] > всех a[n], и меньше всех b[n].
    ДОСТАТОЧНОСТЬ: для каждого (a[n], b[n])⊃[a[N], b[N′]], и дальше теорема о вложенных отрезках.
    Для стационарной последовательности такого не будет — при достаточно большом n как минимум точка a[n] не будет принадлежать интервалу и будет принадлежать отрезку.
    Ответ написан
    Комментировать
  • Как избавится от эффекта бандинга/постеризации градиента?

    @Mercury13
    Программист на «си с крестами» и не только
    1. А точно исходник 16-битный?
    2. А точно преобразование происходит в 16 битах?
    3. А программа-просмотрщик поддерживает deep colour? Или, на худой конец, дизерит эти цвета?
    4. А монитор поддерживает?
    Ответ на любое из этого «нет» — полосы будут! Исключение: если дизерит, значит как-то компенсирует, что монитор всего лишь 8-битный.
    Ответ написан
    Комментировать
  • Как узнать первые признаки, что ноутбук больше не включится?

    @Mercury13
    Программист на «си с крестами» и не только
    Что может деградировать, чтобы потом сломаться окончательно?

    Экран. Если экран на CCFL (ныне сомнительно) — экран начал смещаться в красное. На белых диодах — смещаться в синее, причём пятнами.

    Микронеконтакт. Всё чаще стали происходить блускрины случайного происхождения, артефакты видео, отказы видео в 3D-режиме.

    Диск выработал ресурс. На механическом диске доступ к определённым местам стал слишком долгим. Что там на SSD с подобными признаками, сказать не могу.

    Итак, у вас там отказ чего-то в видяшной подсистеме — скорее всего, видеопамяти или обвязки матрицы. Это значит, что старый ноут уже устал, и надо готовить ему замену. Подозреваю либо микронеконтакт, но поиск таких неконтактов —  та ещё работа. Либо плашку памяти, отказавшую по счастливой случайности на том куске, который изначально при загрузке компьютера прикарманила встроенная видяха.
    Ответ написан
    Комментировать
  • Какая функция (или набор разных ф-ий) изменения "мощности" цвета света при распространении луча?

    @Mercury13
    Программист на «си с крестами» и не только
    Яркость лазера должна меняться с дальностью экспоненциально — яркость = A·e{Bx}: чем больше фотонов, тем больше рассеивается, дифур y’=−ky.
    Не забывайте, что sRGB сам нелинейный и состоит из линейного и степенного участка, но в целом неплохо приближается функцией y^2,2.
    Ответ написан
    Комментировать
  • Как синхронизировать процессы используя только std?

    @Mercury13
    Программист на «си с крестами» и не только
    Для чего нужен межпроцессный мьютекс? Для объекта (обычно куска памяти), который не проверяется на уровне системы и в то же время разделён между процессами.

    А в стандарте Си++ вообще такие объекты есть? Файлы проверяются. Каналы — насколько помню, нет стандартных, но они тоже проверяются.

    UPD3. Syncstream всё же содержит мьютекс, но второе решение — скопить данные в stringstream и сбросить их одной транзакцией — работает.
    Ответ написан
  • Не удаётся продолжить выполнение кода, поскольку система не обнаружила sfml-graphics-d-3.dll. Как исправить ошибку?

    @Mercury13
    Программист на «си с крестами» и не только
    Найти, где система сборки создаёт EXE. И положить рядом нужный DLL.
    Ответ написан
    Комментировать
  • Как правильно указать авторское право на шрифт?

    @Mercury13
    Программист на «си с крестами» и не только
    CC-BY-SA — очень неудачная лицензия для строительных блоков, у которых есть два метода пользования: построение новых блоков и использование по назначению в составной работе. Но если предполагать, что они разрешают менять ШРИФТ и использовать ГДЕ УГОДНО на манер OFL — то как-нибудь, достаточно простого указания где-то в about, титрах или другой сопроводительной документации:

    FONT: Minecraft Ten by Vania 5617sonfan, CC-BY-SA 3.0

    Если шрифт простым файлом, доступным методом «потянись и скопируй» — то лучше приложить текст лицензии в файле вроде LICENSE-MinecraftTen.
    Ответ написан