PSPx форум

PSPx форум (https://www.pspx.ru/forum/index.php)
-   Программирование для PSP (https://www.pspx.ru/forum/forumdisplay.php?f=101)
-   -   GU на PSP (https://www.pspx.ru/forum/showthread.php?t=24500)

T.I.P. 23.06.2008 20:47

Цитата:

А как это тут её умудрились разбить на две?
ХЗ

P.S. Раздел начал активно двигаЦЦо!

l3VGV 23.06.2008 21:21

с огл щас тока разбираюсь. но по идее сони от него не могло уйти далеко... может модель это матрица типа установки вида проектирования в огл?

Ilsor 23.06.2008 21:24

И ещё вопрос тогда. Вот простейшее GU-приложение:

Код:

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <stdlib.h>

#include <pspgu.h>
#include <pspgum.h>
#include <math.h>

#ifndef bool
#define bool char
#define true 1
#define false 0
#endif

PSP_MODULE_INFO("SIMPLY GU MODE",0,1,1);

PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);

static unsigned int __attribute__((aligned(16))) list[262144];

bool done=false;

int exit_callback(int arg1,int arg2,void *common)
{
 done=true;
 return(0);
}
int CallbackThread(SceSize args, void *argp)
{
 int cbid;
 cbid=sceKernelCreateCallback("Exit Callback",exit_callback,NULL);
 sceKernelRegisterExitCallback(cbid);
 sceKernelSleepThreadCB();
 return(0);
}
int SetupCallbacks(void)
{
 int thid = 0;
 thid=sceKernelCreateThread("update_thread",CallbackThread,0x11,0xFA0,0,0);
 if(thid>=0) sceKernelStartThread(thid, 0, 0);
 return(thid);
}

//начинаем программу
int main(void)
{
 SceCtrlData pad;
 pspDebugScreenInit();
 SetupCallbacks();
 sceCtrlSetSamplingCycle(0);
 sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);

 sceKernelDcacheWritebackAll();
 //---------------------------------------------
 //по сути - это немного модифицированный OpenGL
 //---------------------------------------------

 //инициализируем графику GU
 sceGuInit();
 //запускаем на выполнение новый контекст дисплея - он должен выполниться сразу, т.к. GU_DIRECT
 sceGuStart(GU_DIRECT,list);
 //устанавливаем параметры буфера рисования- формат пикселя, указатель на область видеопамяти, длину строки (выровненную, а не физическую)
 sceGuDrawBuffer(GU_PSM_8888,(void*)0,512);
 //устанавливаем параметры буфера экрана - размер экрана, указатель на видеопамять, длину строки
 sceGuDispBuffer(480,272,(void*)0x88000,512);
 //устанавливаем параметры буфера глубины- указатель на начало буфера глубины в видеопамяти и длину строки
 sceGuDepthBuffer((void*)0x110000,512);
 //устанавливаем смещение экрана в общем пространстве 4096x4096 (в PSP такой размер виртуального экрана, судя по всему)
 sceGuOffset(2048-(480/2),2048-(272/2));//ставим по центру
 //настраиваем видовой порт - порт просмотра- координаты центра и размеры сторон
 sceGuViewport(2048,2048,480,272);
 //устанавливаем диапазон значений для буфера глубины - передняя и задняя плоскости отсечения (буфер инвертирован и значения от 0 до 65535 !)
 sceGuDepthRange(65535,0);
 //включаем обрезание области показа по размерам видового порта
 sceGuScissor(0,0,480,272);
 sceGuEnable(GU_SCISSOR_TEST);
 //настроим матрицу проецирования
 sceGumMatrixMode(GU_PROJECTION);
 sceGumLoadIdentity();
 sceGumPerspective(90.0f,16.0/9.0f,0.1f,100.0f);
 //включим тест глубины
 sceGuDepthFunc(GU_GEQUAL);
 sceGuEnable(GU_DEPTH_TEST);
 //включим режим гладкой интерполяции цвета граней
 sceGuShadeModel(GU_SMOOTH);
 //включим режим отсечения граней, повёрнутых обратной стороной к наблюдателю
 sceGuFrontFace(GU_CW);
 sceGuDisable(GU_CULL_FACE);
 //очистим экран и буфер глубины
 sceGuClearColor(0x00000000);
 sceGuClearDepth(0);
 sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);
 //инициализируем матрицы
 sceGumMatrixMode(GU_VIEW);
 sceGumLoadIdentity();
 sceGumMatrixMode(GU_MODEL);
 sceGumLoadIdentity();
 //теперь можно рисовать
 ScePspFVector3 ScePspFVector3_Working;
 ScePspFVector3_Working.x=0;
 ScePspFVector3_Working.y=0;
 ScePspFVector3_Working.z=-10;
 sceGumTranslate(&ScePspFVector3_Working);
 //выбираем цвет
 sceGuColor(0xffffffff);
 //распределяем память в текущем дисплейном списке
 //как только список выполнится, память освободится
 //нельзя создавать массив вершин в обычной памяти, только в памяти списка или как глобальный массив!
 //Иначе ничего изображено не будет.
 float __attribute__((aligned(16))) *vertex=(float*)sceGuGetMemory(9*sizeof(float));
 //треугольник задан в пространстве
 vertex[0]=5;//x
 vertex[1]=0;//y
 vertex[2]=0;//z

 vertex[3]=0;//x
 vertex[4]=0;//y
 vertex[5]=0;//z

 vertex[6]=0;//x
 vertex[7]=5;//y
 vertex[8]=0;//z
 //рисуем
 sceGumDrawArray(GU_TRIANGLES,GU_VERTEX_32BITF|GU_TRANSFORM_3D,3,0,vertex);
 //а вот так вот можно рисовать с координатами уже спроецированными на плоскость экрана
 //выбираем цвет
 sceGuColor(0xff00ffff);
 vertex[0]=0;//x
 vertex[1]=0;//y
 vertex[2]=0;//z

 vertex[3]=160;//x
 vertex[4]=0;//y
 vertex[5]=0;//z

 vertex[6]=0;//x
 vertex[7]=120;//y
 vertex[8]=0;//z
 //рисуем
 sceGumDrawArray(GU_TRIANGLES,GU_VERTEX_32BITF|GU_TRANSFORM_2D,3,0,vertex);
 //и выводим изображение
 sceGuFinish();
 //ждём, пока дисплейный список (у нас - контекст дисплея) не выполнится
 sceGuSync(0,GU_SYNC_DONE);
 //включаем дисплей
 sceGuDisplay(GU_TRUE);
 //делаем видимым буфер, в котором мы рисовали
 sceGuSwapBuffers();
 //ждём нажатия любой клавиши
 while(!done)
 {
  sceCtrlReadBufferPositive(&pad, 1);
  if (pad.Buttons!=0) break;
 }
 sceGuTerm();
 sceKernelExitGame();
 return(0);
}

