libctru/libctru/source/SHDR.c

168 lines
3.7 KiB
C
Raw Normal View History

2014-03-08 12:43:16 +01:00
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctr/types.h>
#include <ctr/GSP.h>
#include <ctr/GX.h>
#include <ctr/GPU.h>
#include <ctr/SHDR.h>
#include <ctr/svc.h>
//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-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-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];
//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;
}
}
GPUCMD_Add(0x800F0050, param, 0x00000007);
}
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;
}