Skip to content

Instantly share code, notes, and snippets.

@handsomematt
Created January 19, 2016 02:22
Show Gist options
  • Save handsomematt/ca542d2fa7412249e12d to your computer and use it in GitHub Desktop.
Save handsomematt/ca542d2fa7412249e12d to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <3ds.h>
#include <citro3d.h>
#include "vshader_shbin.h"
static const u32 SHARED_FONT_SIZE = 0x300000;
struct systemfont_header {
u32 unk1;
u32 unk2;
u32 font_size;
// rest is 0
};
struct cfnt_header {
char signature[4];
u16 endianness;
u16 headersize;
u32 version;
u32 filesize;
u32 num_blocks;
};
struct finf_header {
char signature[4];
u32 sectionsize;
u8 fonttype;
u8 linefeed;
u16 altercharindex;
u8 defaultwidth1;
u8 defaultwidth2;
u8 defaultwidth3;
u8 encoding;
u32 tglpoffset;
u32 cwdhoffset;
u32 cmapoffset;
u8 height;
u8 width;
u8 ascent;
u8 padding;
};
struct tglp_header {
char signature[4];
u32 sectionsize;
u8 cellwidth;
u8 cellheight;
u8 baselinepos;
u8 maxcharwidth;
u32 sheet_size;
u16 num_sheets;
u16 sheetformat;
u16 sheet_num_rows;
u16 sheet_num_lines;
u16 sheet_width;
u16 sheet_height;
u32 sheet_data_offset;
};
#define CLEAR_COLOR 0x659CEFFF
// Used to transfer the final rendered display to the framebuffer
#define DISPLAY_TRANSFER_FLAGS \
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
// Used to convert textures to 3DS tiled format
// Note: vertical flip flag set so 0,0 is top left of texture
#define TEXTURE_TRANSFER_FLAGS \
(GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | \
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
static DVLB_s* vshader_dvlb;
static shaderProgram_s program;
static int uLoc_projection;
static C3D_Mtx projection;
static C3D_Tex sheet_tex;
static void sceneInit(void) {
int i;
// Load the vertex shader, create a shader program and bind it
vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size);
shaderProgramInit(&program);
shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]);
C3D_BindProgram(&program);
// Get the location of the uniforms
uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection");
// Configure attributes for use with the vertex shader
// Attribute format and element count are ignored in immediate mode
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo);
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v2=texcoord
// Compute the projection matrix
// Note: we're setting top to 240 here so origin is at top left.
Mtx_OrthoTilt(&projection, 0.0, 400.0, 240.0, 0.0, 0.0, 1.0);
// Configure buffers
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, 0, 0);
C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
}
static void sceneRender(int x, int y) {
int width = 128;
int height = 32;
C3D_ImmDrawBegin(GPU_TRIANGLES);
C3D_ImmSendAttrib(x, y, 0.5f, 0.0f); // v0=position
C3D_ImmSendAttrib( 0.0f, 1.0f, 0.0f, 0.0f);
C3D_ImmSendAttrib(x+width, y+height, 0.5f, 0.0f);
C3D_ImmSendAttrib( 1.0f, 0.0f, 0.0f, 0.0f);
C3D_ImmSendAttrib(x+width, y, 0.5f, 0.0f);
C3D_ImmSendAttrib( 1.0f, 1.0f, 0.0f, 0.0f);
C3D_ImmSendAttrib(x, y, 0.5f, 0.0f); // v0=position
C3D_ImmSendAttrib( 0.0f, 1.0f, 0.0f, 0.0f);
C3D_ImmSendAttrib(x, y+height, 0.5f, 0.0f);
C3D_ImmSendAttrib( 0.0f, 0.0f, 0.0f, 0.0f);
C3D_ImmSendAttrib(x+width, y+height, 0.5f, 0.0f);
C3D_ImmSendAttrib( 1.0f, 0.0f, 0.0f, 0.0f);
C3D_ImmDrawEnd();
}
static void sceneExit(void) {
// Free the shader program
shaderProgramFree(&program);
DVLB_Free(vshader_dvlb);
}
static bool C3Di_TexInitInVRAM(C3D_Tex* tex, int width, int height, GPU_TEXCOLOR format, void *data, u32 size)
{
tex->data = data;
tex->width = width;
tex->height = height;
tex->param = GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST);
tex->fmt = format;
tex->size = size;
return true;
}
int main()
{
aptInit();
gfxInitDefault();
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
consoleInit(GFX_BOTTOM, NULL);
Handle apt_handle;
srvGetServiceHandle(&apt_handle, "APT:U");
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00440000;
svcSendSyncRequest(apt_handle);
Handle mem_handle = cmdbuf[4];
void* shared_font_addr = reinterpret_cast<void*>(cmdbuf[2]);
svcCloseHandle(apt_handle);
svcMapMemoryBlock(mem_handle, 0, MEMPERM_READ, MEMPERM_DONTCARE);
printf("mem_handle: %p\n", mem_handle);
printf("shared_font_addr: %p\n", shared_font_addr);
systemfont_header* headertest = (struct systemfont_header*)shared_font_addr;
cfnt_header* cfnt = (struct cfnt_header*)(shared_font_addr + 0x80);
finf_header* finf = (struct finf_header*)(shared_font_addr + 0x80 + cfnt->headersize);
printf("header font_size: %d\n", headertest->font_size);
printf("cfntsig: %.*s\n", 4, cfnt->signature);
printf("finfsig: %.*s\n", 4, finf->signature);
printf("tglpoffset: %p\n", finf->tglpoffset);
printf("cwdhoffset: %p\n", finf->cwdhoffset);
printf("cmapoffset: %p\n", finf->cmapoffset);
tglp_header* tglp = (struct tglp_header*)(finf->tglpoffset - 8);
printf("tglpsig: %.*s\n", 4, tglp->signature);
printf("tglp format: %d\n", tglp->sheetformat);
u32 sheetptr = tglp->sheet_data_offset;
u32 sheets[tglp->num_sheets];
for (int i=0; i<tglp->num_sheets; i++)
{
sheets[i] = sheetptr;
sheetptr += tglp->sheet_size;
}
printf("loaded %d sheet pointers\n", tglp->num_sheets);
printf("sheets[13]: %p\n", sheets[13]);
sceneInit();
// Initialize the render target
C3D_RenderTarget* target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetSetClear(target, C3D_CLEAR_ALL, CLEAR_COLOR, 0);
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
printf("texinit: %d, %d\n", tglp->sheet_width, tglp->sheet_height);
C3Di_TexInitInVRAM(&sheet_tex, tglp->sheet_width, tglp->sheet_height, (GPU_TEXCOLOR)tglp->sheetformat, (void*)sheets[0], tglp->sheet_size);
int row = 0;
while (aptMainLoop()) {
gfxFlushBuffers();
gfxSwapBuffers();
hidScanInput();
if (hidKeysHeld() & KEY_START) {
break;
}
if (hidKeysHeld() & KEY_DOWN)
row++;
if (hidKeysHeld() & KEY_UP)
row--;
if (row < 0) row = 0;
if (row > 500) row = 500;
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C3D_FrameDrawOn(target);
C3D_TexBind(0, &sheet_tex);
// Update the uniforms
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection);
for (int y = 0; y < 9; y++)
{
for (int x = 0; x < 3; x++)
{
C3Di_TexInitInVRAM(&sheet_tex, tglp->sheet_width, tglp->sheet_height, (GPU_TEXCOLOR)tglp->sheetformat, (void*)sheets[(row*3)+(y*3)+x], tglp->sheet_size);
C3D_TexBind(0, &sheet_tex);
sceneRender(8 + (x*128), y*32);
}
}
C3D_FrameEnd(0);
//draw_sheet((u8*)sheets[0], tglp->sheet_width, tglp->sheet_height);
gspWaitForEvent(GSPGPU_EVENT_VBlank0, false);
}
sceneExit();
C3D_Fini();
gfxExit();
aptExit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment