
Это самый простой способ создания программ для Р-ФОН.
Традиционно программы для мобильных телефонов собираются в специализированных средах разработки, включающих эмуляторы.
Уникальность телефона Р-ФОН заключается в том, что на нём можно сразу запускать программы, работающие на компьютерах с процессорами ARM и операционными системами «РОСА Фреш» и «РОСА Хром». Это существенно облегчает разработку. И написание, и запуск, и отладку, и работу в программе можно сначала обкатать на компьютере, и лишь на последнем этапе скопировать программу на телефон и протестировать уже на нём.
Естественно, для работы со специфическими для телефона компонентами, такими как GPS-приёмник и GSM-модем, требуется отдельный подход. Но для создания пользовательского интерфейса и, например, кода для работы по сети - компьютер более чем удобен.
Какой же компьютер с архитектурой процессора ARM подойдёт? Неплох компьютер на процессоре Байкал-М, но он дороговат, и его ещё нужно поискать. А вот компьютер на основе Raspberry Pi можно назвать народным. Подойдёт 64-разрядный, то есть, начиная с версии Raspberry Pi 4. Мне достался Pi 400, и всё описанное ниже было опробовано именно на нём.
Ниже описан мой опыт написания простых тестовых программ для Р-ФОН, использующих различные графические инструментарии (Qt, PyQt, GTK3, GTK4, SDL2).
Содержание
1 Запись образа ОС «РОСА Фреш» для Raspberry Pi
2 Дополнительные шаги после запуска ОС
3 Как собрать образ для Raspberry Pi самостоятельно
4 Общие замечания к написанию программ
6 Программы, использующие PyQt
7 Программы, использующие GTK 3
8 Программы, использующие GTK 4
9 Программы, использующие SDL2
1. Запись образа ОС «РОСА Фреш» для Raspberry Pi
Для начала запишем на SD-карту образ диска с операционной системой РОСА Фреш 12.5.1 для Raspberry Pi.
Почему именно версия 12.5.1, когда уже доступна версия 13?
Версия 12.5.1 имеет репозитарий 2021.1, совместимый с репозитарием Р-ФОН (информация на декабрь 2025 года).
Готовые образы я выложил вот сюда:
сборка с графическим интерфейсом Plasma5:
https://disk.360.yandex.ru/d/SxXqB1TYiqsphQ
минимальная сборка:
https://disk.360.yandex.ru/d/-OZE4QknLDEs7g
На моей Raspberry Pi с 4Гб оперативной памяти отлично работает сборка с графическим интерфейсом. Впрочем, тяжелые задачи я на ней не запускал, только сборку небольших тестовых программ.
Я записывал образы на SD-карту командой dd (под Linux). Устройство для чтения SD-карт у меня виделось как /dev/mmcblk0:
$ unxz rosapi-12.5.1-plasma5.raw.xz
$ sudo dd if=rosapi-12.5.1-plasma5.raw of=/dev/mmcblk0 bs=1M status=progress
$ sync
2. дополнительные шаги после запуска ОС
После запуска образа на Raspberry Pi следует выполнить дополнительные шаги
( пароль пользователя root: root ):
2.1. Для работы WiFi на Raspberry Pi 400, нужно скопировать в каталог /lib/firmware/brcm установленного образа операционной системы файлы:
brcmfmac43456-sdio.raspberrypi,400.bin
brcmfmac43456-sdio.raspberrypi,400.clm_blob
brcmfmac43456-sdio.raspberrypi,400.txt
Файлы качать вот отсюда:
https://github.com/bsdkurt/brcm-supplemental
2.2. Отключить засыпание (Suspend). Ибо заснувший Raspberry Pi разбудить невозможно. По крайней мере, мне это не удавалось. Пришлось для оживления отключать/включать питание.

2.3. Добавить обычного пользователя, внести его в группу wheel, чтобы он смог выполнять команду “sudo” . Также браузер и регулировка громкости звука не работали у меня в сессии пользователя root.
# useradd user
# passwd user
# usermod -aG wheel user
2.4. Поменять пароль у пользователя root
# passwd root
2.5. При входе в графическую оболочку выбрать Wayland вместо X11

