fixed sdmc example
This commit is contained in:
parent
ce226ec1b2
commit
5ecb358b56
@ -1,92 +1,19 @@
|
|||||||
#include <3ds/types.h>
|
///////////////////////////////////////
|
||||||
#include <3ds/srv.h>
|
// SDMC example //
|
||||||
#include <3ds/svc.h>
|
///////////////////////////////////////
|
||||||
#include <3ds/gpu/gx.h>
|
|
||||||
#include <3ds/services/apt.h>
|
//this example shows you how to load a binary image file from the SD card and display it on the lower screen
|
||||||
#include <3ds/services/gsp.h>
|
//for this to work you should copy test.bin to the root of your SD card
|
||||||
#include <3ds/services/hid.h>
|
//this file was generated with GIMP by saving a 240x320 image to raw RGB
|
||||||
#include <3ds/services/fs.h>
|
|
||||||
|
#include <3ds.h>
|
||||||
#include "costable.h"
|
#include "costable.h"
|
||||||
|
|
||||||
u8* gspHeap;
|
//this will contain the data read from SDMC
|
||||||
u32* gxCmdBuf;
|
u8* buffer;
|
||||||
|
|
||||||
u8 currentBuffer;
|
|
||||||
u8* topLeftFramebuffers[2];
|
|
||||||
|
|
||||||
Handle gspEvent, gspSharedMemHandle;
|
|
||||||
|
|
||||||
void gspGpuInit()
|
|
||||||
{
|
|
||||||
gspInit();
|
|
||||||
|
|
||||||
GSPGPU_AcquireRight(NULL, 0x0);
|
|
||||||
GSPGPU_SetLcdForceBlack(NULL, 0x0);
|
|
||||||
|
|
||||||
//set subscreen to blue
|
|
||||||
u32 regData=0x01FF0000;
|
|
||||||
GSPGPU_WriteHWRegs(NULL, 0x202A04, ®Data, 4);
|
|
||||||
|
|
||||||
//grab main left screen framebuffer addresses
|
|
||||||
GSPGPU_ReadHWRegs(NULL, 0x400468, (u32*)&topLeftFramebuffers, 8);
|
|
||||||
|
|
||||||
//convert PA to VA (assuming FB in VRAM)
|
|
||||||
topLeftFramebuffers[0]+=0x7000000;
|
|
||||||
topLeftFramebuffers[1]+=0x7000000;
|
|
||||||
|
|
||||||
//setup our gsp shared mem section
|
|
||||||
u8 threadID;
|
|
||||||
svcCreateEvent(&gspEvent, 0x0);
|
|
||||||
GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &threadID);
|
|
||||||
svcMapMemoryBlock(gspSharedMemHandle, 0x10002000, 0x3, 0x10000000);
|
|
||||||
|
|
||||||
//map GSP heap
|
|
||||||
svcControlMemory((u32*)&gspHeap, 0x0, 0x0, 0x2000000, 0x10003, 0x3);
|
|
||||||
|
|
||||||
//wait until we can write stuff to it
|
|
||||||
svcWaitSynchronization(gspEvent, 0x55bcb0);
|
|
||||||
|
|
||||||
//GSP shared mem : 0x2779F000
|
|
||||||
gxCmdBuf=(u32*)(0x10002000+0x800+threadID*0x200);
|
|
||||||
|
|
||||||
currentBuffer=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gspGpuExit()
|
|
||||||
{
|
|
||||||
GSPGPU_UnregisterInterruptRelayQueue(NULL);
|
|
||||||
|
|
||||||
//unmap GSP shared mem
|
|
||||||
svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000);
|
|
||||||
svcCloseHandle(gspSharedMemHandle);
|
|
||||||
svcCloseHandle(gspEvent);
|
|
||||||
|
|
||||||
gspExit();
|
|
||||||
|
|
||||||
//free GSP heap
|
|
||||||
svcControlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, 0x2000000, MEMOP_FREE, 0x0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void swapBuffers()
|
|
||||||
{
|
|
||||||
u32 regData;
|
|
||||||
GSPGPU_ReadHWRegs(NULL, 0x400478, ®Data, 4);
|
|
||||||
regData^=1;
|
|
||||||
currentBuffer=regData&1;
|
|
||||||
GSPGPU_WriteHWRegs(NULL, 0x400478, ®Data, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyBuffer()
|
|
||||||
{
|
|
||||||
//copy topleft FB
|
|
||||||
u8 copiedBuffer=currentBuffer^1;
|
|
||||||
u8* bufAdr=&gspHeap[0x46500*copiedBuffer];
|
|
||||||
GSPGPU_FlushDataCache(NULL, bufAdr, 0x46500);
|
|
||||||
|
|
||||||
GX_RequestDma(gxCmdBuf, (u32*)bufAdr, (u32*)topLeftFramebuffers[copiedBuffer], 0x46500);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//3DS has VFPs so we could just use cos
|
||||||
|
//but we're old school so LUT4life
|
||||||
s32 pcCos(u16 v)
|
s32 pcCos(u16 v)
|
||||||
{
|
{
|
||||||
return costable[v&0x1FF];
|
return costable[v&0x1FF];
|
||||||
@ -94,71 +21,88 @@ s32 pcCos(u16 v)
|
|||||||
|
|
||||||
void renderEffect()
|
void renderEffect()
|
||||||
{
|
{
|
||||||
u8* bufAdr=&gspHeap[0x46500*currentBuffer];
|
static int cnt;
|
||||||
|
u8* bufAdr=gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||||
|
|
||||||
if(!currentBuffer)return;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
for(i=1;i<400;i++)
|
for(i=1;i<400;i++)
|
||||||
{
|
{
|
||||||
for(j=1;j<240;j++)
|
for(j=1;j<240;j++)
|
||||||
{
|
{
|
||||||
u32 v=(j+i*240)*3;
|
u32 v=(j+i*240)*3;
|
||||||
bufAdr[v]=(pcCos(i)+4096)/32;
|
bufAdr[v]=(pcCos(i+cnt)+4096)/32;
|
||||||
bufAdr[v+1]=0x00;
|
bufAdr[v+1]=(pcCos(j-256+cnt)+4096)/64;
|
||||||
bufAdr[v+2]=0xFF*currentBuffer;
|
bufAdr[v+2]=(pcCos(i+128-cnt)+4096)/32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
srvInit();
|
//initialize the services we're going to be using
|
||||||
|
srvInit(); //needed for everything
|
||||||
|
aptInit(); //needed for everything
|
||||||
|
hidInit(NULL); //needed for input
|
||||||
|
gfxInit(); //makes displaying to screen easier
|
||||||
|
fsInit(); //needed for filesystem stuff
|
||||||
|
|
||||||
aptInit(APPID_APPLICATION);
|
u64 size;
|
||||||
|
|
||||||
gspGpuInit();
|
|
||||||
|
|
||||||
hidInit(NULL);
|
|
||||||
|
|
||||||
Handle fsuHandle;
|
|
||||||
srvGetServiceHandle(&fsuHandle, "fs:USER");
|
|
||||||
FSUSER_Initialize(fsuHandle);
|
|
||||||
|
|
||||||
Handle fileHandle;
|
|
||||||
u32 bytesRead;
|
u32 bytesRead;
|
||||||
|
Handle fileHandle;
|
||||||
|
//setup SDMC archive
|
||||||
FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
|
FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
|
||||||
FS_path filePath=(FS_path){PATH_CHAR, 10, (u8*)"/test.bin"};
|
//create file path struct (note : FS_makePath actually only supports PATH_CHAR, it will change in the future)
|
||||||
FSUSER_OpenFileDirectly(fsuHandle, &fileHandle, sdmcArchive, filePath, FS_OPEN_READ, FS_ATTRIBUTE_NONE);
|
FS_path filePath=FS_makePath(PATH_CHAR, "/test.bin");
|
||||||
FSFILE_Read(fileHandle, &bytesRead, 0x0, (u32*)gspHeap, 0x46500);
|
|
||||||
FSFILE_Close(fileHandle);
|
|
||||||
|
|
||||||
APP_STATUS status;
|
//open file
|
||||||
while((status=aptGetStatus())!=APP_EXITING)
|
Result ret=FSUSER_OpenFileDirectly(NULL, &fileHandle, sdmcArchive, filePath, FS_OPEN_READ, FS_ATTRIBUTE_NONE);
|
||||||
|
//check for errors : exit if there is one
|
||||||
|
if(ret)goto exit;
|
||||||
|
|
||||||
|
//get file size
|
||||||
|
ret=FSFILE_GetSize(fileHandle, &size);
|
||||||
|
if(ret)goto exit;
|
||||||
|
|
||||||
|
//allocate a buffer on linear heap (could just be a malloc fwiw)
|
||||||
|
buffer=linearAlloc(size);
|
||||||
|
if(!buffer)goto exit;
|
||||||
|
|
||||||
|
//read contents !
|
||||||
|
ret=FSFILE_Read(fileHandle, &bytesRead, 0x0, buffer, size);
|
||||||
|
if(ret || size!=bytesRead)goto exit;
|
||||||
|
|
||||||
|
//close the file because we like being nice and tidy
|
||||||
|
ret=FSFILE_Close(fileHandle);
|
||||||
|
if(ret)goto exit;
|
||||||
|
|
||||||
|
while(aptMainLoop())
|
||||||
{
|
{
|
||||||
if(status==APP_RUNNING)
|
//exit when user hits B
|
||||||
{
|
hidScanInput();
|
||||||
u32 PAD=hidSharedMem[7];
|
if(keysHeld()&KEY_B)break;
|
||||||
|
|
||||||
|
//render rainbow
|
||||||
renderEffect();
|
renderEffect();
|
||||||
swapBuffers();
|
|
||||||
copyBuffer();
|
//copy buffer to lower screen (don't have to do it every frame)
|
||||||
u32 regData=PAD|0x01000000;
|
memcpy(gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, NULL, NULL), buffer, size);
|
||||||
GSPGPU_WriteHWRegs(NULL, 0x202A04, ®Data, 4);
|
|
||||||
svcSleepThread(1000000000);
|
//wait & swap
|
||||||
}
|
gfxSwapBuffersGpu();
|
||||||
else if(status == APP_SUSPENDING)
|
gspWaitForEvent(GSPEVENT_VBlank0, false);
|
||||||
{
|
|
||||||
aptReturnToMenu();
|
|
||||||
}
|
|
||||||
else if(status == APP_SLEEPMODE)
|
|
||||||
{
|
|
||||||
aptWaitStatusEvent();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svcCloseHandle(fsuHandle);
|
//cleanup and return
|
||||||
|
//returning from main() returns to hbmenu when run under ninjhax
|
||||||
|
exit:
|
||||||
|
//closing all handles is super important
|
||||||
|
svcCloseHandle(fileHandle);
|
||||||
|
//closing all services even more so
|
||||||
|
gfxExit();
|
||||||
hidExit();
|
hidExit();
|
||||||
gspGpuExit();
|
|
||||||
aptExit();
|
aptExit();
|
||||||
svcExitProcess();
|
srvExit();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
1
examples/sdmc/test.bin
Normal file
1
examples/sdmc/test.bin
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user