2014-03-08 12:43:16 +01:00
# include <stdlib.h>
2014-08-16 23:48:05 +02:00
# include <string.h>
2014-07-28 21:41:48 +02:00
# include <3ds/types.h>
# include <3ds/GSP.h>
# include <3ds/GX.h>
# include <3ds/GPU.h>
# include <3ds/SHDR.h>
# include <3ds/svc.h>
2014-03-08 12:43:16 +01:00
//please don't feed this an invalid SHBIN
DVLB_s * SHDR_ParseSHBIN ( u32 * shbinData , u32 shbinSize )
{
if ( ! shbinData ) return NULL ;
DVLB_s * ret = malloc ( sizeof ( DVLB_s ) ) ;
if ( ! ret ) goto exit ;
2014-03-11 19:00:44 +01:00
//parse DVLB
ret - > numDVLE = shbinData [ 1 ] ;
ret - > DVLE = malloc ( sizeof ( DVLE_s ) * ret - > numDVLE ) ;
if ( ! ret - > DVLE ) goto clean1 ;
//parse DVLP
u32 * dvlpData = & shbinData [ 2 + ret - > numDVLE ] ;
ret - > DVLP . codeSize = dvlpData [ 3 ] ;
ret - > DVLP . codeData = & dvlpData [ dvlpData [ 2 ] / 4 ] ;
ret - > DVLP . opdescSize = dvlpData [ 5 ] ;
ret - > DVLP . opcdescData = & dvlpData [ dvlpData [ 4 ] / 4 ] ;
//parse DVLE
int i ;
for ( i = 0 ; i < ret - > numDVLE ; i + + )
{
DVLE_s * dvle = & ret - > DVLE [ i ] ;
u32 * dvleData = & shbinData [ shbinData [ 2 + i ] / 4 ] ;
dvle - > type = ( dvleData [ 1 ] > > 16 ) & 0xFF ;
dvle - > mainOffset = dvleData [ 2 ] ;
dvle - > endmainOffset = dvleData [ 3 ] ;
dvle - > constTableSize = dvleData [ 7 ] ;
dvle - > constTableData = ( DVLE_constEntry_s * ) & dvleData [ dvleData [ 6 ] / 4 ] ;
2014-03-08 12:43:16 +01:00
2014-03-11 19:00:44 +01:00
dvle - > outTableSize = dvleData [ 11 ] ;
dvle - > outTableData = ( DVLE_outEntry_s * ) & dvleData [ dvleData [ 10 ] / 4 ] ;
2014-03-13 15:34:01 +01:00
dvle - > uniformTableSize = dvleData [ 13 ] ;
dvle - > uniformTableData = ( DVLE_uniformEntry_s * ) & dvleData [ dvleData [ 12 ] / 4 ] ;
dvle - > symbolTableData = ( char * ) & dvleData [ dvleData [ 14 ] / 4 ] ;
2014-03-11 19:00:44 +01:00
}
goto exit ;
2014-03-08 12:43:16 +01:00
clean1 :
free ( ret ) ;
exit :
return ret ;
}
2014-03-13 15:50:43 +01:00
s8 SHDR_GetUniformRegister ( DVLB_s * dvlb , char * name , u8 programID )
{
if ( ! dvlb | | ! name ) return - 1 ;
DVLE_s * dvle = & dvlb - > DVLE [ programID ] ;
int i ; DVLE_uniformEntry_s * u = dvle - > uniformTableData ;
for ( i = 0 ; i < dvle - > uniformTableSize ; i + + )
{
2014-03-13 18:27:22 +01:00
if ( ! strcmp ( & dvle - > symbolTableData [ u - > symbolOffset ] , name ) ) return ( s8 ) u - > startReg ;
2014-03-13 15:50:43 +01:00
u + + ;
}
return - 1 ;
}
2014-03-11 19:00:44 +01:00
//hm
2014-03-11 19:08:45 +01:00
static inline u8 minu8 ( u8 a , u8 b )
2014-03-11 19:00:44 +01:00
{
if ( a < b ) return a ;
return b ;
}
2014-03-11 19:08:45 +01:00
static inline u8 maxu8 ( u8 a , u8 b )
2014-03-11 19:00:44 +01:00
{
if ( a < b ) return b ;
return a ;
}
2014-03-08 12:43:16 +01:00
void DVLP_SendCode ( DVLP_s * dvlp )
{
if ( ! dvlp ) return ;
GPUCMD_AddSingleParam ( 0x000F02CB , 0x00000000 ) ;
int i ;
2014-03-11 19:00:44 +01:00
// for(i=0;i<dvlp->codeSize;i+=0x80)GPUCMD_Add(0x000F02CC, &dvlp->codeData[i], ((dvlp->codeSize-i)<0x80)?(dvlp->codeSize-i):0x80);
for ( i = 0 ; i < dvlp - > codeSize ; i + = 0x80 ) GPUCMD_Add ( 0x000F02CC , & dvlp - > codeData [ i ] , maxu8 ( minu8 ( dvlp - > codeSize - i , 0x80 ) , 0x37 ) ) ; //not sure why, but anything smaller than 0x37 seems to break stuff atm...
2014-03-08 12:43:16 +01:00
GPUCMD_AddSingleParam ( 0x000F02BF , 0x00000001 ) ;
}
void DVLP_SendOpDesc ( DVLP_s * dvlp )
{
if ( ! dvlp ) return ;
GPUCMD_AddSingleParam ( 0x000F02D5 , 0x00000000 ) ;
2014-03-11 19:00:44 +01:00
u32 param [ 0x20 ] ;
int i ;
//TODO : should probably preprocess this
for ( i = 0 ; i < dvlp - > opdescSize ; i + + ) param [ i ] = dvlp - > opcdescData [ i * 2 ] ;
GPUCMD_Add ( 0x000F02D6 , param , dvlp - > opdescSize ) ;
2014-03-08 12:43:16 +01:00
}
void DVLE_SendOutmap ( DVLE_s * dvle )
{
if ( ! dvle ) return ;
2014-03-11 19:00:44 +01:00
u32 param [ 0x7 ] = { 0x1F1F1F1F , 0x1F1F1F1F , 0x1F1F1F1F , 0x1F1F1F1F ,
0x1F1F1F1F , 0x1F1F1F1F , 0x1F1F1F1F } ;
2014-03-08 12:43:16 +01:00
int i ;
2014-03-20 18:23:48 +01:00
u8 numAttr = 0 ;
2014-03-20 23:30:11 +01:00
u8 maxAttr = 0 ;
u8 attrMask = 0 ;
2014-03-11 19:00:44 +01:00
//TODO : should probably preprocess this
2014-03-08 12:43:16 +01:00
for ( i = 0 ; i < dvle - > outTableSize ; i + + )
{
u32 * out = & param [ dvle - > outTableData [ i ] . regID ] ;
2014-03-20 23:30:11 +01:00
if ( * out = = 0x1F1F1F1F ) numAttr + + ;
2014-03-08 12:43:16 +01:00
//desc could include masking/swizzling info not currently taken into account
//also TODO : map out other output register values
switch ( dvle - > outTableData [ i ] . type )
{
case RESULT_POSITION : * out = 0x03020100 ; break ;
case RESULT_COLOR : * out = 0x0B0A0908 ; break ;
2014-03-15 21:00:37 +01:00
case RESULT_TEXCOORD0 : * out = 0x1F1F0D0C ; break ;
case RESULT_TEXCOORD1 : * out = 0x1F1F0F0E ; break ;
case RESULT_TEXCOORD2 : * out = 0x1F1F1716 ; break ;
2014-03-08 12:43:16 +01:00
}
2014-03-20 18:23:48 +01:00
2014-03-20 23:30:11 +01:00
attrMask | = 1 < < dvle - > outTableData [ i ] . regID ;
if ( dvle - > outTableData [ i ] . regID + 1 > maxAttr ) maxAttr = dvle - > outTableData [ i ] . regID + 1 ;
2014-03-08 12:43:16 +01:00
}
2014-03-20 23:30:11 +01:00
GPUCMD_AddSingleParam ( 0x000F0251 , numAttr - 1 ) ; //?
GPUCMD_AddSingleParam ( 0x000F024A , numAttr - 1 ) ; //?
GPUCMD_AddSingleParam ( 0x000F02BD , attrMask ) ; //?
GPUCMD_AddSingleParam ( 0x0001025E , numAttr - 1 ) ; //?
GPUCMD_AddSingleParam ( 0x000F004F , numAttr ) ; //?
2014-03-08 12:43:16 +01:00
GPUCMD_Add ( 0x800F0050 , param , 0x00000007 ) ;
}
2014-03-11 22:50:07 +01:00
void DVLE_SendConstants ( DVLE_s * dvle )
{
if ( ! dvle ) return ;
u32 param [ 4 ] ;
u32 rev [ 3 ] ;
u8 * rev8 = ( u8 * ) rev ;
int i ;
DVLE_constEntry_s * cnst = dvle - > constTableData ;
for ( i = 0 ; i < dvle - > constTableSize ; i + + , cnst + + )
{
memcpy ( & rev8 [ 0 ] , & cnst - > data [ 0 ] , 3 ) ;
memcpy ( & rev8 [ 3 ] , & cnst - > data [ 1 ] , 3 ) ;
memcpy ( & rev8 [ 6 ] , & cnst - > data [ 2 ] , 3 ) ;
memcpy ( & rev8 [ 9 ] , & cnst - > data [ 3 ] , 3 ) ;
param [ 0x0 ] = ( cnst - > header > > 16 ) & 0xFF ;
param [ 0x1 ] = rev [ 2 ] ;
param [ 0x2 ] = rev [ 1 ] ;
param [ 0x3 ] = rev [ 0 ] ;
GPUCMD_Add ( 0x800F02C0 , param , 0x00000004 ) ;
}
}
void SHDR_UseProgram ( DVLB_s * dvlb , u8 id )
{
if ( ! dvlb | | id > dvlb - > numDVLE ) return ;
DVLE_s * dvle = & dvlb - > DVLE [ id ] ;
DVLP_SendCode ( & dvlb - > DVLP ) ;
DVLP_SendOpDesc ( & dvlb - > DVLP ) ;
DVLE_SendOutmap ( dvle ) ;
DVLE_SendConstants ( dvle ) ;
}
2014-03-08 12:43:16 +01:00
//TODO
void SHDR_FreeDVLB ( DVLB_s * dvlb )
{
if ( ! dvlb ) return ;
}