libctru/libctru/source/gpu/shbin.c

134 lines
3.3 KiB
C
Raw Normal View History

/*
shdr.c _ Shader loader.
*/
2014-03-08 12:43:16 +01:00
#include <stdlib.h>
2014-08-16 23:48:05 +02:00
#include <string.h>
#include <3ds/types.h>
#include <3ds/gpu/gpu.h>
2015-01-03 02:15:44 +01:00
#include <3ds/gpu/shbin.h>
2014-03-08 12:43:16 +01:00
//please don't feed this an invalid SHBIN
DVLB_s* DVLB_ParseFile(u32* shbinData, u32 shbinSize)
2014-03-08 12:43:16 +01:00
{
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];
2015-01-03 04:16:23 +01:00
ret->DVLP.opcdescData=(u32*)malloc(sizeof(u32)*ret->DVLP.opdescSize);
if(!ret->DVLP.opcdescData)goto clean2;
int i; for(i=0;i<ret->DVLP.opdescSize;i++)ret->DVLP.opcdescData[i]=dvlpData[dvlpData[4]/4+i*2];
2014-03-11 19:00:44 +01:00
//parse DVLE
for(i=0;i<ret->numDVLE;i++)
{
DVLE_s* dvle=&ret->DVLE[i];
u32* dvleData=&shbinData[shbinData[2+i]/4];
2015-01-03 04:16:23 +01:00
dvle->dvlp=&ret->DVLP;
2014-03-11 19:00:44 +01:00
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];
2015-01-03 04:16:23 +01:00
DVLE_GenerateOutmap(dvle);
2014-03-11 19:00:44 +01:00
}
goto exit;
2015-01-03 04:16:23 +01:00
clean2:
free(ret->DVLE);
2014-03-08 12:43:16 +01:00
clean1:
free(ret);
2015-01-03 01:41:07 +01:00
ret=NULL;
2014-03-08 12:43:16 +01:00
exit:
return ret;
}
2015-01-03 04:16:23 +01:00
//TODO
void DVLB_Free(DVLB_s* dvlb)
2015-01-03 04:16:23 +01:00
{
if(!dvlb)return;
if(dvlb->DVLP.opcdescData)free(dvlb->DVLP.opcdescData);
if(dvlb->DVLE)free(dvlb->DVLE);
free(dvlb);
2015-01-03 04:16:23 +01:00
}
s8 DVLE_GetUniformRegister(DVLE_s* dvle, const char* name)
{
if(!dvle || !name)return -1;
int i; DVLE_uniformEntry_s* u=dvle->uniformTableData;
for(i=0;i<dvle->uniformTableSize;i++)
{
if(!strcmp(&dvle->symbolTableData[u->symbolOffset],name))return (s8)u->startReg-0x10;
u++;
}
return -1;
}
2015-01-03 04:16:23 +01:00
void DVLE_GenerateOutmap(DVLE_s* dvle)
2014-03-08 12:43:16 +01:00
{
if(!dvle)return;
2015-01-03 04:16:23 +01:00
memset(dvle->outmapData, 0x1F, sizeof(dvle->outmapData));
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;
2015-01-03 04:16:23 +01:00
2014-03-08 12:43:16 +01:00
for(i=0;i<dvle->outTableSize;i++)
{
2015-01-03 04:16:23 +01:00
u32* out=&dvle->outmapData[dvle->outTableData[i].regID+1];
2014-12-27 20:22:48 +01:00
u32 mask=0x00000000;
u8 tmpmask=dvle->outTableData[i].mask;
mask=(mask<<8)|((tmpmask&8)?0xFF:0x00);tmpmask<<=1;
mask=(mask<<8)|((tmpmask&8)?0xFF:0x00);tmpmask<<=1;
mask=(mask<<8)|((tmpmask&8)?0xFF:0x00);tmpmask<<=1;
mask=(mask<<8)|((tmpmask&8)?0xFF:0x00);tmpmask<<=1;
2014-03-20 23:30:11 +01:00
if(*out==0x1F1F1F1F)numAttr++;
2014-03-08 12:43:16 +01:00
2014-12-27 20:22:48 +01:00
u32 val=0x1F1F1F1F;
2014-03-08 12:43:16 +01:00
switch(dvle->outTableData[i].type)
{
2014-12-27 20:22:48 +01:00
case RESULT_POSITION: val=0x03020100; break;
case RESULT_NORMALQUAT: val=0x07060504; break;
case RESULT_COLOR: val=0x0B0A0908; break;
case RESULT_TEXCOORD0: val=0x1F1F0D0C; break;
case RESULT_TEXCOORD0W: val=0x10101010; break;
case RESULT_TEXCOORD1: val=0x1F1F0F0E; break;
case RESULT_TEXCOORD2: val=0x1F1F1716; break;
case RESULT_VIEW: val=0x1F141312; break;
2014-03-08 12:43:16 +01:00
}
2014-12-27 20:22:48 +01:00
*out=((*out)&~mask)|(val&mask);
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
}
2015-01-03 04:16:23 +01:00
dvle->outmapData[0]=numAttr;
dvle->outmapMask=attrMask;
}