libctru/libctru/source/gpu/shbin.c

134 lines
3.3 KiB
C

/*
shdr.c _ Shader loader.
*/
#include <stdlib.h>
#include <string.h>
#include <3ds/types.h>
#include <3ds/gpu/gpu.h>
#include <3ds/gpu/shbin.h>
//please don't feed this an invalid SHBIN
DVLB_s* DVLB_ParseFile(u32* shbinData, u32 shbinSize)
{
if(!shbinData)return NULL;
DVLB_s* ret=malloc(sizeof(DVLB_s));
if(!ret)goto exit;
//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=(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];
//parse DVLE
for(i=0;i<ret->numDVLE;i++)
{
DVLE_s* dvle=&ret->DVLE[i];
u32* dvleData=&shbinData[shbinData[2+i]/4];
dvle->dvlp=&ret->DVLP;
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];
dvle->outTableSize=dvleData[11];
dvle->outTableData=(DVLE_outEntry_s*)&dvleData[dvleData[10]/4];
dvle->uniformTableSize=dvleData[13];
dvle->uniformTableData=(DVLE_uniformEntry_s*)&dvleData[dvleData[12]/4];
dvle->symbolTableData=(char*)&dvleData[dvleData[14]/4];
DVLE_GenerateOutmap(dvle);
}
goto exit;
clean2:
free(ret->DVLE);
clean1:
free(ret);
ret=NULL;
exit:
return ret;
}
//TODO
void DVLB_Free(DVLB_s* dvlb)
{
if(!dvlb)return;
if(dvlb->DVLP.opcdescData)free(dvlb->DVLP.opcdescData);
if(dvlb->DVLE)free(dvlb->DVLE);
free(dvlb);
}
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;
}
void DVLE_GenerateOutmap(DVLE_s* dvle)
{
if(!dvle)return;
memset(dvle->outmapData, 0x1F, sizeof(dvle->outmapData));
int i;
u8 numAttr=0;
u8 maxAttr=0;
u8 attrMask=0;
for(i=0;i<dvle->outTableSize;i++)
{
u32* out=&dvle->outmapData[dvle->outTableData[i].regID+1];
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;
if(*out==0x1F1F1F1F)numAttr++;
u32 val=0x1F1F1F1F;
switch(dvle->outTableData[i].type)
{
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;
}
*out=((*out)&~mask)|(val&mask);
attrMask|=1<<dvle->outTableData[i].regID;
if(dvle->outTableData[i].regID+1>maxAttr)maxAttr=dvle->outTableData[i].regID+1;
}
dvle->outmapData[0]=numAttr;
dvle->outmapMask=attrMask;
}