Вопросы такие:

1) Как я понял, работает GU всегда на основе дисплейных списков (как в OpenGL). И для списка нужно явно указывать доступный объём памяти да ещё и с выравниванием по параграфу. Почему-то все задают размер 262144 - это почему так? И вообще, сколько на борту видеопамяти?
2) Почему буфер глубины 16-ти битный? Точность же пострадает...
3) Какой смысл в виртуальном экране 4096x4096, если отображать можно 480x272 максимум и при этом переключать страницы sceGuSwapBuffers(). Зачем же тогда такой экран? Хм... Какой в нём смысл? Единственно, реализовывать полноэкранное сглаживание можно используя полный 4096x4096, но примимо ли это на PSP?
4) Нулевой байт цвета - это альфа-канал?
5) Почему примитивы можно создавать либо глобально в программе, либо распределяя память дисплейного списка командой float __attribute__((aligned(16))) *vertex=(float*)sceGuGetMemory(9*sizeof(float)), но нельзя выделить память типа float vertex[9]. У меня последний вариант не работает никак.
6) Зачем придумано обрезание порта просмотра командами
sceGuScissor(0,0,480,272);
sceGuEnable(GU_SCISSOR_TEST);
7) Для чего нужна команда sceGuDisplay(GU_TRUE); Не понимаю логики. Зачем включать то, что уже включено? Хм...

Вот такие вот пироги... я хорошо знаком с OpenGL, но вот GU меня местами удивляет неимоверно. :)

Ilsor 23.06.2008 21:27

Вложений: 1
Цитата:

с огл щас тока разбираюсь. но по идее сони от него не могло уйти далеко... может модель это матрица типа установки вида проектирования в огл?
Нет, для проецирования есть специальная матрица. Я могу вам показать мою старую (года 4 ей уже) реализацию софтверного OpenGL (точнее, части - тестуры я так и не сделал - пропал интерес). Не для PSP. Там конвейер матриц можно посмотреть.