2.6. Увеличить корневую файловую систему (сборка для версии 13 сама расширят файловую систему при первом запуске, но в 12.5.1 я это до ума не довёл, поэтому – руками). Пример ниже:
Пример увеличения корневой файловой системы
[mikhail@raspberrypi ~]$ sudo parted /dev/mmcblk0
[sudo] password for mikhail:
GNU Parted 3.5
Using /dev/mmcblk0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Warning: Not all of the space available to /dev/mmcblk0 appears to be used, you can fix the GPT to use all of the space
(an extra 17208928 blocks) or continue with the current setting?
Fix/Ignore? f
Model: SD SC16G (sd/mmc)
Disk /dev/mmcblk0: 15.9GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 269MB 268MB fat32 bootfs boot, esp
2 269MB 7121MB 6851MB ext4 rootfs
(parted) resizepart 2 15000
Warning: Partition /dev/mmcblk0p2 is being used. Are you sure you want to continue?
Yes/No? Y
(parted) q
Information: You may need to update /etc/fstab.
[mikhail@raspberrypi ~]$ sudo resize2fs /dev/mmcblk0p2
resize2fs 1.46.6 (1-Feb-2023)
Filesystem at /dev/mmcblk0p2 is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 2
The filesystem on /dev/mmcblk0p2 is now 3596317 (4k) blocks long.
3. Как собрать образ для Raspberry Pi самостоятельно
Для тех, кто хочет собрать образ самостоятельно, под катом привожу инструкцию по сборке.
Инструкция по сборке образа операционной системы РОСА Фреш 12.5.1 для Raspberry Pi
3.1 Установите на компьютер ( x86 ) операционную систему РОСА Фреш 13. Дистрибутивы лежат вот здесь: https://rosa.ru/rosa-linux-download-links/
Я использовал сборку с графическим интерфейсом Plasma 6, но вы можете выбрать другой интерфейс по своему вкусу.
При разбиении диска убедитесь, что после установки у вас останется по 20 Гбайт свободного места в корневой файловой системе, в «/home» и в «/var/tmp».
Сразу после установки обновите систему.
3.2 Установите набор файлов конфигурации для создания образов операционной системы для различных платформ «image-builder». Качается вот отсюда, там же есть инструкция по установке необходимых ему пакетов:
https://github.com/rosalinux/image-builder
3.3 Скопируйте файл /etc/pki/rpm-gpg/RPM-GPG-KEY-ROSA в каталог /usr/share/distribution-gpg-keys/
sudo cp /etc/pki/rpm-gpg/RPM-GPG-KEY-ROSA /usr/share/distribution-gpg-keys/
3.4 Перейдите в каталог image-builder-main/device/raspberry/rpi5
Для создания образа диска с установленной минимальной операционной системой версии 12.5.1 подставьте файл mkosi.conf вот отсюда: https://disk.360.yandex.ru/d/uj_4IyvKpfOxkQ
Для создания образа диска с установленной операционной системы версии 12.5.1 и графической оболочкой Plasma5 (впрочем, минимально наполненной) подставьте файл mkosi.conf вот отсюда: https://disk.360.yandex.ru/d/cPfQHdNrZpX82g
3.5 Запустите команду:
$ sudo mkosi --force
Во время сборки могут появляться отдельные незначительные ошибки, связанные с тем, что собирается предыдущая версия операционной системы, на которую скрипт не был изначально рассчитан. Но по окончании сборки образа вы должны увидеть сообщение вида:
‣ /home/mikhail/image-builder-main/device/raspberry/rpi5/rce.raw size is 6.5G, consumes 6.4G.
3.6. Необходимо отключить в свойствах файловой системы образа функцию orphan_file (она же FEATURE_C12).
Примонтируйте образ (файл raw) как устройство:
$ sudo losetup -P /dev/loop0 rosapi.raw
Убедитесь, что появились устройства для обоих разделов на образе диска:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 1G 0 loop
├─loop0p1 259:0 0 256M 0 part
└─loop0p2 259:1 0 815,9M 0 part
Отключите функцию orphan_file на большем (втором) разделе:
$ sudo tune2fs -O ^orphan_file /dev/loop0p2
tune2fs 1.47.2 (1-Jan-2025)
( tune2fs сделает работу молча, только напишет свою версию, да код возврата укажет на то, что она всё сделала успешно)
Размонтируйте образ диска:
$ sudo losetup -d /dev/loop0
4. Общие замечания к написанию программ.
4.1 Несовпадение разрешений экрана
Разрешение экрана, подключенного к Raspberry Pi и дисплея Р-ФОН, скорее всего, у вас будут существенно различаться.
У Р-Фон стандартное разрешение: 1080 x 2412
Некоторые графические инструментарии (например, Qt), сами подстраиваются под разрешение дисплея, и можно использовать один и тот же код как для компьютера, так и для телефона.
Другие же (например, GTK) не масштабируют самостоятельно элементы интерфейса, и нужно менять ход исполнения программы в зависимости от того, с каким разрешением она будет работать.
Разрешение экрана иногда лучше знать до того, как инициализируется графический инструментарий. Для этого можно воспользоваться библиотекой libdrm.
Пример кода программы, добывающей разрешение дисплея
// позаимствовано из https://twosixtech.com/blog/learning-libdrm/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <drm.h>
#include <drm_mode.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
char *device_path="/dev/dri/card0";
int main()
{
int result=0;
int fd = open(device_path, O_RDONLY);
if (fd < 0)
{
printf ("Не удалось открыть файл %s на чтение\n", device_path);
return -1;
}
drmModeRes *device = drmModeGetResources(fd);
if (!device)
{
printf ("Не удался вызов drmModeGetResources\n");
result=-1;
goto close;
}
// uint32_t
printf ("Максимальные размеры: %lu %lu\n", device->max_width, device->max_height);
// find first available connector
printf("Checking for first available plugged-in connector.\n");
drmModeConnector *first_available_connector;
bool found_connector = false;
for (int i = 0; i < device->count_connectors; i++) {
first_available_connector = drmModeGetConnector(fd, device->connectors[i]);
printf("%d\n", i);
if (first_available_connector->connection == DRM_MODE_CONNECTED) {
found_connector = true;
break;
} else {
drmModeFreeConnector(first_available_connector);
}
}
if(!found_connector) {
fprintf(stderr, "Couldn't find plugged-in connector!\n");
result=-1;
goto close;
}
// find first available CRTC
printf("Finding first available crtc\n");
if(!device->count_crtcs) {
fprintf(stderr, "No available CRTCs on first connector!");
result=-1;
goto close;
}
// find first available mode
printf("Checking for preferred mode.\n");
drmModeModeInfo *mode;
if(!first_available_connector->count_modes) {
fprintf(stderr, "No available modes on first connector!");
result=-1;
goto close;
}
bool found_preferred_mode = false;
for (int i = 0; i < first_available_connector->count_modes; i++) {
mode = &first_available_connector->modes[i];
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
found_preferred_mode = true;
break;
}
}
if (!found_preferred_mode) {
printf("Did not find preferred mode!\n");
result=-1;
goto close;
}
printf ("Предпочтительное разрешение: %u %u\n", mode->hdisplay, mode->vdisplay);
close:
close(fd);
return result;
}Для сборки используйте командную строку:
gcc drm.c -o drm -I/usr/include/drm -ldrm
Программа, естественно, работает как на Raspberry PI, так и на Р-Фон. Предлагаю использовать куски кода из этой программы в своём приложении для определения, с каким разрешением экрана оно будет работать.
4.2 Поворот экрана
В текущей прошивке (декабрь 2025 года) при повороте экрана менеджер окон поворачивает только два приложения: галерею и браузер.
Для того, чтобы ваше приложение также поворачивалось, сегодня есть только один способ: имя исполняемого файла должно были либо «koko» (как у Галереи), либо «angelfish», как у браузера.
В будущих прошивках ожидается более гибкий механизм.
4.3. Пакеты, необходимые для всех инструментариев
Практически для всех приведённых ниже примеров необходимо установить компиляторы С, С++ и программу make:
sudo dnf install gcc gcc-c++ make
4.4. X11 и Wayland
На сегодняшний день телефон поддерживает только Wayland, не пытайтесь запускать классические X11-приложения.
5. Программы, использующие Qt
Здесь всё просто. Если вы явно не задаёте размеры шрифтов или элементов управления, то программа будет отображаться единообразно на компьютере и на телефоне.
В примере ниже явно задан размер шрифта для надписи «Привет!», поэтому на экране телефона, имеющего большее разрешение, эта надпись выглядит уменьшенной.

