kounch
21/02/2006, 14:17
Hola
mi candidatura al concurso GP2X 2006 consiste en un corrector automático de la salida de TV para los programas que estén corriendo. No se puede hacer público nada del sofware que se ha entregado hasta que ellos lo hagan, pero lo que si puedo hacer es contaros todo lo que he deducido de la investigación para hacerlo. Ahí va:
El tamaño de la salida a pantalla (LCD o TV) está controlado por tres registros de la memoria:
C000 2906 - Escala horizontal de la pantalla
C000 2908 - Escala vertical de la pantalla
C000 290C - Anchura de la pantalla
El area visualizable de la pantalla está controlado por los registros de ventanas RGB:
C000 0x28E2+window*8 Coordenada X1 de la ventana número (window+1)
C000 0x28E4+window*8 Coordenada X2 de la ventana número (window+1)
C000 0x28E6+window*8 Coordenada Y1 de la ventana número (window+1)
C000 0x28E8+window*8 Coordenada Y2 de la ventana número (window+1)
Donde window puede variar de 0 a 3.
Los valores que se deben aplicar a estos registros dependen de que la pantalla esté en LCD, en TV-Out PAL o en TV-Out NTSC. El método para calcularlo es el siguiente:
Comprobamos si el TV-Out está activado, para ello se debe cumplir que el valor de C000 2800 tenga el bit 17 con valor 1.
Miramos el tamaño real de la pantalla. Para ello comprobar el valor del registros C000 2818 (altura real de la pantalla). Si el valor es 239, estamos en LCD. Si el valor es 287, estamos en TV PAL. Si el valor es 231, estamos en TV NTSC.
Tomamos la dimension X de nuestra imagen a representar, y aplicamos este calculo: dimensionX/320*MaxX donde MaxX es 1024 si estamos en LCD o 489 Si estamos en TV. El resultado lo ponemos en C000 2906
Tomamos la dimension Y de nuestra imagen a representar, y aplicamos este calculo: dimensionY/240*MaxY*BitsPP donde BistPP es 1 para 8 bits y 2 para 16 bits de color. MaxY es 320 si estamos en LCD, 274 Si estamos en TV PAL o 331 si estamos en TV NTSC. El resultado lo aplicamos en C000 2908.
Nos aseguramos de que el valor en C000 290C es 320*BitsPP
Finalmente, escalamos las ventanas RGB teniendo en cuenta que sus coordenadas deben tener un ancho maximo de 329 para LCD o de 669 para TV, así como un alto máximo de 239 para LCD, de 279 para TV PAL o de 231 para TV NTSC
Todo esto se traduce, por ejemplo, en cambiar estas dos funciones en la minimal lib:
void gp2x_video_RGB_setscaling(int W, int H)
{
float escalaw,escalah;
int bpp=(gp2x_memregs[0x28DA>>1]>>9)&0x3;
if(gp2x_memregs[0x2800>>1]&0x100) //Vemos si el TV-Out esta activado
{
escalaw=489.0; //Factor de escala RGB Horizontal para TV (comun a PAL y NTSC)
if (gp2x_memregs[0x2818>>1] == 287) //Comprobacion si la altura de la pantalla es para PAL
escalah=274.0; //Factor de escala RGB Vertical para TV PAL
else if (gp2x_memregs[0x2818>>1] == 239) //Comprobacion si la altura de la pantalla es para NTSC
escalah=331.0; //Factor de escala RGB Vertical para TV NTSC
}
else //Suponemos que esta en modo LCD (TV-Out desactivado)
{
escalaw=1024.0; //Escala RGB Horizontal para LCD
escalah=320.0; //Escala RGB Vertical para LCD
}
// scale horizontal
gp2x_memregs[0x2906>>1]=(unsigned short)((float)escalaw *(W/320.0));
// scale vertical
gp2x_memregl[0x2908>>2]=(unsigned long)((float)escalah *bpp *(H/240.0));
}
void gp2x_video_RGB_setwindows(int window0, int window1, int window2, int window3, int x, int y)
{
int window,mode,mode2,x1,y1,x2,y2;
int xmax,ymax;
if(gp2x_memregs[0x2800>>1]&0x100) //Vemos si el TV-Out esta activado
{
xmax=669; //Maximo ancho en modo TV-Out (comun a PAL y NTSC)
if (gp2x_memregs[0x2818>>1] == 287) //Comprobacion si la altura de la pantalla es para PAL
ymax=279; //Maximo alto en modo TV-Out PAL
else if (gp2x_memregs[0x2818>>1] == 239) //Comprobacion si la altura de la pantalla es para NTSC
ymax=231; //Maximo alto en modo TV-Out NTSC
}
else //Suponemos que esta en modo LCD (TV-Out desactivado)
{
xmax=319; //Maximo ancho en modo LCD
ymax=239; //Maximo alto en modo LCD
}
//Escalamos las coordenadas segun las dimensiones de la pantalla
x=(x * xmax) / 319;
y=(y * ymax) / 239;
//enable all RGB windows
gp2x_memregs[0x2880>>1]|=(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2);
for(window=0;window<4;window++) //windows 0..3
{
if(window==0) x1=0, y1=0, x2=x, y2=y, mode=window0;
if(window==1) x1=x, y1=0, x2=xmax, y2=y, mode=window1;
if(window==2) x1=0, y1=y, x2=x, y2=ymax, mode=window2;
if(window==3) x1=x, y1=y, x2=xmax, y2=ymax, mode=window3;
if(mode<0) { gp2x_memregs[0x28da>>1]&=~(1<<(window<<1)); }
else {
mode2=(mode>0x0F?0xF:mode);
//set alpha 0..0xE / colorkey,solid 0xF value
if(window<3)
{
gp2x_memregs[0x28de>>1]&=~(mode2<<(window<<2));
gp2x_memregs[0x28de>>1]|= (mode2<<(window<<2));
}
else
{
gp2x_memregs[0x28e0>>1]&=~(mode2<<((window-3)<<2));
gp2x_memregs[0x28e0>>1]|= (mode2<<((window-3)<<2));
}
//set window as blended (2), transparent/colorkey (1), solid (0)
gp2x_memregs[0x28dc>>1]&=~(3 <<(window<<1));
gp2x_memregs[0x28dc>>1]|= ((mode==0x11 ? 0 : (mode==0x10 ? 1 : 2))<<(window<<1));
//window coordinates
gp2x_memregs[(0x28e2+window*8)>>1]=x1;
gp2x_memregs[(0x28e4+window*8)>>1]=x2;
gp2x_memregs[(0x28e6+window*8)>>1]=y1;
gp2x_memregs[(0x28e8+window*8)>>1]=y2;
//enable window
gp2x_memregs[0x28da>>1]|=(3<<(window<<1));
}
}Simplemente aplicando estos dos cambios he recompilado el GP2XEngine así como el GP2XSpectrum y el Selector, y funcionan perfectamente con la televisión.
Perdón por el rollo, y espero que esto sea útil para todos.
kounch
EDIT: El ejemplo que he puesto es válido para la minimal lib 0.B siempre y cuando no se altere el valor del registro MLC_STL_HW (C000 290C) con funciones propias.
mi candidatura al concurso GP2X 2006 consiste en un corrector automático de la salida de TV para los programas que estén corriendo. No se puede hacer público nada del sofware que se ha entregado hasta que ellos lo hagan, pero lo que si puedo hacer es contaros todo lo que he deducido de la investigación para hacerlo. Ahí va:
El tamaño de la salida a pantalla (LCD o TV) está controlado por tres registros de la memoria:
C000 2906 - Escala horizontal de la pantalla
C000 2908 - Escala vertical de la pantalla
C000 290C - Anchura de la pantalla
El area visualizable de la pantalla está controlado por los registros de ventanas RGB:
C000 0x28E2+window*8 Coordenada X1 de la ventana número (window+1)
C000 0x28E4+window*8 Coordenada X2 de la ventana número (window+1)
C000 0x28E6+window*8 Coordenada Y1 de la ventana número (window+1)
C000 0x28E8+window*8 Coordenada Y2 de la ventana número (window+1)
Donde window puede variar de 0 a 3.
Los valores que se deben aplicar a estos registros dependen de que la pantalla esté en LCD, en TV-Out PAL o en TV-Out NTSC. El método para calcularlo es el siguiente:
Comprobamos si el TV-Out está activado, para ello se debe cumplir que el valor de C000 2800 tenga el bit 17 con valor 1.
Miramos el tamaño real de la pantalla. Para ello comprobar el valor del registros C000 2818 (altura real de la pantalla). Si el valor es 239, estamos en LCD. Si el valor es 287, estamos en TV PAL. Si el valor es 231, estamos en TV NTSC.
Tomamos la dimension X de nuestra imagen a representar, y aplicamos este calculo: dimensionX/320*MaxX donde MaxX es 1024 si estamos en LCD o 489 Si estamos en TV. El resultado lo ponemos en C000 2906
Tomamos la dimension Y de nuestra imagen a representar, y aplicamos este calculo: dimensionY/240*MaxY*BitsPP donde BistPP es 1 para 8 bits y 2 para 16 bits de color. MaxY es 320 si estamos en LCD, 274 Si estamos en TV PAL o 331 si estamos en TV NTSC. El resultado lo aplicamos en C000 2908.
Nos aseguramos de que el valor en C000 290C es 320*BitsPP
Finalmente, escalamos las ventanas RGB teniendo en cuenta que sus coordenadas deben tener un ancho maximo de 329 para LCD o de 669 para TV, así como un alto máximo de 239 para LCD, de 279 para TV PAL o de 231 para TV NTSC
Todo esto se traduce, por ejemplo, en cambiar estas dos funciones en la minimal lib:
void gp2x_video_RGB_setscaling(int W, int H)
{
float escalaw,escalah;
int bpp=(gp2x_memregs[0x28DA>>1]>>9)&0x3;
if(gp2x_memregs[0x2800>>1]&0x100) //Vemos si el TV-Out esta activado
{
escalaw=489.0; //Factor de escala RGB Horizontal para TV (comun a PAL y NTSC)
if (gp2x_memregs[0x2818>>1] == 287) //Comprobacion si la altura de la pantalla es para PAL
escalah=274.0; //Factor de escala RGB Vertical para TV PAL
else if (gp2x_memregs[0x2818>>1] == 239) //Comprobacion si la altura de la pantalla es para NTSC
escalah=331.0; //Factor de escala RGB Vertical para TV NTSC
}
else //Suponemos que esta en modo LCD (TV-Out desactivado)
{
escalaw=1024.0; //Escala RGB Horizontal para LCD
escalah=320.0; //Escala RGB Vertical para LCD
}
// scale horizontal
gp2x_memregs[0x2906>>1]=(unsigned short)((float)escalaw *(W/320.0));
// scale vertical
gp2x_memregl[0x2908>>2]=(unsigned long)((float)escalah *bpp *(H/240.0));
}
void gp2x_video_RGB_setwindows(int window0, int window1, int window2, int window3, int x, int y)
{
int window,mode,mode2,x1,y1,x2,y2;
int xmax,ymax;
if(gp2x_memregs[0x2800>>1]&0x100) //Vemos si el TV-Out esta activado
{
xmax=669; //Maximo ancho en modo TV-Out (comun a PAL y NTSC)
if (gp2x_memregs[0x2818>>1] == 287) //Comprobacion si la altura de la pantalla es para PAL
ymax=279; //Maximo alto en modo TV-Out PAL
else if (gp2x_memregs[0x2818>>1] == 239) //Comprobacion si la altura de la pantalla es para NTSC
ymax=231; //Maximo alto en modo TV-Out NTSC
}
else //Suponemos que esta en modo LCD (TV-Out desactivado)
{
xmax=319; //Maximo ancho en modo LCD
ymax=239; //Maximo alto en modo LCD
}
//Escalamos las coordenadas segun las dimensiones de la pantalla
x=(x * xmax) / 319;
y=(y * ymax) / 239;
//enable all RGB windows
gp2x_memregs[0x2880>>1]|=(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2);
for(window=0;window<4;window++) //windows 0..3
{
if(window==0) x1=0, y1=0, x2=x, y2=y, mode=window0;
if(window==1) x1=x, y1=0, x2=xmax, y2=y, mode=window1;
if(window==2) x1=0, y1=y, x2=x, y2=ymax, mode=window2;
if(window==3) x1=x, y1=y, x2=xmax, y2=ymax, mode=window3;
if(mode<0) { gp2x_memregs[0x28da>>1]&=~(1<<(window<<1)); }
else {
mode2=(mode>0x0F?0xF:mode);
//set alpha 0..0xE / colorkey,solid 0xF value
if(window<3)
{
gp2x_memregs[0x28de>>1]&=~(mode2<<(window<<2));
gp2x_memregs[0x28de>>1]|= (mode2<<(window<<2));
}
else
{
gp2x_memregs[0x28e0>>1]&=~(mode2<<((window-3)<<2));
gp2x_memregs[0x28e0>>1]|= (mode2<<((window-3)<<2));
}
//set window as blended (2), transparent/colorkey (1), solid (0)
gp2x_memregs[0x28dc>>1]&=~(3 <<(window<<1));
gp2x_memregs[0x28dc>>1]|= ((mode==0x11 ? 0 : (mode==0x10 ? 1 : 2))<<(window<<1));
//window coordinates
gp2x_memregs[(0x28e2+window*8)>>1]=x1;
gp2x_memregs[(0x28e4+window*8)>>1]=x2;
gp2x_memregs[(0x28e6+window*8)>>1]=y1;
gp2x_memregs[(0x28e8+window*8)>>1]=y2;
//enable window
gp2x_memregs[0x28da>>1]|=(3<<(window<<1));
}
}Simplemente aplicando estos dos cambios he recompilado el GP2XEngine así como el GP2XSpectrum y el Selector, y funcionan perfectamente con la televisión.
Perdón por el rollo, y espero que esto sea útil para todos.
kounch
EDIT: El ejemplo que he puesto es válido para la minimal lib 0.B siempre y cuando no se altere el valor del registro MLC_STL_HW (C000 290C) con funciones propias.