l3VGV 23.06.2008 22:03

Ээээ. мастер ты это. мыж тут нубы :)а ты к нам будто мы соневские доки читали и знаем...
видеопамяти на борту 2 метра афайк.

Ilsor 24.06.2008 12:27

Жалко... придётся выяснять опытным путём... Увы, в русском сегменте инета никакой вразумительной информации я не нашёл. А с английским у меня некоторые трудности - я немецкий учил, а английский исключительно "опытным путём". :) Ну ничего, эксперименты покажут, что вся эта тарабарщина из себя представляет. :)

добавлено через 4 часа 17 минут
1) Однако, оказывается, что альфа-канал в цвете идёт первым, а вот дальше идут уже b g и r.
2) Инициализацию локальных и глобальных массивов вершин примитивов можно делать только до sceGuInit. После sceGuInit инициализацию можно делать только через выделенный дисплею блок памяти, через sceGuGetMemory.
3) Чтобы каждую точку примитива раскрасить в свой цвет или чтобы назначить ей точку текстуры,нормали и т.д. нужно объединять флаги команды sceGumDrawArray, например, sceGumDrawArray(GU_TRIANGLES,GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D,3,0, sVertex);

Ну а с остальным пока экспериментирую...

Ilsor 24.06.2008 19:03

Вложений: 1
Вот что ещё выяснил:
1) При задании текстур данные идут как RGBA (т.е. порядок не такой, как при задании цвета! в sceGuColor)
2) Если синхронизацию по sceDisplayWaitVblankStart() ставить после sceGuSwapBuffers(), то вверху экрана будет полоса, где вывод производиться не будет - отстаём от развёртки? :)
3) Ширина и высота текстуры должны быть степенью 2 и ширина должна быть выровнена по параграфу (16 байт).

Вот код моей библиотеки для работы со спрайтами с использованием GU:

Код:

#ifndef CSPRITE_H_INCLUDED
#define CSPRITE_H_INCLUDED

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <psprtc.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <pspgu.h>
#include <pspgum.h>

#ifndef bool
#define bool char
#define true 1
#define false 0
#endif

//спрайт
struct SGuSprite
{
 int Width;//ширина
 int Height;//высота
 int WidthImage;//ширина картинки
 int HeightImage;//высота картинки
 unsigned char *Data;//указатель на данные спрайта
};

//загрузить спрайт
bool GuSprite_LoadSprite(char *FileName,struct SGuSprite *sGuSprite,unsigned char alpha);
//отобразить спрайт
void GuSprite_PutSprite(int x,int y,struct SGuSprite *sGuSprite);
//удалить спрайт
void GuSprite_DeleteSprite(struct SGuSprite *sGuSprite);
//выставить спрайту для цвета (r,g,b) значение alpha
void GuSprite_ReplaceAlpha(unsigned char alpha,unsigned char r,unsigned char g,unsigned char b,struct SGuSprite *sGuSprite);
#endif // CSPRITE_H_INCLUDED

//-------------------------------------------------------------------------


#include "gusprite.h"


struct SGuVertex
{
 float U;
 float V;
 unsigned int Color;
 float X;
 float Y;
 float Z;
};

//заголовок TGA-файла
#pragma pack(1)
struct TGAHEADER
{
 char identsize;//размер поля ID заголовка (0)
 char colorMapType;//если ли палитра:0-нет,1-есть
 char imageType;//тип картинки:0-нет,1-индексные цвета,2-RGB,3-оттенки серого, (3-й бит - RLE-кодирование)
 unsigned short        colorMapStart;//начало карты цветов
 unsigned short        colorMapLength;//количество цветов в карте
 unsigned char        colorMapBits;//размерность палитры
 unsigned short        xstart;//начальные координаты изображения
 unsigned short        ystart;
 unsigned short        width;//размер изображения по X
 unsigned short        height;//размер изображения по Y
 char bits;//количесто бит на пиксель (8,16,24,32)
 char de******or;//дескриптор изрображения
};
#pragma pack(8)

