#include #include #include #include <3ds.h> #include #include #include "vshader_shbin.h" #define CLEAR_COLOR (0x68B0D8FF) #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_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \ 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 maintex; static void sceneInit(void) { // 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 xyz AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=texcoord xy // Compute the projection matrix Mtx_OrthoTilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0, true); FILE *f = fopen("sdmc:/rgb_gba_test.bin", "rb"); u8 *const data = linearAlloc(256 * 256 * 3); u8 *dst = data; for(u32 i = 0; i < 160; i++) { fread(dst, 240 * 3, 1, f); dst += 256 * 3; } fclose(f); GSPGPU_FlushDataCache(data, 256 * 256 * 3); C3D_TexInit(&maintex, 256, 256, GPU_RGB8); const u32 flags = (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)); C3D_SyncDisplayTransfer((u32*)data, GX_BUFFER_DIM(256, 256), (u32*)maintex.data, GX_BUFFER_DIM(256, 256), flags); linearFree(data); C3D_TexSetFilter(&maintex, GPU_LINEAR, GPU_NEAREST); //C3D_TexSetWrap(&maintex, GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE); C3D_TexBind(0, &maintex); // Configure the first fragment shading substage to just pass through the vertex color // See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnvInit(env); C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, 0, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); //C3D_TexEnvScale(env, C3D_Both, GPU_TEVSCALE_2); C3D_TexEnv* env1 = C3D_GetTexEnv(1); C3D_TexEnvInit(env1); C3D_TexEnvSrc(env1, C3D_Both, GPU_PREVIOUS, GPU_PREVIOUS, 0); C3D_TexEnvFunc(env1, C3D_Both, GPU_MODULATE); } static void sceneRender(void) { // Update the uniforms C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection); // with scake=1.5, then xShift=20 // // with scake=1.0, then xShift=80, the reason is 256 is change to 512 // 80 0 0.5 1 // 0 0.6875 0 0 --> 0.6875 = 1-80/256 // 320 0 0.5 1 // 0.46875 0.6875 0 0 --> 120/256 1-80/256 // 80 160 0.5 1 // 0 1 0 0 // 320 160 0.5 1 // 0.46875 1 0 0 // Draw a textured quad directly C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP); const float scale = 1.5f; const float xShift = (400.0f - (240.0f * scale)) / 2.0f; // Bottom left corner. C3D_ImmSendAttrib(xShift, 0.0f, 0.5f, 1.0f); // v0=position xyz C3D_ImmSendAttrib(0.0f, 1.0f - (160.0f / 256.0f), 0.0f, 0.0f); // v1=texcoord xy // Bottom right corner. C3D_ImmSendAttrib(240.0f * scale + xShift, 0.0f, 0.5f, 1.0f); C3D_ImmSendAttrib(1.0f * 240.0f / 256.0f, 1.0f - (160.0f / 256.0f), 0.0f, 0.0f); // Top left corner. C3D_ImmSendAttrib(xShift, 160.0f * scale, 0.5f, 1.0f); C3D_ImmSendAttrib(0.0f, 1.0f, 0.0f, 0.0f); // Top right corner. C3D_ImmSendAttrib(240.0f * scale + xShift, 160.0f * scale, 0.5f, 1.0f); C3D_ImmSendAttrib(1.0f * 240.0f / 256.0f, 1.0f, 0.0f, 0.0f); C3D_ImmDrawEnd(); } static void sceneExit(void) { // Free the shader program shaderProgramFree(&program); DVLB_Free(vshader_dvlb); C3D_TexDelete(&maintex); } int main() { // Initialize graphics gfxInit(GSP_BGR8_OES, GSP_RGB565_OES, false); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); // Initialize the render target C3D_RenderTarget* target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, GPU_RB_DEPTH24_STENCIL8); C3D_StencilTest(false, GPU_ALWAYS, 0, 0, 0); C3D_EarlyDepthTest(false, GPU_EARLYDEPTH_GEQUAL, 0); C3D_DepthTest(false, GPU_ALWAYS, GPU_WRITE_COLOR); C3D_AlphaTest(false, GPU_ALWAYS, 0); C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); // Initialize the scene sceneInit(); // Main loop while (aptMainLoop()) { hidScanInput(); // Respond to user input u32 kDown = hidKeysDown(); if (kDown & KEY_START) break; // break in order to return to hbmenu // Render the scene C3D_FrameBegin(C3D_FRAME_SYNCDRAW); C3D_RenderTargetClear(target, C3D_CLEAR_ALL, CLEAR_COLOR, 0); C3D_FrameDrawOn(target); sceneRender(); C3D_FrameEnd(0); } // Deinitialize the scene sceneExit(); C3D_RenderTargetDelete(target); // Deinitialize graphics C3D_Fini(); gfxExit(); return 0; } // -Wl,-wrap=GX_ProcessCommandList Result __wrap_GX_ProcessCommandList(u32* buf0a, u32 buf0s, u8 flags) { static u32 dumped = 0; if(dumped == 0) { dumped++; FILE *f = fopen("sdmc:/first_cmdlist.bin", "wb"); fwrite(buf0a, buf0s, 1, f); fclose(f); } else if(dumped == 1) { dumped++; FILE *f = fopen("sdmc:/second_cmdlist.bin", "wb"); fwrite(buf0a, buf0s, 1, f); fclose(f); } return __real_GX_ProcessCommandList(buf0a, buf0s, flags); }