Так выглядит приложение, запущенное на компьютере

Так выглядит то же приложение, запущенное на телефоне
Исходный код программы состоит из двух файлов: hello.pro и main.cpp
hello.pro
QT += core gui widgets
TARGET = hello
TEMPLATE = app
SOURCES += main.cppmain.cpp
#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDialog dialog;
dialog.setWindowTitle("Miha");
QLabel *logoLabel = new QLabel("Привет!");
logoLabel->setAlignment(Qt::AlignCenter);
logoLabel->setStyleSheet("font-size: 32px; font-weight: bold; color: #2c3e50;");
QLabel *messageLabel = new QLabel("<font color=red>Hello, World!</font>");
messageLabel->setAlignment(Qt::AlignCenter);
QPushButton *okButton = new QPushButton("OK");
QObject::connect(okButton, &QPushButton::clicked, &dialog, &QDialog::accept);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(logoLabel);
layout->addWidget(messageLabel);
layout->addWidget(okButton);
layout->setAlignment(Qt::AlignCenter);
dialog.setLayout(layout);
dialog.resize(250, 150);
dialog.show();
return app.exec();
}
Для сборки программы вам проще всего установить пакет qt-creator, который подтянет все другие необходимые пакеты.
sudo dnf install qt-creator
Сборку осуществляйте последовательным выполнением команд:
qmake5
make
На выходе получите исполняемый файл «hello», который, как и во всех остальных примерах, можете запускать как на Raspberry Pi, так и на Р-Фон.
6. Программы, использующие PyQt
Для примера я взял программу из статьи на Хабре: https://habr.com/ru/companies/skillfactory/articles/599599/
Перепечатывать здесь код программы не буду, единственное внесённое мною изменения – заменил цифру 6 на цифру 5, сделав из PyQt6 PyQt5.
Вам необходимо установить модуль python3-qt5
sudo dnf install python3-qt5
Одна и та же программа выглядит на RaspberryPi и на телефоне вот так:

Так выглядит приложение, запущенное на компьютере

Так выглядит то же приложение, запущенное на телефоне
7. Программы, использующие GTK 3
Если выставить переменную окружения GDK_SCALE=2 или GDK_DPI_SCALE=2, то программа при выполнении увеличит элементы интерфейса в 2 раза.
Благодаря этому свойству GTK 3 мне удалось запустить на телефоне ( в относительно удобоваримом виде) программу audacity, скачанную прямо из репозитария. Естественно, пользоваться ей на телефоне в таком виде сложно, но проиллюстрировать масштабирование это позволило.

Вы можете менять эту переменную окружения в самом начале программы (перед вызовом g_application_run ) функцией:
g_setenv("GDK_SCALE", "2", TRUE);
Ниже приведён пример программы, которую вы можете собрать сами.
Окно программы выглядит вот так:

Так выглядит приложение, запущенное на компьютере

Так выглядит то же приложение, запущенное на телефоне
Для сборки потребуются пакет gtk+3-devel :
sudo dnf install gtk+3-devel
Собрать программу можно командной строкой:
gcc 2.c -o 2 -I/usr/include/gtk-3.0 -I/usr/include/glib-2.0 -I//usr/lib64/glib-2.0/include -I/usr/include/pango-1.0/ -I/usr/include/harfbuzz/ -I/usr/include/cairo/ -I/usr/include/gdk-pixbuf-2.0/ -I/usr/include/atk-1.0/ -lgtk-3 -lgdk-3 -lglib-2.0 -lgobject-2.0
Исходный код программы, файл «2.с» :
#include <gtk/gtk.h>
gint count = 0;
char buf[5];
void increase(GtkWidget *widget, gpointer label)
{
count++;
sprintf(buf, "%d", count);
gtk_label_set_text(GTK_LABEL(label), buf);
}
void decrease(GtkWidget *widget, gpointer label)
{
count--;
sprintf(buf, "%d", count);
gtk_label_set_text(GTK_LABEL(label), buf);
}
int main(int argc, char** argv) {
setenv("GDK_DPI_SCALE","5",0);
GtkWidget *label;
GtkWidget *window;
GtkWidget *plus;
GtkWidget *minus;
GtkWidget *grid;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 250, 500);
gtk_window_set_title(GTK_WINDOW(window), "+-");
grid = gtk_grid_new();
plus = gtk_button_new_with_label("+");
gtk_grid_attach(GTK_GRID(grid), plus, 0, 0, 1, 1);
gtk_widget_set_valign(window,GTK_ALIGN_FILL);
minus = gtk_button_new_with_label("-");
gtk_grid_attach(GTK_GRID(grid), minus, 0, 3, 1, 1);
label = gtk_label_new("0");
gtk_grid_attach(GTK_GRID(grid), label, 2, 2, 1, 1);
gtk_container_add( GTK_CONTAINER(window), grid);
gtk_widget_show_all(window);
g_signal_connect(window, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect(plus, "clicked",
G_CALLBACK(increase), label);
g_signal_connect(minus, "clicked",
G_CALLBACK(decrease), label);
gtk_main();
return 0;
}
8. Программы, использующие GTK 4
Программы на GTK 4 не реагируют на переменные окружения, которыми мы управляли масштабом отображения в GTK 3.
Поэтому воспользуемся стилем CSS для получения нужного размера элементов отображения.
Окно программы выглядит вот так:

Так выглядит приложение, запущенное на компьютере

Так выглядит то же приложение, запущенное на телефоне
Для сборки потребуются пакет lib64gtk4.0-devel:
sudo dnf install lib64gtk4.0-devel
Собрать программу можно командной строкой (если не ошибаюсь):
gcc $( pkg-config --cflags gtk4 ) -o 4 4.c $( pkg-config --libs gtk4 )
Код программы 4.с
Код программы 4.с
#include <gtk/gtk.h>
static void activate(GtkApplication *app, gpointer user_data) {
// Добавлено в функцию activate():
GtkCssProvider *provider = gtk_css_provider_new();
const char *css = "button { min-height: 60px; min-width: 200px; font-size: 48px; }";
gtk_css_provider_load_from_data(provider, css, -1);
gtk_style_context_add_provider_for_display(
gdk_display_get_default(),
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
// Создаем главное окно
GtkWidget *window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "GTK4 Mobile App");
// Создаем вертикальный контейнер
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
gtk_widget_set_margin_top(box, 20);
gtk_widget_set_margin_bottom(box, 20);
gtk_widget_set_margin_start(box, 20);
gtk_widget_set_margin_end(box, 20);
// Создаем кнопки с увеличенными размерами
GtkWidget *button1 = gtk_button_new_with_label("Кнопка 1");
GtkWidget *button2 = gtk_button_new_with_label("Кнопка 2");
// Устанавливаем минимальные размеры кнопок
gtk_widget_set_size_request(button1, 200, 110);
gtk_widget_set_size_request(button2, 200, 110);
// Добавляем кнопки в контейнер
gtk_box_append(GTK_BOX(box), button1);
gtk_box_append(GTK_BOX(box), button2);
// Добавляем контейнер в окно
gtk_window_set_child(GTK_WINDOW(window), box);
gtk_widget_show(window);
}
int main(int argc, char **argv) {
// Создаем приложение
GtkApplication *app = gtk_application_new("com.example.gtkapp",
// G_APPLICATION_DEFAULT_FLAGS);
0);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
9. Программы, использующие SDL2
Тестовая программа составлена путём комбинирования обучающих материалов с сайта LazyFoo’ Productions ( https://lazyfoo.net/tutorials/SDL/index.php )
В одном куске кода проверялся:
рендеринг текстуры
реакция на нажатие мыши (или пальца в случае с телефоном)
проигрывание звука
Всё это сработало и на Raspberry Pi, и на Р-Фон.
В Raspberry Pi может не быть встроенного выхода звука, тогда можно проверить звук на HDMI-мониторе или же вонзить простейшую USB звуковую карту, как это сделал я. В моём случае – карта на чипе PCM2902.

Окно программы выглядит вот так:

Так выглядит приложение, запущенное на компьютере

Так выглядит то же приложение, запущенное на телефоне
Основные моменты, на которые следует обратить внимание:
1. В начале программы следует выставить переменную окружения, которая укажет на то, что нам нужен именно Wayland, а не X11
setenv("SDL_VIDEODRIVER","wayland",0);
2. Если нам не нужна экранная клавиатура, то сразу после SDL_Init вызываем:
SDL_StopTextInput();
Для сборки нам потребуются пакеты: SDL2-devel, SDL2_mixer-devel, SDL2_image-devel
sudo dnf install SDL2-devel SDL2_mixer-devel SDL2_image-devel
Сборка выполняется запуском в командной строке:
gcc 07.cpp -o 07 -I/usr/include/SDL2 -lSDL2 -lSDL2_image -lSDL2_mixer -lstdc++
Архив со всеми файлами (включая исходный код программы, звуковой файл и файл с текстурой) доступен для скачивания вот здесь:
https://disk.360.yandex.ru/d/4C20EML3ZdM-Iw
Исходный код программы 07.cpp
/*This source code copyrighted by Lazy Foo' Productions 2004-2024
and may not be redistributed without written permission.*/
//Using SDL, SDL_image, standard IO, and strings
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <stdio.h>
#include <string>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//Loads individual image as texture
SDL_Texture* loadTexture( std::string path );
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The sound effects that will be used
Mix_Chunk* gScratch = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Current displayed texture
SDL_Texture* gTexture = NULL;
bool init()
{
//Initialization flag
bool success = true;
// Пробуем установить переменную окружения
setenv("SDL_VIDEODRIVER","wayland",0);
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
// Попробуем запретить текстовый ввод
SDL_StopTextInput();
//Set texture filtering to linear
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
{
printf( "Warning: Linear texture filtering not enabled!" );
}
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create renderer for window
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
//Initialize SDL_mixer
if( Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048 ) < 0 )
{
printf( "SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError() );
success = false;
}
}
}
}
return success;
}
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load PNG texture
gTexture = loadTexture( "texture.png" );
if( gTexture == NULL )
{
printf( "Failed to load texture image!\n" );
success = false;
}
//Load sound effects
gScratch = Mix_LoadWAV( "scratch.wav" );
if( gScratch == NULL )
{
printf( "Failed to load scratch sound effect! SDL_mixer Error: %s\n", Mix_GetError() );
success = false;
}
return success;
}
void close()
{
//Free loaded image
SDL_DestroyTexture( gTexture );
gTexture = NULL;
//Free the sound effects
Mix_FreeChunk( gScratch );
gScratch = NULL;
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
SDL_Texture* loadTexture( std::string path )
{
//The final texture
SDL_Texture* newTexture = NULL;
//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
//Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
if( newTexture == NULL )
{
printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
}
//Get rid of old loaded surface
SDL_FreeSurface( loadedSurface );
}
return newTexture;
}
int main( int argc, char* args[] )
{
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() )
{
printf( "Failed to load media!\n" );
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
switch (e.type)
{
case SDL_MOUSEBUTTONDOWN:
Mix_PlayChannel( -1, gScratch, 0 );
break;
case SDL_QUIT:
quit = true;
break;
}
}
//Clear screen
SDL_RenderClear( gRenderer );
//Render texture to screen
SDL_RenderCopy( gRenderer, gTexture, NULL, NULL );
//Update screen
SDL_RenderPresent( gRenderer );
}
}
}
//Free resources and close SDL
close();
return 0;
}
10. Заключение
Лично мне оказалось удобнее сначала писать и отлаживать программу на x86 версии Роса Хром. Просто потому, что я привык работать на ноутбуке, который можно легко переносить с места на место. Если же вы всегда работаете на одном рабочем месте, то первый шаг с архитектурой x86 для вас будет излишним.

Лирическое отступление
Интересно, что работая на x86 и на ARM (она же aarch) версиях РОСА Хром, я не почувствовал никакой разницы. Даже странным показалось. Если раньше пересаживался, например, с PA-RISC на IBM Power, то приходилось переключаться на особенности их операционных систем. А здесь - ну прямо одно и то же.
Неоценимую помощь при написании статьи мне оказали сотрудники «НТЦ ИТ РОСА» Михаил Новосёлов и Олег Воробьёв.

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