//загрузить спрайт (формат - TGA)
bool GuSprite_LoadSprite(char *FileName,struct SGuSprite *sGuSprite,unsigned char alpha)
{
 //задаём размеры по-умолчанию
 sGuSprite->Data=NULL;
 sGuSprite->Width=0;
 sGuSprite->Height=0;
 //пробуем считать изображение
 struct TGAHEADER tgaHeader;
 SceUID SceUID_File;
 SceUID_File=sceIoOpen(FileName,PSP_O_RDONLY,0777);//открываем файл
 if (SceUID_File<0) return(false);//ошибка
 //читаем заголовок
 if (sceIoRead(SceUID_File,&tgaHeader,sizeof(struct TGAHEADER))<sizeof(struct TGAHEADER))//ошибка - мало данных
 {
  sceIoClose(SceUID_File);
  return(false);
 }
 //проверяем на возможность чтения
 if (tgaHeader.imageType&8)
 {
  sceIoClose(SceUID_File);
  return(false);//RLE не поддерживаем
 }
 if ((tgaHeader.imageType&7)==0 || (tgaHeader.imageType&7)==3)
 {
  sceIoClose(SceUID_File);
  return(false);//градации серого и отсутствие изображения не поддерживаем
 }
 //задаём параметры изображения
 sGuSprite->Width=tgaHeader.width;
 sGuSprite->Height=tgaHeader.height;
 //определяем размер изображения, являющегося степенью двойки с широной, кратной 4-м байтам
 sGuSprite->WidthImage=1;
 sGuSprite->HeightImage=1;
 while(sGuSprite->WidthImage<sGuSprite->Width || sGuSprite->WidthImage%4!=0) sGuSprite->WidthImage*=2;
 while(sGuSprite->HeightImage<sGuSprite->Height) sGuSprite->HeightImage*=2;
 //выделяем память для изображения
 int image_length=tgaHeader.width*tgaHeader.height*tgaHeader.bits/8;
 unsigned char *i_buffer=(unsigned char*)malloc(image_length);
 //считываем изображение
 sceIoLseek(SceUID_File,sizeof(struct TGAHEADER)+tgaHeader.colorMapStart+tgaHeader.colorMapLength*tgaHeader.colorMapBits/8,SEEK_SET);
 if(sceIoRead(SceUID_File,i_buffer,image_length)<image_length)
 {
  sceIoClose(SceUID_File);
  free(i_buffer);
  return(false);
 }
 //а теперь анализируем формат
 if (tgaHeader.bits==24)//BGR - модицифируем для четвёрок байт
 {
  sceIoClose(SceUID_File);
  unsigned char *out_image=(unsigned char*)malloc(sGuSprite->WidthImage*sGuSprite->HeightImage*4);
  int y,x;
  if (tgaHeader.de******or==32)//прямой формат
  {
  unsigned char *oi_ptr=out_image;
  unsigned char *i_ptr=i_buffer;
  for(y=0;y<tgaHeader.height;y++,i_ptr+=tgaHeader.width*3,oi_ptr+=sGuSprite->WidthImage*4)
  {
    unsigned char *i_ptrc=i_ptr;
    unsigned char *oi_ptrc=oi_ptr;
    for(x=0;x<tgaHeader.width;x++)
    {
    unsigned char b=*(i_ptrc);i_ptrc++;
    unsigned char g=*(i_ptrc);i_ptrc++;
    unsigned char r=*(i_ptrc);i_ptrc++;
    unsigned char a=alpha;
    *oi_ptrc=r;oi_ptrc++;
    *oi_ptrc=g;oi_ptrc++;
    *oi_ptrc=b;oi_ptrc++;
    *oi_ptrc=a;oi_ptrc++;
    }
  }
  }
  if (tgaHeader.de******or==8)//обратный формат
  {
  unsigned char *oi_ptr=out_image;
  unsigned char *i_ptr=i_buffer+tgaHeader.width*tgaHeader.height*3-1;
  for(y=tgaHeader.height-1;y>=0;y--,i_ptr-=tgaHeader.width*3,oi_ptr+=sGuSprite->WidthImage*4)
  {
    unsigned char *i_ptrc=i_ptr;
    unsigned char *oi_ptrc=oi_ptr;
    for(x=0;x<tgaHeader.width;x++)
    {
    unsigned char b=*(i_ptrc);i_ptrc++;
    unsigned char g=*(i_ptrc);i_ptrc++;
    unsigned char r=*(i_ptrc);i_ptrc++;
    unsigned char a=alpha;
    *oi_ptrc=r;oi_ptrc++;
    *oi_ptrc=g;oi_ptrc++;
    *oi_ptrc=b;oi_ptrc++;
    *oi_ptrc=a;oi_ptrc++;
    }
  }
  }
  free(i_buffer);
  sGuSprite->Data=out_image;
  return(true);
 }
 if (tgaHeader.colorMapType==1 && tgaHeader.colorMapBits/8==3)//есть палитра по 24 бита
 {
  sceIoLseek(SceUID_File,tgaHeader.colorMapStart+sizeof(struct TGAHEADER),SEEK_SET);
  //читаем палитру
  unsigned char *color_map=(unsigned char*)malloc(tgaHeader.colorMapLength*3);
  if (sceIoRead(SceUID_File,color_map,tgaHeader.colorMapLength*3)<tgaHeader.colorMapLength*3)
  {
  sceIoClose(SceUID_File);
  free(color_map);
  free(i_buffer);
  return(false);
  }
  //нам потребуется изменить формат
  unsigned char *out_image=(unsigned char*)malloc(sGuSprite->WidthImage*sGuSprite->HeightImage*4);
  int y,x;
  if (tgaHeader.de******or==32)//прямой формат
  {
  unsigned char *oi_ptr=out_image;
  unsigned char *i_ptr=i_buffer;
  for(y=0;y<tgaHeader.height;y++,i_ptr+=tgaHeader.width,oi_ptr+=sGuSprite->WidthImage*4)
  {
    unsigned char *i_ptrc=i_ptr;
    unsigned char *oi_ptrc=oi_ptr;
    for(x=0;x<tgaHeader.width;x++,i_ptrc++)
    {
    int index=(*i_ptrc)*3;
    unsigned char b=color_map[index];
    unsigned char g=color_map[index+1];
    unsigned char r=color_map[index+2];
    unsigned char a=alpha;
    *oi_ptrc=r;oi_ptrc++;
    *oi_ptrc=g;oi_ptrc++;
    *oi_ptrc=b;oi_ptrc++;
    *oi_ptrc=a;oi_ptrc++;
    }
  }
  }
  if (tgaHeader.de******or==8)//формат перевёрнутый
  {
  unsigned char *oi_ptr=out_image;
  unsigned char *i_ptr=i_buffer+tgaHeader.width*(tgaHeader.height-1);
  for(y=tgaHeader.height-1;y>=0;y--,i_ptr-=tgaHeader.width,oi_ptr+=sGuSprite->WidthImage*4)
  {
    unsigned char *i_ptrc=i_ptr;
    unsigned char *oi_ptrc=oi_ptr;
    for(x=0;x<tgaHeader.width;x++,i_ptrc++)
    {
    int index=(*i_ptrc)*3;
    unsigned char b=color_map[index];
    unsigned char g=color_map[index+1];
    unsigned char r=color_map[index+2];
    unsigned char a=alpha;
    *oi_ptrc=r;oi_ptrc++;
    *oi_ptrc=g;oi_ptrc++;
    *oi_ptrc=b;oi_ptrc++;
    *oi_ptrc=a;oi_ptrc++;
    }
  }
  }
  free(i_buffer);
  free(color_map);
  sGuSprite->Data=out_image;
  sceIoClose(SceUID_File);
  return(true);
 }
 //иные режимы не поддерживаем
 sceIoClose(SceUID_File);
 free(i_buffer);
 return(false);
}
//отобразить спрайт
void GuSprite_PutSprite(int x,int y,struct SGuSprite *sGuSprite)
{
 if (sGuSprite->Data==NULL || sGuSprite->Width==0 || sGuSprite->Height==0) return;//спрайт отсутствует
 sceGuTexMode(GU_PSM_8888,0,0,0);
 sceGuTexImage(0,sGuSprite->WidthImage,sGuSprite->HeightImage,sGuSprite->WidthImage,sGuSprite->Data);
 sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA);
 sceGuTexFilter(GU_NEAREST,GU_NEAREST);
 sceGuTexWrap(GU_CLAMP,GU_CLAMP);
 sceGuTexScale(1,1);
 sceGuTexOffset(0,0);
 struct SGuVertex *sGuVertex;
 sGuVertex=sceGuGetMemory(2*sizeof(struct SGuVertex));
 sGuVertex[0].X=x;
 sGuVertex[0].Y=y;
 sGuVertex[0].Z=0;
 sGuVertex[0].Color=0xffffffff;
 sGuVertex[0].U=0;
 sGuVertex[0].V=0;

 sGuVertex[1].X=x+sGuSprite->Width;
 sGuVertex[1].Y=y+sGuSprite->Height;
 sGuVertex[1].Z=0;
 sGuVertex[1].Color=0xffffffff;
 sGuVertex[1].U=sGuSprite->Width;
 sGuVertex[1].V=sGuSprite->Height;
