Главная » 2008 » Июль » 14 » Промежуточное знакомство с функциями [Кодинг]
Промежуточное знакомство с функциями [Кодинг]
22:56
Многие из счастливых обладателей PSP, наверняка не раз задумывались: вот прогаю я для компа, или взламываю
всякие сайты - а вот клево было бы написать что-нибудь для своей
приставки. Например, ММОРПГ - при наличии Wi-Fi, неплохих графических
возможностей и удобного управления, созданного специально для игр, в
этой нише у карманной игровой станции странная пустота. Или тулзу для
взлома Wi-Fi сетей. Или брутер, который можно спокойно оставить на ночь
- потому что он не шумит, не жрет много электричества и не кишит
вирусами (кстати, тоже ведь идея!). Тем более, к PSP теперь можно
подсоединить всяческие фотоаппараты и микрофоны - в общем, гуляй - не
хочу.
Как
обычно зловещая корпорация не хочет, чтобы под их консоль штамповали
игры, не отчисляя ей ни копейки - тем более, основной доход идет именно
с процентов от продажи игр, а приставки частенько продаются по
себестоимости, или даже в убыль. Поэтому абсолютно легально не
получится не то что написать программу - да даже ее и запустить. Слава
хакерам - нашлись умельцы, давно взломавшие зловещую прошивку приставки
и убравшие из нее защиту (заодно врубив эмуляцию iso-образов игр,
потому что UMD-диски дороговато стоят... но я вам этого не говорил ;)).
Как получить такую версию прошивки расскажет pspfaqs.ru. Иди на этот
сайт и перепрошивайся до 3.90 М33-3, и не забудь установить ядро 1.50
(если у тебя "толстая" версия консоли) - иначе то, что у нас получится,
вполне может и не запуститься. Так что я буду считать, что ты это уже
сделал, и останавливаться на этом не стану.
Также тебе
понадобится карточка MemoryStick Duo. Идущая в комплекте должна вполне
подойти, хотя я бы посоветовал купить хотя бы на 2 гигабайта - для
программирования это очень много, но образы некоторых игр весят больше
1 Гб. Понадобится и шнур для соединения компа с приставкой (тоже есть в
комплекте, а если уже потерял - что, ты не найдешь Usb-2-MiniUsb?). Еще
из хардваре пригодится холодный, незамутненный разум хирурга, а то
вскрытие (программное, корпус открывать не будем) может завершиться
смертью или сумасшествием пациента.
Кстати, предупреждаю сразу:
ни я, ни редакция, ни - тем более - Sony не дает никаких гарантий, что
с приставкой все будет хорошо в результате наших анатомических
исследований. Она вполне может брикнуться (так бывалые псп-геймеры
называют таинственное превращение клевой приставки в черный, белый,
розовый - нужное подчеркнуть кирпич), заглючить, убить твою карточку
MemoryStick или, превратившись в НЛО, улететь на Луну оставлять там
будоражащие кровь в жилах надписи.
Но ни у меня, ни у тех на ком
я ставил свои противоестественные опыты, ничего такого не случилось.
Самое страшное, что было - это зависание намертво, которое лечится
обычным аварийным выключением: задержи рычажок выключения в позиции
Power секунд на 6-7, пока зеленая лампочка не перестанет мигать. Теперь
можешь включать.
В блокноте получается писать только на
JavaScript'е, что для наших целей не особо подходит, поэтому придется
скачать IDE и набор компиляторов. IDE я рекомендую Code::Blocks -
именно для этой IDE я опишу процесс настройки, а набор компиляторов,
под названием DevKitPSP. Я распаковал DevKitPSP в корень диска E:, так,
что у меня теперь есть папка E:\devkitpsp\, а в ней папки bin, include
и другие, и настройки буду указывать для этого пути - соответственно,
если у тебя путь окажется другой, его придется везде заменять. IDE
можно установить куда угодно, после чего запусти его и настрой (буду
давать сведения по настройке максимально сжато потому, что их много.
Утешает то, что придется сделать это один раз):
1. Settings -
Compiler and Debugger, Selected Compiler: GNU GCC, жмем Copy, называем
копию DevKitPSP, выбираем ее в списке компиляторов.
2. В том же окне - вкладка Search Directories - Compiler должна содержать только:
Compiler's installation directory: E:\devkitPSP C-compiler: psp-gcc.exe C++-compiler: psp-g++.exe Linker for dynamic libs: psp-g++.exe Linker for static libs: psp-ar.exe
Еще три поля там же оставляем пустыми, и жмем ОК.
4.
Создаем проект: File-New-Project..., Projects, Empty. Project Title
пусть будет PSPHelloWorld, указываем папку для сохранения проекта
где-нибудь на компьютере; компилятор ставим DevKitPSP.
5.
Cоздаем фаил File>New>File..., main.c — в мастере создания фаила
выбираем язык Си и ставим галочки "Add to current project", "Debug" и
"Release".
6. В созданный фаил копируем код из архива. Попозже разберемся, что он делает, а пока - донастроим проект и запустим его.
7.
Project-Properties, Build targets. Снимаем галочку "Auto-generate
filename extension", и правим в Output filename расширение "exe" на
"elf". Выполняем тоже самое для конфигурации Release, жмем Ok.
8. Project-Build Options, Linker Options, Other linker options:
Ура!
Можно жать на Build-Build и собирать проект, надеюсь - без ошибок. Так
мы получим elf-файл с программой. Но эльфы "грабят корованы" в юниксах,
а у нас странная ОС от PSP, готовая исполнять лишь файлы с милым
русскому человеку названием EBOOT.PBP. Для выполнения сложной операции
преобразования у меня есть волшебный bat-ник:
Разумеется,
запускать его надо с аргументом-именем твоего elf-фаила (без
расширения). Т.е., если у тебя получился HelloWorld.elf, то запускай
батник как my_batnik.bat HelloWorld. Ну а если ты противник таких вещей
- можешь вводить содержимое по строчке в консоль, заменяя %1 на имя
того файла.
Теперь у нас есть долгожданный EBOOT, и его мы
пихаем в папку /PSP/GAME150/HelloWorld/ нашей PSP-шки. После чего
запускаем его, громогласно приветствуя мир. Поздравляю! Вы написали
свою первую программу на PSP. Прежде чем закрывать IDE, советую
сохранить проект как шаблон (File-Save Project as user-template...) -
чтобы потом, при создании нового, не начинать все заново.
Как ты
уже наверное понял, функция pspDebugScreenPrintf() выводит текст на
экран. Она - полный аналог функции printf() и поддерживает ее форматную
строку. Я начал описывать код с нее, так как это - первая функция,
которой учат несчастных, изучающих Си. Вторая же изучаемая функция -
обычно scanf(), но ее для PSP нет - потому что нет клавиатуры. Поэтому
я просто расскажу, как получать состояние кнопок и джойстика.
За кнопки отвечает функция sceCtrlReadBufferPositive, описанная в фаиле pspctrl.h, так что добавляем в начало main.c строку:
#include
В
качестве параметров функция принимает указатель на структуру
SceCtrlData, в которую она возвратит данные о кнопках, и количество
буферов для чтения, так что вызывать мы ее будем так:
А вот - список кнопок, состояние которых появляется в битовой маске SceCtrlData::Buttons:
enum PspCtrlButtons { PSP_CTRL_SELECT = 0x000001, PSP_CTRL_START = 0x000008, PSP_CTRL_UP = 0x000010, PSP_CTRL_RIGHT = 0x000020, PSP_CTRL_DOWN = 0x000040, PSP_CTRL_LEFT = 0x000080, PSP_CTRL_LTRIGGER = 0x000100, PSP_CTRL_RTRIGGER = 0x000200, PSP_CTRL_TRIANGLE = 0x001000, PSP_CTRL_CIRCLE = 0x002000, PSP_CTRL_CROSS = 0x004000, PSP_CTRL_SQUARE = 0x008000, PSP_CTRL_HOME = 0x010000, PSP_CTRL_HOLD = 0x020000, PSP_CTRL_NOTE = 0x800000, // читается только в режиме ядра, т.е. // не судьба нам узнать о нажатии на нее PSP_CTRL_SCREEN = 0x400000, // только в режиме ядра PSP_CTRL_VOLUP = 0x100000,// только в режиме ядра PSP_CTRL_VOLDOWN = 0x200000,// только в режиме ядра PSP_CTRL_WLAN_UP = 0x040000,// только в режиме ядра PSP_CTRL_REMOTE = 0x080000,// только в режиме ядра PSP_CTRL_DISC = 0x1000000,// только в режиме ядра PSP_CTRL_MS = 0x2000000,// только в режиме ядра };
Как
использовать эти странные числа? А очень просто. Чтобы узнать, нажата
ли, скажем, кнопка с кружочком, нам надо проверить (pad.Buttons &
PSP_CTRL_CIRCLE). Т.е., например:
if (pad.Buttons & PSP_CTRL_CIRCLE) pspDebugScreenPrintf("CIRCLE PRESSED");
А
как использовать джойстик, можно догадаться и самому. Надо только
знать, что координаты его положения меняются от 0 до 255 (значит,
середина - в точке (128,128)), и не забывать, что он редко стоит прямо
по центру (на отклонение в несколько единиц лучше не обращать внимания,
позже ты увидишь, почему). Кстати, чтобы информация о положении
джойстика приходила, необходимо добавить вот такие строки:
Все.
Теперь мы знаем о кнопках все, что можем. И для примера можно написать
несложную программу, которая будет показывать, что в данный момент
нажато. Вот что получилось у меня (я, кстати, поленился и стал
мониторить только кнопки с рисунками, т.е. крестик, кружок, треугольник
и квадрат. Но не думаю, что у тебя возникнут какие-то проблемы с этим):
SceCtrlData pad;
int main(int argc, char ** argv) { pspDebugScreenInit();
// устанавливаем каллбеки SetupCallbacks();
sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); // настраиваем на прием информации о положении стика
while(1) // главный цикл программы { pspDebugScreenClear(); // чистим экран sceCtrlReadBufferPositive(&pad, 1); // читаем содержимое буфера э-э клавиатуры pspDebugScreenPrintf("TimeStamp %i | Pressed: ", pad.TimeStamp); // выводим TimeStamp if (pad.Buttons == 0) // ничего не нажато { pspDebugScreenPrintf("NONE "); } else { if (pad.Buttons & PSP_CTRL_TRIANGLE) pspDebugScreenPrintf("TRIANGLE "); if (pad.Buttons & PSP_CTRL_CIRCLE) pspDebugScreenPrintf("CIRCLE "); if (pad.Buttons & PSP_CTRL_CROSS) pspDebugScreenPrintf("CROSS "); if (pad.Buttons & PSP_CTRL_SQUARE) pspDebugScreenPrintf("SQUARE "); // какие кнопки нажаты? } pspDebugScreenPrintf("(%i) | Stick: %i:%in", pad.Buttons, pad.Lx, pad.Ly); // выводим координаты стика }
sceKernelSleepThread(); // поток засыпает // если уснули все потоки, то единственное, // что может случиться - это каллбек // в этой программе эта строчка никогда не выполнится ;)
return 0; }
Все
остальные функции лучше оставить такими, какие есть. Полную версию этой
программы с комментарием к каждой строчке можно найти в архиве.
Итак,
мы можем теперь выводить что угодно и узнавать, как на это реагирует
пользователь. Самое время портировать Moria или какую-нибудь змейку :)
Для полного текстового счастья не хватает, конечно же, цвета и
возможности писать где угодно. Ради цвета я бы посоветовал использовать
макрос, который я благополучно стырил откуда-то из хедеров к IDE:
typedef unsigned char byte; // определяем, потому что DevKitPSP понятия не имеет, // что есть такой тип #define RGB(r,g,b) ((u32)((byte)(r)|((byte)(g) << 8)|((byte)(b) << 16)))
Этот
макрос выдает цвет, подходящий к любым функциям, связанным с цветом
среди API PSP. Например, к функции установки фона для текста:
pspDebugScreenPutChar(100, 100, RGB(255, 0, 0), 'A'); // ставим красный символ 'A' в точку с координатами (100, 100)
Кстати, координаты задаются в пикселях, а не в строках и столбцах символов.
Ну
что ж, теперь ты можешь написать на экране PSP что угодно. Например,
проклятие черными буквами на черном фоне своему врагу, или другу-готу.
Или розовым по черному нарисовать ASCII-спанч боба. Или красным по
розовому признаться в любви своей девушке (парню?). Или... а, о чем я.
Решать тебе. Наслаждайся! А в следующей статье я постараюсь рассказать
про картинки. Хотя бы немножко ;)