From 4471e9ee536039dad22ae41b2d800607ca1f8e75 Mon Sep 17 00:00:00 2001 From: anod <182859762@qq.com> Date: Wed, 5 Jul 2023 22:00:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E6=9E=90=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/cmdlist/from/main.c | 199 ++++++++++++++++++++++++++++++ tools/cmdlist/from/vshader.v.pica | 35 ++++++ tools/cmdlist/parse.js | 28 +++++ 3 files changed, 262 insertions(+) create mode 100644 tools/cmdlist/from/main.c create mode 100644 tools/cmdlist/from/vshader.v.pica create mode 100644 tools/cmdlist/parse.js diff --git a/tools/cmdlist/from/main.c b/tools/cmdlist/from/main.c new file mode 100644 index 0000000..d4b6f45 --- /dev/null +++ b/tools/cmdlist/from/main.c @@ -0,0 +1,199 @@ +#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); +} diff --git a/tools/cmdlist/from/vshader.v.pica b/tools/cmdlist/from/vshader.v.pica new file mode 100644 index 0000000..2c59c51 --- /dev/null +++ b/tools/cmdlist/from/vshader.v.pica @@ -0,0 +1,35 @@ +; Example PICA200 vertex shader + +; Uniforms +.fvec projection[4] + +; Constants +.constf myconst(0.0, 1.0, -1.0, 0.5) +.alias zeros myconst.xxxx ; Vector full of zeros +.alias ones myconst.yyyy ; Vector full of ones + +; Outputs +.out outpos position +.out outtc0 texcoord0 + +; Inputs (defined as aliases for convenience) +.alias inpos v0 +.alias intex v1 + +.proc main + ; Force the w component of inpos to be 1.0 + mov r0.xyz, inpos + mov r0.w, ones + + ; outpos = projectionMatrix * inpos + dp4 outpos.x, projection[0], r0 + dp4 outpos.y, projection[1], r0 + dp4 outpos.z, projection[2], r0 + dp4 outpos.w, projection[3], r0 + + ; outtc0 = intex + mov outtc0, intex + + ; We're finished + end +.end \ No newline at end of file diff --git a/tools/cmdlist/parse.js b/tools/cmdlist/parse.js new file mode 100644 index 0000000..1588643 --- /dev/null +++ b/tools/cmdlist/parse.js @@ -0,0 +1,28 @@ +function *read_one_command( words ) +{ + let pos = 0; + while( pos < words.length ) + { + let header = words[pos+1]; + let [reg, size] = read_header(header); + let param = [words[0]] + + let idx = pos+2; + while( size-- > 0 ) param.push( words[idx++] ); + pos += 2 + ( (size%2) ? size+1 : size ); + yield {reg, param} + } +} + +function *parse( bytes ) +{ + const words = new Uint32Array( bytes ); + let output = []; + while( 1 ){ + let command = yield read_one_command( words ); + if( command == null ) break; + else output.push( command ); + } + return output; +} +