sceGumDrawArray(GU_SPRITES,GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D,2,0,sGuVertex);
}
//удалить спрайт
void GuSprite_DeleteSprite(struct SGuSprite *sGuSprite)
{
 if (sGuSprite->Data==NULL || sGuSprite->Width==0 || sGuSprite->Height==0) return;//спрайт отсутствует
 free(sGuSprite->Data);
 sGuSprite->Data=NULL;
 sGuSprite->Width=0;
 sGuSprite->Height=0;
}
//выставить спрайту для цвета (r,g,b) значение alpha
void GuSprite_ReplaceAlpha(unsigned char alpha,unsigned char r,unsigned char g,unsigned char b,struct SGuSprite *sGuSprite)
{
 if (sGuSprite->Data==NULL || sGuSprite->Width==0 || sGuSprite->Height==0) return;//спрайт отсутствует
 unsigned char *ptr=sGuSprite->Data;
 int n;
 int length=sGuSprite->WidthImage*sGuSprite->HeightImage;
 for(n=0;n<length;n++)
 {
  unsigned char ri=*ptr;ptr++;
  unsigned char gi=*ptr;ptr++;
  unsigned char bi=*ptr;ptr++;
  if (ri==r && gi==g && bi==b) *ptr=alpha;
  ptr++;
 }
}

