ElfPack2: различия между версиями
(comment6 , http://forums3.mapletip.com/index.php?/user/91015-brandeusto/ order tramadol visa , http://gravatar.com/laurenceshonda generic tramadol no prescription cod , http://dailybooth.com/mrtrados/) | NoPH8 (обсуждение | вклад) м (Снята защита с «ElfPack2») | ||
(не показано 110 промежуточных версий 3 участников) | |||
Строка 1: | Строка 1: | ||
− | + | '''ElfPack2''' — это развитие предыдущей версии [[ElfPack]]-а для [[Motorola]], где учтён опыт его использования как со стороны конечного пользователя, так и со стороны разработчика [[ELF|эльфов]], исправлено множество моментов, досаждавших ранее, а также значительно расширена функциональность. | |
+ | |||
+ | |||
+ | == Отличия и нововведения == | ||
+ | |||
+ | ElfPack2 является улучшенной и полностью переработанной версией своего предшественника. Достаточно упомянуть, что объём кода увеличился почти в 4 раза, и при этом они не имеют общего кода. | ||
+ | |||
+ | *Для сборки эльфов используется компилятор GCC вместо ADS<br>Переход на GCC позволил реализовать полноценную систему импортов и динамических библиотек. | ||
+ | |||
+ | *Основная библиотека функций имеет более сложный формат, при этом в ней хранится её версия и версия прошивки, для которой библиотека предназначена. При этом библиотека может быть перезагружена в любой момент - для этого более не требуется перезагружать телефон. | ||
+ | |||
+ | *Исправлена недоработка, связанная с передачей параметров в эльф в виде char вместо WCHAR. | ||
+ | |||
+ | *Более совершенный обработчик auto.run | ||
+ | |||
+ | *Добавлена полноценная система импортов функций по их именам. Если ранее для этой цели использовались механизмы сомнительной надёжности, что не раз приводило к различным проблемам, то теперь процедура загрузки эльфа стала гораздо более надёжной. Это в том числе означает, что для каждого загружаемого эльфа проверяется наличие в библиотеках всех требуемых им функций, и выводится сообщение об ошибке, если обнаружены несоответствия. | ||
+ | |||
+ | *Добавлена "Консоль" - встроенное в ElfPack средство для вывода текстовой информации на дисплей. В основном используется для вывода информации самим ElfPack-ом, но ещё позволяет выводить информацию и эльфам. Консоль будет полезна для фоновых эльфов. | ||
+ | |||
+ | *Система callback-ов для вывода на дисплей средствами [[AHI]] ''параллельно'' с [[UIS]]. Таким, например, образом работает и Консоль. | ||
+ | |||
+ | *Shared libraries - так называют аналог DLL в [[Linux|линуксе]]. Это такие модули, содержащие функции, которые будучи однажды загружены в память, могут быть подлинкованы к различным эльфам. И также, как и с DLL, есть два варианта их подгрузки - статический и динамический. Первый подразумевает, что библиотека будет найдена и загружена в память в момент запуска эльфа. Второй означает, что эльф может загрузить любую библиотеку "на лету". Это позволяет вынести общий код, используемый сразу во множестве эльфов в отдельный модуль, который будет подгружен лишь единожды - получаем экономию памяти. Второе применение библиотек - возможность реализации полноценной системы плагинов. Shared libraries имеют расширение .so | ||
+ | |||
+ | *Для предоставления своей функциональности эльфам, в ElfPack2 предусмотрен API - набор интерфейсных функций. Их описание можно посмотреть в файле loader2.h SDK. | ||
+ | |||
+ | *Для настройки возможностей ElfPack2 есть конфигурационный файл, который находится в стандартном билде в /b/Elf2/elfpack.cfg | ||
+ | |||
+ | *В версии для E398 предусмотрена кнопка для пропуска обработки auto.run (настраивается при сборке эльфпакак, по умолчанию - "0") - полезно в случае добавления нерабочего эльфа в авторан. Просто зажмите нужную кнопку во время запуска телефона - и автозапуск обрабатываться не будет. Для других моделей - возможность ещё в разработке. Но, в любом случае, необходимо проверять эльфы на работоспособность запуском вручную, прежде чем добавлять их в автозапуск. | ||
+ | |||
+ | *В процесс сборки эльфа добавилось ещё одно звено - postlinker. Основная функция этой программы - подготовить эльф для загрузки в ElfPack2. Эльфы, не прошедшие такую обработку, запускаться не будут. Также postlinker создаёт стандартные библиотеки функий из sym-файлов. | ||
+ | |||
+ | *Важная особенность для русскоязычных разработчиков - теперь можно хранить исходники в кодировке UTF-8. За подробностями - ниже. | ||
+ | |||
+ | |||
+ | == Библиотека функций == | ||
+ | |||
+ | Для генерации библиотеки функций для EP2, необходимо: | ||
+ | |||
+ | <ol> | ||
+ | <li> | ||
+ | '''Postlinker<br> | ||
+ | |||
+ | Вызывается с ключом "<tt>-stdlib</tt>". | ||
+ | </li> | ||
+ | <li> | ||
+ | '''SYM-файл, точно в таком же формате, как раньше, за исключением того, что добавляется информация о константах<br> | ||
+ | |||
+ | Константами же считаются все коды ивентов, оффсеты в симах, FeatureID и т.п. прошивкозависимые значения.<br> | ||
+ | |||
+ | Каждая константа в библиотеке определяется своим идентификатором ''длиной 2 байта'', так что максимальное значение идентификатора - 0xFFFF(65535). Идентификаторы являются универсальными для всех прошивок и прописаны в SDK.<br> | ||
+ | |||
+ | В SYM-файле же константы описываются следующим образом:<br> | ||
+ | |||
+ | <tt><значение_константы> C <имя_константы></tt><br> | ||
+ | |||
+ | тоесть, в SYM-файле прописываются соответствия Value->Name.<br> | ||
+ | |||
+ | Например: | ||
+ | <pre> | ||
+ | 0xC100D C EV_MME_PLAY_COMPLETE | ||
+ | </pre> | ||
+ | </li> | ||
+ | |||
+ | <li> | ||
+ | '''DEF-файл со списком функций API EP2<br> | ||
+ | |||
+ | Этот файл может меняться только с новыми релизами EP2 и находится в репозитории libgen. | ||
+ | </li> | ||
+ | |||
+ | <li> | ||
+ | '''Заголовочный файл consts.h из SDK<br> | ||
+ | |||
+ | Для разрешения имён из SYM-файла в идентификаторы для занесения их в библиотеку, используется обычный заголовочный файл C, взятый прямо из SDK. Задаётся с помощью ключа "<tt>-header</tt>". В этом файле фактически прописаны соответствия Name->ID. Postlinker обрабатывает заголовочный файл и в результате построения цепочки соответствий Value->Name->ID, находит для каждой константы пары Значение-Идентификатор. Имена констант в результирующей библиотеке никак не отражаются, они используются лишь в SYM-файлах и в исходниках эльфов.<br> | ||
+ | |||
+ | Например: | ||
+ | <pre> | ||
+ | #define EV_MME_PLAY_COMPLETE 0x1504 | ||
+ | </pre> | ||
+ | В результирующей библиотеке значению 0xC100D будет соответствовать идентификатор 0x1504. | ||
+ | </li> | ||
+ | <li> | ||
+ | '''Немного информации о самой библиотеке<br> | ||
+ | |||
+ | Необходимо указать версию прошивки (и именно так, как прошивка сама себя идентифицирует) с помощью ключа -fw: | ||
+ | <pre>-fw R373_G_0E.30.49R | ||
+ | </pre> | ||
+ | |||
+ | А также строковую "версию" библиотеки (не больше 7 символов, без пробелов) с помощью ключа -v. Эту информацию ElfPack игнорирует и нужна она только чтобы отличать библиотеки для одной прошивки друг от друга, так что никаких требований (кроме длины и пробелов) на неё не накладывается: | ||
+ | <pre>-v ^_^Nya1 | ||
+ | </pre> | ||
+ | ''Все же очень настаиваю называть версии в формате YYMMDDN, YYMMDD = дата, N - номер за день по возрастанию. Требуется для сравнения версий либ и определения самой свежей эльфом SyncLib. ред.:[[Участник:Tim apple|Tim apple]] | ||
+ | </li> | ||
+ | </ol> | ||
+ | |||
+ | |||
+ | В результате команда для создания библиотеки (а также файла std.sa, необходимого только при сборке эльфов) будет выглядеть примерно так: | ||
+ | <pre> | ||
+ | postlink.exe -stdlib R373_G_0E.30.49R.sym -def ldrAPI.def -fw R373_G_0E.30.49R -v ^_^Nya1 -header ..\SDK\consts.h | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | А уже подготовленные образцы скриптов и файлов (а также собранный postlinker) Вы можете найти в Subversion (SVN) репозитории: | ||
+ | |||
+ | <tt>svn://svn.vilko.ru/libgen</tt> | ||
+ | |||
+ | О том, как пользоваться Subversion - в следующем разделе. | ||
+ | |||
+ | |||
+ | == Разработчикам == | ||
+ | |||
+ | Процесс разработки эльфов имеет ряд отличий от предыдущей версии. Это касается как исходного кода, так и процесса сборки. | ||
+ | |||
+ | Разработка самого эльфпака и ряда эльфов под него проводилось под контролем системы Subversion, её мы рекомендуем использовать и всем разработчикам. Адреса основных репозиториев: | ||
+ | |||
+ | |||
+ | <tt>svn://svn.vilko.ru/elfpack2</tt> - исходный код эльфпака | ||
+ | <tt>svn://andy.wtf.la/elfpack2</tt> - зеркало | ||
+ | |||
+ | <tt>svn://svn.vilko.ru/elfs2</tt> - исходные коды эльфов для него | ||
+ | |||
+ | <tt>svn://svn.vilko.ru/postlinker</tt> - Postlinker | ||
+ | |||
+ | <tt>svn://svn.vilko.ru/SDK</tt> - объединённый SDK | ||
+ | |||
+ | |||
+ | |||
+ | Все репозитории доступны для чтения с анонимным доступом. Если Вы желаете внести свой вклад, особенно в развитие SDK - обратитесь к администраторам репозиториев ('''Andy51''', '''tim apple''', '''Vilko'''). | ||
+ | |||
+ | {{Внимание|Как Вы могли заметить, появился репозиторий для SDK, а это значит, что разработчики ElfPack2 настоятельно рекомендуют пользоваться только данной версией и активно дополнять именно её всем разработчикам!}} | ||
+ | |||
+ | |||
+ | === Использование Subversion === | ||
+ | |||
+ | Если Вы не знаете, что это такое - можно ознакомиться, например, здесь: [http://ru.wikipedia.org/wiki/Subversion Subversion] | ||
+ | |||
+ | Также Вам понадобится клиент для работы с репозиториями: [http://tortoisesvn.net/downloads TortoiseSVN] | ||
+ | |||
+ | После установки клиента, чтобы скачать самые последние версии исходников с какого-либо репозитория: | ||
+ | #Cоздайте папку для проекта. | ||
+ | #Нажмите на ней правой кнопкой мыши и выберите "SVN Checkout..." | ||
+ | #В поле "URL of repository" введите адрес репозитория. Остальные настройки менять не нужно. | ||
+ | #Нажмите ОК. Исходники теперь будут закачиваться в текущую папку. | ||
+ | |||
+ | Чтобы обновить проект до самой последней версии из репозитория - выберите из контекстного меню папки с проектом "SVN Update". | ||
+ | |||
+ | == Инструментарий разработчика == | ||
+ | |||
+ | Как уже упоминалось ранее, для сборки эльфов используется '''GCC'''. А именно, набор [http://www.devkitpro.org devkitPro], который широко используется для разработки под GameBoy Advance, Nintendo DS, GP32, Playstation Portable и GameCube. Из его состава, правда, понадобится только devkitARM часть, которая также включает множество бесполезных для разработчика эльфов приложений и требует много трафика для скачки. Возможно, найдутся желающие сделать специальный пакет программ для разработчиков эльфов... И уже есть первая версия настроенной среды разработки, собранная тов. '''DmT''': [http://forum.motofan.ru/index.php?showtopic=169109 EDK] | ||
+ | |||
+ | Скачать установщик можно здесь: [http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/ Automated Installer] | ||
+ | |||
+ | |||
+ | === Сборка эльфа === | ||
+ | |||
+ | Пример простейшего скрипта для сборки эльфа (make.cmd): | ||
+ | <pre> | ||
+ | @echo off | ||
+ | |||
+ | del prelink.elf | ||
+ | |||
+ | arm-eabi-gcc -c -Wall -mbig-endian -mthumb -mthumb-interwork -I..\SDK -fshort-wchar -nostdlib -O -DEP2 helloworld_snd.c | ||
+ | arm-eabi-ld -pie -EB -O -nostdlib helloworld_snd.o std.sa -o prelink.elf | ||
+ | |||
+ | del /Q *.o | ||
+ | postlink prelink.elf -o helloworld_snd.elf | ||
+ | pause | ||
+ | </pre> | ||
+ | |||
+ | Некоторые пояснения: | ||
+ | *Ключ -I указывает относительный путь к SDK | ||
+ | *Файл std.sa выполняет функцию, аналогичную Lib.o предыдущей версии эльфпака | ||
+ | *Результат работы arm-eabi-ld мы передаём в postlink. Он создаёт результирующий файл res.elf - его мы переименовываем в helloworld_snd.elf и загружаем в телефон. | ||
+ | *Ключ -o у postlink задаёт имя результирующего файла | ||
+ | |||
+ | Для сборки C++ проекта используйте '''arm-eabi-g++''', а также добавьте следующие ключи: | ||
+ | <pre> | ||
+ | -fno-enforce-eh-specs -fno-rtti -fno-use-cxa-get-exception-ptr -fno-exceptions -fno-non-call-exceptions | ||
+ | </pre> | ||
+ | |||
+ | === Сборка shared library === | ||
+ | |||
+ | В общем случае, скрипт сборки аналогичен скрипту для обычного эльфа, за исключением: | ||
+ | <ol> | ||
+ | <li> | ||
+ | Используйте "<tt>-shared</tt>" вместо "<tt>-pie</tt>" | ||
+ | </li> | ||
+ | |||
+ | <li> | ||
+ | К строке линкера (arm-eabi-ld) добавляется "<tt>-soname=<внутреннее_имя_библиотеки></tt>" | ||
+ | </li> | ||
+ | |||
+ | <li> | ||
+ | К строке постлинкера добавляется ключ "<tt>-shared</tt>" и "<tt>-def <имя_def_файла></tt>" | ||
+ | |||
+ | Def-файл предназначен для определения списка функций и глобальных переменных (хотя вторые не рекомендуется делать доступными), к которым имеют доступ эльфы, подключающие данную библиотеку.<br><br> | ||
+ | |||
+ | Пример def-файла: | ||
+ | |||
+ | <pre> | ||
+ | testlibfn | ||
+ | sharedVar | ||
+ | </pre> | ||
+ | </li> | ||
+ | </ol> | ||
+ | |||
+ | Пример самой библиотеки можно посмотреть в репозитории svn://svn.vilko.ru/elfs2/libtest | ||
+ | |||
+ | |||
+ | == Различия в исходных кодах == | ||
+ | |||
+ | С различиями можно наглядно ознакомиться на примере helloworld из репозитория svn://svn.vilko.ru/elfs2/hw - важные участки кода отмечены #ifdef-ами. | ||
+ | |||
+ | |||
+ | === Больше всего изменения касаются функции - точки входа в эльф === | ||
+ | <br> | ||
+ | |||
+ | <ul> | ||
+ | <li>'''Необходимо объявить ''глобальную'' переменную типа ldrElf: | ||
+ | <ul><pre> | ||
+ | ldrElf elf; | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''Точка входа в эльф теперь имеет следующий вид (раньше называлась Register): | ||
+ | <ul><pre> | ||
+ | ldrElf* _start( WCHAR *uri, WCHAR *params ) | ||
+ | </pre></ul> | ||
+ | :Обратите внимание также на то, что параметры теперь передаются в неё как WCHAR*, что позволяет избежать проблем с путями, содержащими символы кроме латиницы, и на то, что reserve не передаётся. | ||
+ | </li> | ||
+ | |||
+ | <li>'''При необходимости, можно добавить проверку на то, был ли уже запущен эльф с таким именем: | ||
+ | <ul><pre> | ||
+ | if ( ldrIsLoaded( (char*)app_name ) ) | ||
+ | { | ||
+ | ... | ||
+ | // Если возвращаем NULL из _start - эльф удаляется из памяти | ||
+ | return NULL; | ||
+ | } | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''Вместо reserve, evcode_base можно получить так: | ||
+ | <ul><pre> | ||
+ | evcode_base = ldrRequestEventBase( ); | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''В ElfPack2 важные константы берутся из библиотеки функций. К ним также относятся и все коды ивентов. | ||
+ | :А конкретно механизм выглядит так - на этапе компиляции в таблицы ивентов (any_state_handlers, например) заносятся не сами значения ивентов, а их идентификаторы. С точки зрения кода в этом месте ничего не меняется - подмена никак не отражается. А вот чтобы идентификаторы заменились на реальные значения, необходимо вызвать для каждой таблицы функцию ldrInitEventHandlersTbl ДО вызова APP_Register. | ||
+ | <ul><pre> | ||
+ | // Функция не модифицирует evcode_base, но возвращает новое значение базы - поэтому присваивание | ||
+ | evcode_base = ldrInitEventHandlersTbl( any_state_handlers, evcode_base ); | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''Вместо LdrStartApp используется ldrSendEvent: | ||
+ | <ul><pre> | ||
+ | ldrSendEvent( evcode_base ); | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''Необходимо поместить в объявленную ранее переменную типа ldrElf имя текущего эльфа и возвратить указатель на неё: | ||
+ | <ul><pre> | ||
+ | elf.name = (char*)app_name; | ||
+ | return &elf; | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | </ul> | ||
+ | |||
+ | <br> | ||
+ | === Также обратите внимание на следующие общие изменения === | ||
+ | <br> | ||
+ | |||
+ | <ul> | ||
+ | <li>'''В функции старта приложения (в примере - HelloWorldStart) необходимо записать в структуру elf указатель на созданное [[Application|приложение]]. | ||
+ | :Этим мы сообщаем эльфпаку, что эльф начал свою работу как приложение. | ||
+ | <ul><pre> | ||
+ | elf.app = app; | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''Функции выгрузки эльфа из памяти теперь не требуются какие-либо параметры: | ||
+ | <ul><pre> | ||
+ | // Название сменилось - теперь с маленькой буквы! | ||
+ | ldrUnloadElf(); | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''Никаких структур вроде APP_HELLOWORLD_T (в helloworld_snd.h) объявлять не нужно. | ||
+ | :В прошивке это - необходимая особенность приложений, работающих прямо из ROM-памяти. В этой структуре размещаются глобальные переменные для приложения. А так как эльфы выполняются из RAM - они могут создавать обычные глобальные переменные. | ||
+ | </li> | ||
+ | |||
+ | <li>'''В обработчиках сообщений вторым параметром вместо void *app передаётся APPLICATION_T *app, что позволяет избавиться от ненужных преобразований типов, сравните: | ||
+ | <ul><pre> | ||
+ | // EP1: | ||
+ | UINT32 HandleUITokenGranted( EVENT_STACK_T *ev_st, void *app ) | ||
+ | { | ||
+ | APPLICATION_T *papp = (APPLICATION_T*) app; | ||
+ | status = APP_ExitStateAndApp( ev_st, app, 0 ); | ||
+ | ... | ||
+ | |||
+ | // EP2: | ||
+ | UINT32 HandleUITokenGranted( EVENT_STACK_T *ev_st, APPLICATION_T *app ) | ||
+ | { | ||
+ | status = APP_ExitStateAndApp( ev_st, app, 0 ); | ||
+ | ... | ||
+ | </pre></ul> | ||
+ | </li> | ||
+ | |||
+ | <li>'''Некоторые заголовочные файлы переименованы для совместимости с Visual Studio (для [[EmuElf]]): | ||
+ | *stdarg.h -> stdargs.h | ||
+ | *util.h -> utilities.h | ||
+ | *memory.h -> mem.h | ||
+ | </li> | ||
+ | |||
+ | <li>'''Исходники можно (и рекомендуется) сохранять в кодировке UTF-8: | ||
+ | :При этом будет корректно обрабатываться, например, такой код, содержащий кириллические символы: | ||
+ | |||
+ | <ul> | ||
+ | <pre> | ||
+ | WCHAR *str = L"Привет"; | ||
+ | </pre> | ||
+ | Больше не нужно вводить такие строки посимвольно, а также для эльфов отпадёт проблема т.н. "неправильного ленга с кракозябрами". | ||
+ | Кто сталкивался с этим - поймёт. | ||
+ | </ul> | ||
+ | </li> | ||
+ | |||
+ | </ul> | ||
+ | |||
+ | |||
+ | == Заключение == | ||
+ | |||
+ | Прогресс не стоит на месте, не стоит и нам с Вами - пора переходить на более совершенную технологию и постепенно отправить устаревший ElfPack1 в архив. | ||
+ | |||
+ | Тем более, что в новой версии для пользователей предоставляется значительно больше возможностей, а разработчикам нужно приложить относительно немного усилий для портирования своих эльфов на EP2. | ||
+ | |||
+ | |||
+ | [[Категория:Эльфостроение]] |
Текущая версия на 17:19, 9 октября 2011
ElfPack2 — это развитие предыдущей версии ElfPack-а для Motorola, где учтён опыт его использования как со стороны конечного пользователя, так и со стороны разработчика эльфов, исправлено множество моментов, досаждавших ранее, а также значительно расширена функциональность.
Содержание
Отличия и нововведения
ElfPack2 является улучшенной и полностью переработанной версией своего предшественника. Достаточно упомянуть, что объём кода увеличился почти в 4 раза, и при этом они не имеют общего кода.
- Для сборки эльфов используется компилятор GCC вместо ADS
Переход на GCC позволил реализовать полноценную систему импортов и динамических библиотек.
- Основная библиотека функций имеет более сложный формат, при этом в ней хранится её версия и версия прошивки, для которой библиотека предназначена. При этом библиотека может быть перезагружена в любой момент - для этого более не требуется перезагружать телефон.
- Исправлена недоработка, связанная с передачей параметров в эльф в виде char вместо WCHAR.
- Более совершенный обработчик auto.run
- Добавлена полноценная система импортов функций по их именам. Если ранее для этой цели использовались механизмы сомнительной надёжности, что не раз приводило к различным проблемам, то теперь процедура загрузки эльфа стала гораздо более надёжной. Это в том числе означает, что для каждого загружаемого эльфа проверяется наличие в библиотеках всех требуемых им функций, и выводится сообщение об ошибке, если обнаружены несоответствия.
- Добавлена "Консоль" - встроенное в ElfPack средство для вывода текстовой информации на дисплей. В основном используется для вывода информации самим ElfPack-ом, но ещё позволяет выводить информацию и эльфам. Консоль будет полезна для фоновых эльфов.
- Система callback-ов для вывода на дисплей средствами AHI параллельно с UIS. Таким, например, образом работает и Консоль.
- Shared libraries - так называют аналог DLL в линуксе. Это такие модули, содержащие функции, которые будучи однажды загружены в память, могут быть подлинкованы к различным эльфам. И также, как и с DLL, есть два варианта их подгрузки - статический и динамический. Первый подразумевает, что библиотека будет найдена и загружена в память в момент запуска эльфа. Второй означает, что эльф может загрузить любую библиотеку "на лету". Это позволяет вынести общий код, используемый сразу во множестве эльфов в отдельный модуль, который будет подгружен лишь единожды - получаем экономию памяти. Второе применение библиотек - возможность реализации полноценной системы плагинов. Shared libraries имеют расширение .so
- Для предоставления своей функциональности эльфам, в ElfPack2 предусмотрен API - набор интерфейсных функций. Их описание можно посмотреть в файле loader2.h SDK.
- Для настройки возможностей ElfPack2 есть конфигурационный файл, который находится в стандартном билде в /b/Elf2/elfpack.cfg
- В версии для E398 предусмотрена кнопка для пропуска обработки auto.run (настраивается при сборке эльфпакак, по умолчанию - "0") - полезно в случае добавления нерабочего эльфа в авторан. Просто зажмите нужную кнопку во время запуска телефона - и автозапуск обрабатываться не будет. Для других моделей - возможность ещё в разработке. Но, в любом случае, необходимо проверять эльфы на работоспособность запуском вручную, прежде чем добавлять их в автозапуск.
- В процесс сборки эльфа добавилось ещё одно звено - postlinker. Основная функция этой программы - подготовить эльф для загрузки в ElfPack2. Эльфы, не прошедшие такую обработку, запускаться не будут. Также postlinker создаёт стандартные библиотеки функий из sym-файлов.
- Важная особенность для русскоязычных разработчиков - теперь можно хранить исходники в кодировке UTF-8. За подробностями - ниже.
Библиотека функций
Для генерации библиотеки функций для EP2, необходимо:
- Postlinker
Вызывается с ключом "-stdlib". - SYM-файл, точно в таком же формате, как раньше, за исключением того, что добавляется информация о константах
Константами же считаются все коды ивентов, оффсеты в симах, FeatureID и т.п. прошивкозависимые значения.
Каждая константа в библиотеке определяется своим идентификатором длиной 2 байта, так что максимальное значение идентификатора - 0xFFFF(65535). Идентификаторы являются универсальными для всех прошивок и прописаны в SDK.
В SYM-файле же константы описываются следующим образом:
<значение_константы> C <имя_константы>
тоесть, в SYM-файле прописываются соответствия Value->Name.
Например:0xC100D C EV_MME_PLAY_COMPLETE
- DEF-файл со списком функций API EP2
Этот файл может меняться только с новыми релизами EP2 и находится в репозитории libgen. - Заголовочный файл consts.h из SDK
Для разрешения имён из SYM-файла в идентификаторы для занесения их в библиотеку, используется обычный заголовочный файл C, взятый прямо из SDK. Задаётся с помощью ключа "-header". В этом файле фактически прописаны соответствия Name->ID. Postlinker обрабатывает заголовочный файл и в результате построения цепочки соответствий Value->Name->ID, находит для каждой константы пары Значение-Идентификатор. Имена констант в результирующей библиотеке никак не отражаются, они используются лишь в SYM-файлах и в исходниках эльфов.
Например:#define EV_MME_PLAY_COMPLETE 0x1504
В результирующей библиотеке значению 0xC100D будет соответствовать идентификатор 0x1504.
- Немного информации о самой библиотеке
Необходимо указать версию прошивки (и именно так, как прошивка сама себя идентифицирует) с помощью ключа -fw:-fw R373_G_0E.30.49R
А также строковую "версию" библиотеки (не больше 7 символов, без пробелов) с помощью ключа -v. Эту информацию ElfPack игнорирует и нужна она только чтобы отличать библиотеки для одной прошивки друг от друга, так что никаких требований (кроме длины и пробелов) на неё не накладывается:
-v ^_^Nya1
Все же очень настаиваю называть версии в формате YYMMDDN, YYMMDD = дата, N - номер за день по возрастанию. Требуется для сравнения версий либ и определения самой свежей эльфом SyncLib. ред.:Tim apple
В результате команда для создания библиотеки (а также файла std.sa, необходимого только при сборке эльфов) будет выглядеть примерно так:
postlink.exe -stdlib R373_G_0E.30.49R.sym -def ldrAPI.def -fw R373_G_0E.30.49R -v ^_^Nya1 -header ..\SDK\consts.h
А уже подготовленные образцы скриптов и файлов (а также собранный postlinker) Вы можете найти в Subversion (SVN) репозитории:
О том, как пользоваться Subversion - в следующем разделе.
Разработчикам
Процесс разработки эльфов имеет ряд отличий от предыдущей версии. Это касается как исходного кода, так и процесса сборки.
Разработка самого эльфпака и ряда эльфов под него проводилось под контролем системы Subversion, её мы рекомендуем использовать и всем разработчикам. Адреса основных репозиториев:
svn://svn.vilko.ru/elfpack2 - исходный код эльфпакаsvn://andy.wtf.la/elfpack2 - зеркало
svn://svn.vilko.ru/elfs2 - исходные коды эльфов для него
svn://svn.vilko.ru/postlinker - Postlinker
svn://svn.vilko.ru/SDK - объединённый SDK
Все репозитории доступны для чтения с анонимным доступом. Если Вы желаете внести свой вклад, особенно в развитие SDK - обратитесь к администраторам репозиториев (Andy51, tim apple, Vilko).
Как Вы могли заметить, появился репозиторий для SDK, а это значит, что разработчики ElfPack2 настоятельно рекомендуют пользоваться только данной версией и активно дополнять именно её всем разработчикам!
Использование Subversion
Если Вы не знаете, что это такое - можно ознакомиться, например, здесь: Subversion
Также Вам понадобится клиент для работы с репозиториями: TortoiseSVN
После установки клиента, чтобы скачать самые последние версии исходников с какого-либо репозитория:
- Cоздайте папку для проекта.
- Нажмите на ней правой кнопкой мыши и выберите "SVN Checkout..."
- В поле "URL of repository" введите адрес репозитория. Остальные настройки менять не нужно.
- Нажмите ОК. Исходники теперь будут закачиваться в текущую папку.
Чтобы обновить проект до самой последней версии из репозитория - выберите из контекстного меню папки с проектом "SVN Update".
Инструментарий разработчика
Как уже упоминалось ранее, для сборки эльфов используется GCC. А именно, набор devkitPro, который широко используется для разработки под GameBoy Advance, Nintendo DS, GP32, Playstation Portable и GameCube. Из его состава, правда, понадобится только devkitARM часть, которая также включает множество бесполезных для разработчика эльфов приложений и требует много трафика для скачки. Возможно, найдутся желающие сделать специальный пакет программ для разработчиков эльфов... И уже есть первая версия настроенной среды разработки, собранная тов. DmT: EDK
Скачать установщик можно здесь: Automated Installer
Сборка эльфа
Пример простейшего скрипта для сборки эльфа (make.cmd):
@echo off del prelink.elf arm-eabi-gcc -c -Wall -mbig-endian -mthumb -mthumb-interwork -I..\SDK -fshort-wchar -nostdlib -O -DEP2 helloworld_snd.c arm-eabi-ld -pie -EB -O -nostdlib helloworld_snd.o std.sa -o prelink.elf del /Q *.o postlink prelink.elf -o helloworld_snd.elf pause
Некоторые пояснения:
- Ключ -I указывает относительный путь к SDK
- Файл std.sa выполняет функцию, аналогичную Lib.o предыдущей версии эльфпака
- Результат работы arm-eabi-ld мы передаём в postlink. Он создаёт результирующий файл res.elf - его мы переименовываем в helloworld_snd.elf и загружаем в телефон.
- Ключ -o у postlink задаёт имя результирующего файла
Для сборки C++ проекта используйте arm-eabi-g++, а также добавьте следующие ключи:
-fno-enforce-eh-specs -fno-rtti -fno-use-cxa-get-exception-ptr -fno-exceptions -fno-non-call-exceptions
В общем случае, скрипт сборки аналогичен скрипту для обычного эльфа, за исключением:
- Используйте "-shared" вместо "-pie"
- К строке линкера (arm-eabi-ld) добавляется "-soname=<внутреннее_имя_библиотеки>"
- К строке постлинкера добавляется ключ "-shared" и "-def <имя_def_файла>"
Def-файл предназначен для определения списка функций и глобальных переменных (хотя вторые не рекомендуется делать доступными), к которым имеют доступ эльфы, подключающие данную библиотеку.
Пример def-файла:testlibfn sharedVar
Пример самой библиотеки можно посмотреть в репозитории svn://svn.vilko.ru/elfs2/libtest
Различия в исходных кодах
С различиями можно наглядно ознакомиться на примере helloworld из репозитория svn://svn.vilko.ru/elfs2/hw - важные участки кода отмечены #ifdef-ами.
Больше всего изменения касаются функции - точки входа в эльф
- Необходимо объявить глобальную переменную типа ldrElf:
ldrElf elf;
ldrElf* _start( WCHAR *uri, WCHAR *params )
- Обратите внимание также на то, что параметры теперь передаются в неё как WCHAR*, что позволяет избежать проблем с путями, содержащими символы кроме латиницы, и на то, что reserve не передаётся.
if ( ldrIsLoaded( (char*)app_name ) ) { ... // Если возвращаем NULL из _start - эльф удаляется из памяти return NULL; }
evcode_base = ldrRequestEventBase( );
- А конкретно механизм выглядит так - на этапе компиляции в таблицы ивентов (any_state_handlers, например) заносятся не сами значения ивентов, а их идентификаторы. С точки зрения кода в этом месте ничего не меняется - подмена никак не отражается. А вот чтобы идентификаторы заменились на реальные значения, необходимо вызвать для каждой таблицы функцию ldrInitEventHandlersTbl ДО вызова APP_Register.
// Функция не модифицирует evcode_base, но возвращает новое значение базы - поэтому присваивание evcode_base = ldrInitEventHandlersTbl( any_state_handlers, evcode_base );
ldrSendEvent( evcode_base );
elf.name = (char*)app_name; return &elf;
Также обратите внимание на следующие общие изменения
- В функции старта приложения (в примере - HelloWorldStart) необходимо записать в структуру elf указатель на созданное приложение.
- Этим мы сообщаем эльфпаку, что эльф начал свою работу как приложение.
elf.app = app;
// Название сменилось - теперь с маленькой буквы! ldrUnloadElf();
- В прошивке это - необходимая особенность приложений, работающих прямо из ROM-памяти. В этой структуре размещаются глобальные переменные для приложения. А так как эльфы выполняются из RAM - они могут создавать обычные глобальные переменные.
// EP1: UINT32 HandleUITokenGranted( EVENT_STACK_T *ev_st, void *app ) { APPLICATION_T *papp = (APPLICATION_T*) app; status = APP_ExitStateAndApp( ev_st, app, 0 ); ... // EP2: UINT32 HandleUITokenGranted( EVENT_STACK_T *ev_st, APPLICATION_T *app ) { status = APP_ExitStateAndApp( ev_st, app, 0 ); ...
- stdarg.h -> stdargs.h
- util.h -> utilities.h
- memory.h -> mem.h
- При этом будет корректно обрабатываться, например, такой код, содержащий кириллические символы:
WCHAR *str = L"Привет";
Больше не нужно вводить такие строки посимвольно, а также для эльфов отпадёт проблема т.н. "неправильного ленга с кракозябрами". Кто сталкивался с этим - поймёт.
Заключение
Прогресс не стоит на месте, не стоит и нам с Вами - пора переходить на более совершенную технологию и постепенно отправить устаревший ElfPack1 в архив.
Тем более, что в новой версии для пользователей предоставляется значительно больше возможностей, а разработчикам нужно приложить относительно немного усилий для портирования своих эльфов на EP2.