|
|
Спасибо за пост: 4 |
#1 Добавлено: 4 мая 2008 14:56 |
|
|
|
|
Забанен
LIon__
--
Возраст: 32 |  |
Сообщений: 377
Благодарности: 22 / 55
Репутация: 9
Предупреждений: 1
Друзья
Тут: 17 лет 3 месяцa
|
|
Забудьте про тупые проги!! Зарание извеяюсь за ошибки:) Сайт там где полно уроков и самодельные проги(англиский) туттам всё по англиски так что читайте лучше мою статью: Программируем для PSP: Часть I, настройка компилятора Давайте условимся сразу: я следую паттерну "изучение обучением", т.е. учу, одновременно изучая, обгоняя читателей на 2-3 "шага" вперед. Однако это не значит, что я ничего не знаю и все, что говорю - обычные копипасты: я стараюсь разобраться в теме, прежде чем писать о ней. Поэтому смело задавайте вопросы, этим вы принесете пользу и себе, и мне: на вопросы, ответ на которые я не знаю, я буду его искать, осозновать и рассказывать вам. Итак, в этом топике будет небольшой рассказ о том, как скомпилировать и запустить первую программу на своей приставке. Сразу предупреждение: статья мегатехнического плана, почти все содержание касается утомительной, но быстрой настройки компилятора, а в результате вы получите лишь банальный "Hello World". Однако без нее никак. Будем предполагать как данность, что у вас есть приставка Sony PSP, перепрошитая до последней версии - 3.90 M33-3 (так называемая custom firmware, неофициальная прошивка). О том, как перепрошиваться, уже рассказывали многие, и останавливаться на этом я не буду. Так же будем считать, что в кирпич ваш вставлена флешка, на которой есть хотя бы 50кб свободного места, и вы имеете к ним доступ (например, через саму PSP). Скажу сразу: я почти уверен, что ничего плохого с вашей приставкой не случится, если вы будете достаточно аккуратны, но никаких гарантий дать, к сожалению, не могу. Используемый язык программирования -- Си, я буду использовать бесплатную IDE Code::Blocks под Windows XP. Пользователи других компиляторов или ОС могут попробовать настроить IDE сами, благо, настройки у всех похожи; я же использовал то, для чего нашел мануал ;) Для начала, скачаем набор компиляторов, линкеров и библиотек для PSP под названием DevKitPSP. Распакуйте его куда-нибудь, я его распаковал в корень диска E: (теперь у меня есть папка E:devkitpsp). Теперь откройте Code::Blocks. В меню выберите Settings→Compiler and Debugger, как Selected Compiler в открывшемся окошке выберите GNU GCC (он должен стоять по умолчанию), скопируйте его, назвав, например, DevKitPSP, и настройте его: Вкладка Search Directories→Compiler (удалите все, что там есть, и нажимайте Add для добавления каждого из путей): E:devkitPSPinclude E:devkitPSPpspinclude E:devkitPSPpspsdkincludeLinker: E:devkitPSPlib E:devkitPSPpsplib E:devkitPSPpspsdklibВкладка Toolchain Executables: Compiler's installation directory: E:devkitPSP . Там есть примечание, что в этой папке должна быть подпапка bin, проверьте. C-compiler: psp-gcc.exe C++-compiler: psp-g++.exe Linker for dynamic libs: psp-g++.exe Linker for static libs: psp-ar.exe Еще три поля я оставил пустыми.Теперь можно жать OK, и переходить к созданию нового проекта (File→New→Project..., слева в окошке жмем Projects и выбираем Empty). Заполняем Project Title (не играет роли, пусть будет PSPHelloWorld), не забываем поставить папку для сохранения проекта (я вон в первый раз забыл, и получил кучу глюков и ошибок); компилятор, разумеется, ставим свежесозданный нами. Наш проект девственно пуст, создаем фаил (File→New→File..., на название наплевать, я выбрал main.c) -- не забудьте в мастере создания фаила выбрать как язык Си и поставить галочки "Add to current project", "Debug" и "Release" (почему они не стоят по умолчанию?). В созданный фаил копируем код: #include
#include
PSP_MODULE_INFO("Hello World", 0, 1, 1); int ExitCallback(int Arg1, int Arg2, void *Common) { sceKernelExitGame(); return 0; }
int CallbackThread(SceSize Args, void *Argp) { int CallbackId; CallbackId = sceKernelCreateCallback("Exit Callback", ExitCallback, NULL); sceKernelRegisterExitCallback(CallbackId); sceKernelSleepThreadCB(); return 0; }
int SetupCallbacks(void) { int ThreadId = 0; ThreadId = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0); if (ThreadId >= 0) { sceKernelStartThread(ThreadId, 0, 0); } return ThreadId; } int main(int argc, char ** argv) { pspDebugScreenInit(); SetupCallbacks(); while(1) { pspDebugScreenPrintf ("Hello World"); sceDisplayWaitVblankStart(); } sceKernelSleepThread(); return 0; }
Код писал не я, кстати: опыта пока-что маловато, хотя я вполне понимаю, что там происходит и как - в любом случае, в этом топике я останавливаться на этом не буду. Теперь последние штрихи к настройке. Мы уже настроили то, с помощью чего будем компилировать, но не настроили, как и что у нас должно выходить. Поэтому жмем правой кнопкой на название проекта справа, выбираем Properties, а там -- Build targets. Снимаем галочку "Auto-generate filename extension", и правим в Output filename расширение "exe" на "elf". Выполняем тоже самое для конфигурации Release, жмем Ok. Жмем правой кнопкой на название проекта опять, выбираем Build Options и, на вкладке Linker Options, вписываем в Other linker options: -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lpsplibc -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel. Повторяем для Release. Вроде всё (надеюсь, это последняя статья скучного технического плана). Теперь собираем проект (Build→Build или знакомое всем Ctrl-F9) -- если вдруг появились ошибки, то думаем, что же сделали не так, а потом спрашиваем в комментариях (может, я забыл чего). Чтобы не настраивать потом заново, стоит сохранить проект как шаблон (File→Save Project as user-template...). Итак, у нас есть elf-фаил нашей программы. Перед тем, как закидывать его на PSP, надо преобразовать его в EBOOT.PBP (название придумал не я, честно). Для этого у меня стоит такой bat-ник: "E:devkitPSPbinmksfo.exe" %1/bin/Debug/%1 %1/bin/Debug/%1.sfo "E:devkitPSPbinpsp-fixup-imports.exe" %1/bin/Debug/%1.elf "E:devkitPSPbinpsp-strip.exe" %1/bin/Debug/%1.elf -o %1/bin/Debug/stripped.elf "E:devkitPSPbinpack-pbp.exe" %1/bin/Debug/EBOOT.PBP %1/bin/Debug/%1.sfo NULL NULL NULL NULL NULL %1/bin/Debug/stripped.elf NULLОн располагается у меня в директории pspprj, в которой я создаю по папке для каждого проекта. Используется он так: make_eboot.bat HelloWorld . Если у вас другая организация папок, или вы просто хотите его переписать или запускать каждую программу вручную -- просто запускайте по строчке, не забывая заменять %1 на названия или пути к фаилам. В результате у вас получится фаил EBOOT.PBP, его надо будет закинуть в папку /PSP/GAME150/HelloWorld (или другое название)/, а все остальное можно спокойно удалить. Теперь проверяйте (выход -- по кнопке Home). Как "домашнее задание" -- сделайте так, чтобы все "хелловорлды" были с новой строки. До встречи! P.S. Вырезал весь "юмор", который сначала вписывал. Всегда самого раздражали тупые шутки в такого рода постах, а в том, что мои шутки не тупы, я быть уверен не могу :) Остальные части щя выложу:)  , ток ошибки исправлю:)
|
|
|
|
Спасибо за пост: 1 |
#2 Добавлено: 4 мая 2008 15:49 |
|
|
|
|
Посетители
вафля
--
Возраст: 31 |  |
Сообщений: 17
Благодарности: 1 / 1
Репутация: 0
Предупреждений: 0
Друзья
Тут: 17 лет 2 месяцa
|
|
|
|
|
|
|
#3 Добавлено: 4 мая 2008 16:49 |
|
|
|
|
Забанен
LIon__
--
Возраст: 32 |  |
Сообщений: 377
Благодарности: 22 / 55
Репутация: 9
Предупреждений: 1
Друзья
Тут: 17 лет 3 месяцa
|
|
|
|
|
|
|
#4 Добавлено: 5 мая 2008 16:16 |
|
|
|
|
Забанен
Gramoboi
--
Возраст: 35 |  |
Сообщений: 40
Благодарности: 0 / 6
Репутация: 0
Предупреждений: 1
Друзья
Тут: 17 лет 6 месяцев
|
|
да было дела занимался но забил ((((.........
|
|
|
|
|
#5 Добавлено: 7 мая 2008 13:27 |
|
|
|
|
Посетители
F.G.M.
--
Возраст: -- |  |
Сообщений: 27
Благодарности: 3 / 2
Репутация: 0
Предупреждений: 0
Друзья
Тут: 17 лет
|
|
LIon__, класная тема, спасибо, буду ждать следующих уроков
|
|
|
|
|
#6 Добавлено: 10 мая 2008 15:24 |
|
|
|
|
Посетители
pspalexx
--
Возраст: 36 |  |
Сообщений: 57
Благодарности: 0 / 1
Репутация: 0
Предупреждений: 0
Друзья
Тут: 17 лет 2 месяцa
|
|
LIon__, прекрасная тема, я как раз sdk установил пару дней назад, правда на Linux
Добавлено спустя 15 минут 49 секунд:
LIon__, ты случайно не знаешь чем распаковать Eboot.pbp под Linux (PPC)?
|
|
|
|
Спасибо за пост: 1 |
#7 Добавлено: 11 мая 2008 00:06 |
|
|
|
|
Забанен
LIon__
--
Возраст: 32 |  |
Сообщений: 377
Благодарности: 22 / 55
Репутация: 9
Предупреждений: 1
Друзья
Тут: 17 лет 3 месяцa
|
|
ждали:) Программируем для PSP: Часть II. Тотальный контроль В прошлом туториале мы разобрались с "хелловорлдом", теперь пришло время к следующей, не менее важной вещи: вводе информации. Умея выводить что-то на экран и узнавать, что нажал пользователь, уже можно сделать полезную программу. Фактически, после этого урока уже можно будет начинать что-то свое, однако я бы посоветовал дождаться, хотя бы, спрайтов. Создадим проект по шаблону, описанному в первой части. Найдем в фаиле функцию main() -- основную функцию программы, а в ней главный цикл ( while(1) { ... } ). Кстати, насчет while(1): в программировании для psp не считается дурным тоном делать бесконечные циклы внутри программы, т.к. выход все равно осуществляется по кнопке HOME, и только так. Сделаем стандартный цикл обработки сообщений: получение и переваривание. Первое, что нужно сделать -- определить переменную, в которой будет хранится состояние клавиатуры: SceCtrlData pad; // переменная, где хранится информация о состоянии кнопок (нажаты/не нажаты). Структура SceCtrlData хранит в себе TimeStamp - количество фреймов, похоже, от запуска программы (надо уточнить!), Buttons -- битовую маску состояния кнопок (учитываются кнопки Select, Start, крестик, треугольник, квадрат, шифты, стрелки, состояние Hold и Home. Все остальное учитывается только в Kernel Mode, за подробностями смотрите фаил devkitPSPpspsdkincludepspctrl.h) и координаты стика Lx и Ly. Поскольку она определена только в pspctrl.h, придется добавить в начало фаила #include Итак, стираем все внутренности while'ла, и пишем sceCtrlReadBufferPositive(&pad, 1); // читаем содержимое буфера э-э клавиатуры Эта функция заполняет структуру pad текущими значениями состояния кнопок и стика. Кстати, чтобы получить координаты стика удавалось, надо перед while'ом впихнуть 2 строки: sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); // настраиваем на прием информации о положении стика Иначе джойстик так и застынет на положении (128:128) (это -- середина, сами координаты меняются от 0 до 255). Итак, мы считали информацию, теперь нужно ее вывести. Вот что получилось у меня: 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); // выводим координаты стика Как видите, я учитываю только состояние кнопок с картинками (ну, треугольника, круга, квадрата и крестика), дописать поддержку остальных легко, за константами обращайтесь к devkitPSPpspsdkincludepspctrl.h. Код в цикле будет выводить нечто такое: TimeStamp 68832112 | Pressed NONE (0) | Stick: 126:150 TimeStamp 72317982 | Pressed TRIANGLE CIRCLE (12288) | Stick: 119:167 Итак, компилируйте весь полученный код:
#include
#include
#include
PSP_MODULE_INFO("Hello World", 0, 1, 1);
int ExitCallback(int Arg1, int Arg2, void *Common) { sceKernelExitGame(); return 0; }
int CallbackThread(SceSize Args, void *Argp) { int CallbackId;
CallbackId = sceKernelCreateCallback("Exit Callback", ExitCallback, NULL); sceKernelRegisterExitCallback(CallbackId);
sceKernelSleepThreadCB();
return 0; }
int SetupCallbacks(void) { int ThreadId = 0;
ThreadId = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0); if (ThreadId >= 0) { sceKernelStartThread(ThreadId, 0, 0); }
return ThreadId; }
SceCtrlData pad; // переменная, где хранится информация о состоянии кнопок (нажаты/не нажаты).
int main(int argc, char ** argv) { pspDebugScreenInit(); SetupCallbacks();
sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); // настраиваем на прием информации о положении стика
while(1) // главный цикл программы { 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; }
Теперь преобразовывайте в EBOOT, закидывайте на приставку и наслаждайтесь. Как домашнее задание можно попробовать сделать бродилку, или еще какую-нибудь невероятно полезную штуку; я думаю, что посвящу третюю часть всяким прочим фичам text mode, а потом перейду к графике. Удачи!
|
|
|
|
|
#8 Добавлено: 11 мая 2008 00:10 |
|
|
|
|
Посетители
MIK1993
--
Возраст: 31 |  |
Сообщений: 211
Благодарности: 7 / 88
Репутация: 0
Предупреждений: 0
Друзья
Тут: 17 лет 6 месяцев
|
|
|
|
|
|
|
#9 Добавлено: 11 мая 2008 00:19 |
|
|
|
|
Забанен
LIon__
--
Возраст: 32 |  |
Сообщений: 377
Благодарности: 22 / 55
Репутация: 9
Предупреждений: 1
Друзья
Тут: 17 лет 3 месяцa
|
|
MIK1993, ето тем хто программы пишет на зызку, уроки:) Весь код, написанный ранее, но с подробными комментариями. // каллбеки и прочие необходимые для работы программы вещи // нечто вроде windows.h ;-) #include
// как ни странно, почти все функции для работы в текстовом режиме находятся именно там #include
// получение информации о состоянии кнопок и положении джойстика #include
// некий код на ассемблере, необходимый для индентификации программы или модуля системой PSP_MODULE_INFO("Hello World", 0, 1, 1);
// будет вызываться при закрытии программы, смотри функцию CallbackThread int ExitCallback(int Arg1, int Arg2, void *Common) { // "уходя - уходи" // ну, то есть закрывает программу // если не вставить эту строку, то при попытке закрыть игру через кнопку HOME // система зависнет на надписи "Пожалуйста, подождите..." // если решили попробовать ее не вставить, резет девайса произоводится // путем перевода штуки справа в положение "Power" на несколько (около 7) секунд // (пока лампочка не перестанет гореть). потом можно включать sceKernelExitGame(); return 0; }
// специальный поток int CallbackThread(SceSize Args, void *Argp) { // тут будет храниться ID нашего каллбэка // доступ к ним, значить, не по указателям всяким, а по номерам int CallbackId;
// создаем некий каллбэк // система еще не знает, что он для закрытия, название (первый аргумент) нужно, // похоже, для статистики :)
CallbackId = sceKernelCreateCallback("Exit Callback", ExitCallback, NULL);
// регистрируем наш каллбэк как каллбэк для закрытия sceKernelRegisterExitCallback(CallbackId);
// поток больше не нужем, ложимся спать sceKernelSleepThreadCB();
return 0; }
// вопреки названию, в этой функции не создаются каллбэки, а создается поток, // выполняющий эту черную работу int SetupCallbacks(void) { // опять же, доступ к потокам осуществляется по ID int ThreadId = 0;
// Создаем поток. На имя всем наплевать, второй аргумент это функция // выполняемая потоком, третий - приоритет (меньше - приоритетнее), // четвертый - изначальный размер стека, потом идут аттрибуты и опции // на них нам плевать пока что, это вообще для отдельного туториала тема :) ThreadId = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0); if (ThreadId >= 0) // если создался, то запускаем { sceKernelStartThread(ThreadId, 0, 0); // первый параметр - ID потока, второй - размер передаваемых функции аргументов, // указатель на которые содержится в третьем аргументе }
return ThreadId; }
SceCtrlData pad; // переменная, где хранится информация о состоянии кнопок (нажаты/не нажаты).
int main(int argc, char ** argv) { // текстовый режим 34*68 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; }
Добавлено спустя 3 минуты 46 секунд:НЕ могу написать нормально!! Powered by TWSF 1.6 Воспринимает как скрипт!!!!!!!!/* */ Сообщение отредактировано 11 мая 2008 00:17. Редактировалось 1 раз(а)
|
|
|
|
|
#10 Добавлено: 18 мая 2008 13:58 |
|
|
|
|
Посетители
pspalexx
--
Возраст: 36 |  |
Сообщений: 57
Благодарности: 0 / 1
Репутация: 0
Предупреждений: 0
Друзья
Тут: 17 лет 2 месяцa
|
|
|
|
|
|
|
#11 Добавлено: 19 мая 2008 14:34 |
|
|
|
|
Посетители
MIK1993
--
Возраст: 31 |  |
Сообщений: 211
Благодарности: 7 / 88
Репутация: 0
Предупреждений: 0
Друзья
Тут: 17 лет 6 месяцев
|
|
LIon__, хоть я ниче не понимаю, но молодца
|
|
|
|
|
#12 Добавлено: 29 мая 2008 19:18 |
|
|
|
|
Забанен
LIon__
--
Возраст: 32 |  |
Сообщений: 377
Благодарности: 22 / 55
Репутация: 9
Предупреждений: 1
Друзья
Тут: 17 лет 3 месяцa
|
|
|
|
|
|
|
#13 Добавлено: 17 сентября 2008 16:20 |
|
|
|
|
Посетители
3bl3gamer
--
Возраст: 31 |  |
Сообщений: 21
Благодарности: 0 / 0
Репутация: 2
Предупреждений: 0
Друзья
Тут: 17 лет 3 месяцa
|
|
а естьь разница между if (pad.Buttons == 0) и if (pad.Buttons = 0)
|
|
|
|
|
#14 Добавлено: 17 сентября 2008 16:55 |
|
|
|
|
Посетители
.:Witcher:.
--
Возраст: 32 |  |
Сообщений: 101
Благодарности: 0 / 56
Репутация: 15
Предупреждений: 0
Друзья
Тут: 16 лет 7 месяцев
|
|
3bl3gamer, да!! == это знак равенства, можно сказать что если перевести человечески языком то if (pad.Buttons == 0) переводится как: если pad.Buttons ровняется нулю, то....
|
|
|
|
|
#15 Добавлено: 17 сентября 2008 22:35 |
|
|
|
|
Посетители
DarkMedveD
--
Возраст: 31 |  |
Сообщений: 64
Благодарности: 5 / 2
Репутация: 2
Предупреждений: 0
Друзья
Тут: 16 лет 7 месяцев
|
|
Послушай,а какие языки кроме С ещё привлечь можно,просто я Blitz знаю в совершенстве...
|
|
|
|
Добавить эту тему в  |
|
|