А вот пример приложения-заготовки для пасьянса с двумя спрайтами, причём, второй спрайт (указатель) имеет область прозрачности.

l3VGV 24.06.2008 21:58

А какой смысл в пикселе интресно порядок менять?

Ilsor 24.06.2008 22:09

Хороший вопрос... Наверное, из целей совместимости с OpenGL. А вообще, картинки всякие (TGA и BMP и другие) тоже порядок цветов меняют. Я уже и не помню, зачем им это надо было... Но вообще, это не очень удобно лично мне. :)

добавлено через 1 минуту
Ах да, я сказал несколько неоднозначно:
"Однако, оказывается, что альфа-канал в цвете идёт первым, а вот дальше идут уже b g и r. "

Т.е. раскладка битовая такая: abgr.

А для текстуры или спрайта раскладка: rgba

l3VGV 24.06.2008 22:35

может во время какихто прередач(внутре конвеера или из памяти в гу...) удобно чтобы байты задом наперёд шли...хых. мистика :)
однако ценное наблюдение. спасибо.

Ilsor 25.06.2008 06:15

Да нет, вроде конвейеру-то как раз всё равно... Может, там для прямого вывода загруженных картинок сделано? То есть, читаем, скажем, bmp и тут же выводим простым копированием в видеопамять. Хотя вряд ли. Надо поискать смысл инверсии порядка цветов.

Ilsor 29.06.2008 12:23

Отправил GU текстурку 480x272 по-моему, а по его представлениям 512x512. Ну что можно сказать... либо я что-то сделал не так, либо он с такими размерами не работает. Экран мерцает, по нему идут полосы, хотя на заднем фоне текстуру видно. Увеличивал размер памяти дисплейного списка - не помогло. А с маленькими 64x64 без проблем всё идёт. Наверное, 512 для него слишком жирно...

Ilsor 29.06.2008 13:57

Вложений: 1
А вот GU-приложение "пасьянс косынка". Пока - прототип. То есть, играть можно (аналоговый джойстик и кнопка "крестик"). Это на нём текстуру зелёного сукна вместо 480x272 мне пришлось заменить маленький кусочек. :)

Ilsor 05.07.2008 17:28

Занятно. Попытался вывести несколько раз относительно крупный спрайт (256x64). Опять глюки. Экран мерцает, картинка разваливается. Причём, один спрайт выводится. Два - уже нет. Такое впечатление, что Gu массив данных спрайта зачем-то перекидывает в память списка и заданных 256 кБ не хватает. Но если выделить в 10 раз больше, тоже работать не начинает. Если выводить один спрайт в одном дисплейном списке, а второй во втором, то тоже ничего не выходит, либо я чего-то не так делаю.
Вот сейчас сделал спрайты 128x64 и выделил под список 512 кБ. Пока работает. Интересно, если я ещё спрайтов добавлю, оно продолжит работать... хм..

Ilsor 07.07.2008 20:45

А всё-таки непонятно, как же выглядит адресное пространство PSP. Я попытался снять скриншот в моём пасьянсе копированием области, заданной GU как видеобуфер (т.е. начинающейся с 0 (!) - обычно-то для графических приложений не для GU задавался адрес 64 мБ)
Код:

<...>
static unsigned int staticOffset=0;

static unsigned int getMemorySize(unsigned int width,unsigned int height,unsigned int psm)
{
 switch (psm)
 {
  case GU_PSM_T4: return((width*height)>>1);
  case GU_PSM_T8: return(width*height);
  case GU_PSM_5650:
  case GU_PSM_5551:
  case GU_PSM_4444:
  case GU_PSM_T16: return(2*width*height);
  case GU_PSM_8888:
  case GU_PSM_T32: return(4*width*height);
  default: return(0);
 }
}

void* getStaticVramBuffer(unsigned int width,unsigned int height,unsigned int psm)
{
 unsigned int memSize=getMemorySize(width,height,psm);
 void* result=(void*)staticOffset;
 staticOffset+=memSize;
 return(result);
}

void* getStaticVramTexture(unsigned int width,unsigned int height,unsigned int psm)
{
 void* result=getStaticVramBuffer(width,height,psm);
 return((void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr())));
}
<...>


 void* fbp0=getStaticVramBuffer(512,272,GU_PSM_8888);
 void* fbp1=getStaticVramBuffer(512,272,GU_PSM_8888);
 void* zbp=getStaticVramBuffer(512,272,GU_PSM_4444);

 //инициализируем графику GU
 sceGuInit();
 //запускаем на выполнение новый контекст дисплея - он должен выполниться сразу, т.к. GU_DIRECT
 sceGuStart(GU_DIRECT,list);
 //устанавливаем параметры буфера рисования- формат пикселя, указатель на область видеопамяти, длину строки (выровненную, а не физическую)
 sceGuDrawBuffer(GU_PSM_8888,fbp0,512);
 //устанавливаем параметры буфера экрана - размер экрана, указатель на видеопамять, длину строки
 sceGuDispBuffer(480,272,fbp1,512);
 //устанавливаем параметры буфера глубины- указатель на начало буфера глубины в видеопамяти и длину строки
 sceGuDepthBuffer(zbp,512);

и ничего не вышло. Точнее, я выделил память через malloc и туда сделал memcpy с адреса fbp0 (и с fbp1 тоже пробовал). Приставка вырубается и перезагружается. Но ведь когда я работал с видео через прямое обращение к видеопамяти, то самое в 64 мБ, то всё работало отлично. Не понимаю я, где же реально расположена видеопамять и как так получается, что я могу указать видеопамять на каких-то адресах, где по какой-то случайности не попадает кусок моей программы? Я пытался GU дать адрес равный 64 мБ - на экране хаос точек. Эх, знать бы архитектуру и принципы управления памятью этого чуда...

l3VGV 07.07.2008 21:26

Даю справку. по адресам:
http://wiki.ps2dev.org/psp:memory_map

Надеюсь это то. на слимке чутка отличается но не критично. чуть пошире куски основной памяти и безкешевой области.

думаю начинать копировать с 0 бесполезно, для неё это ркивой указатель и она сразу его в топку. АФАЙК начинать надо с 64Кб.

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

Ilsor 08.07.2008 06:23

Цитата:

думаю начинать копировать с 0 бесполезно, для неё это ркивой указатель и она сразу его в топку. АФАЙК начинать надо с 64Кб.
Однако, для GU этот указатель вполне рабочий. И Совершенно не понятно, почему он в нуле, а следующий за ним тоже затирает совсем не свободную область памяти.

l3VGV 08.07.2008 09:42

Вопрос без официальных доков имхо не отвечаем :) те как факт мы это знаем. а вот почему? ну хз. так уж сделано.

Ilsor 08.07.2008 10:49

А ещё никто у Sony оригинальный SKD не спиратил? :)

l3VGV 08.07.2008 11:20

Пока нет :( по крайней мере в торентах не ищутся.


Текущее время: 18:38. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2025, vBulletin Solutions, Inc. Перевод: zCarot
PSPx Forum - Сообщество фанатов игровых консолей.