void gpuFrameBegin(void) { // Configure the viewport and the depth linear conversion function GPU_SetViewport( (u32*)osConvertVirtToPhys((u32)depthBuf), (u32*)osConvertVirtToPhys((u32)colorBuf), 0, 0, 240, 400); // The top screen is physically 240x400 pixels GPU_DepthMap(-1.0f, 0.0f); // calculate the depth value from the Z coordinate in the following way: -1.0*z + 0.0 // Configure some boilerplate GPU_SetFaceCulling(GPU_CULL_BACK_CCW); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00); GPU_SetStencilOp(GPU_KEEP, GPU_KEEP, GPU_KEEP); GPU_SetBlendingColor(0,0,0,0); GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL); // This is unknown GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0); GPUCMD_AddWrite(GPUREG_0118, 0); // Configure alpha blending and test GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00); int i; for (i = 0; i < 6; i ++) GPU_SetDummyTexEnv(i); }
void sf2d_start_frame(gfxScreen_t screen, gfx3dSide_t side) { sf2d_pool_reset(); GPUCMD_SetBufferOffset(0); // Only upload the uniform if the screen changes if (screen != cur_screen) { if (screen == GFX_TOP) { matrix_gpu_set_uniform(ortho_matrix_top, projection_desc); } else { matrix_gpu_set_uniform(ortho_matrix_bot, projection_desc); } cur_screen = screen; } int screen_w; if (screen == GFX_TOP) { screen_w = 400; cur_side = side; } else { screen_w = 320; } GPU_SetViewport((u32 *)osConvertVirtToPhys((u32)gpu_depth_fb_addr), (u32 *)osConvertVirtToPhys((u32)gpu_fb_addr), 0, 0, 240, screen_w); GPU_DepthMap(-1.0f, 0.0f); GPU_SetFaceCulling(GPU_CULL_NONE); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00); GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP); GPU_SetBlendingColor(0,0,0,0); GPU_SetDepthTestAndWriteMask(true, GPU_GEQUAL, GPU_WRITE_ALL); GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0); GPUCMD_AddWrite(GPUREG_0118, 0); GPU_SetAlphaBlending( GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ZERO ); GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00); GPU_SetDummyTexEnv(1); GPU_SetDummyTexEnv(2); GPU_SetDummyTexEnv(3); GPU_SetDummyTexEnv(4); GPU_SetDummyTexEnv(5); }
void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float)x+tex_w, (float)y, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+tex_h, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float)x+tex_w, (float)y+tex_h, 0.5f}; float u0 = tex_x/(float)texture->pow2_w; float v0 = tex_y/(float)texture->pow2_h; float u1 = (tex_x+tex_w)/(float)texture->pow2_w; float v1 = (tex_y+tex_h)/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){u0, v0}; vertices[1].texcoord = (sf2d_vector_2f){u1, v0}; vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
void glBindTexture(GLenum target, GLuint texture) { //printf("bind texture: %d %08x\n", ctr_state.client_texture_current, texture); if (texture == 0) { DBGPRINT("binding 0 texture\n"); ctr_state.bound_texture[ctr_state.client_texture_current] = 0; return; } CTR_TEXTURE *tx = ctr_handle_get(CTR_HANDLE_TEXTURE, texture); DBGPRINT("bound texture: %d %08x %08x\n", ctr_state.client_texture_current, texture, tx); if (tx == 0) { tx = malloc(sizeof(*tx)); if (tx == 0) { return; } memset(tx, 0, sizeof(*tx)); tx->params = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT); ctr_handle_set(CTR_HANDLE_TEXTURE, texture, tx); } ctr_state.bound_texture[ctr_state.client_texture_current] = texture; //#ifdef _3DS if (tx->data) { myGPU_SetTexture( __tmu[ctr_state.client_texture_current], osConvertVirtToPhys((u32)tx->data), tx->width, // Width tx->height, // Height tx->params, // Flags tx->format // Pixel format ); } //#endif }
static void sceneRender(void) { // Bind the shader program shaderProgramUse(&program); // 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 GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // RGB channels GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // Alpha GPU_TEVOPERANDS(0, 0, 0), // RGB GPU_TEVOPERANDS(0, 0, 0), // Alpha GPU_REPLACE, GPU_REPLACE, // RGB, Alpha 0xFFFFFFFF); // Configure the "attribute buffers" (that is, the vertex input buffers) GPU_SetAttributeBuffers( 1, // Number of inputs per vertex (u32*)osConvertVirtToPhys((u32)vbo_data), // Location of the VBO GPU_ATTRIBFMT(0, 3, GPU_FLOAT), // Format of the inputs (in this case the only input is a 3-element float vector) 0xFFE, // Unused attribute mask, in our case bit 0 is cleared since it is used 0x0, // Attribute permutations (here it is the identity) 1, // Number of buffers (u32[]) { 0x0 }, // Buffer offsets (placeholders) (u64[]) { 0x0 }, // Attribute permutations for each buffer (identity again) (u8[]) { 1 }); // Number of attributes for each buffer // Upload the projection matrix GPU_SetFloatUniformMatrix(GPU_VERTEX_SHADER, uLoc_projection, &projection); // Draw the VBO GPU_DrawArray(GPU_TRIANGLES, vertex_list_count); }
// topscreen void renderFrame() { GPU_SetViewport((u32*)osConvertVirtToPhys((u32)gpuDOut),(u32*)osConvertVirtToPhys((u32)gpuOut),0,0,240*2,400); GPU_DepthRange(-1.0f, 0.0f); GPU_SetFaceCulling(GPU_CULL_BACK_CCW); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00); GPU_SetStencilOp(GPU_KEEP, GPU_KEEP, GPU_KEEP); GPU_SetBlendingColor(0,0,0,0); GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL); GPUCMD_AddSingleParam(0x00010062, 0); GPUCMD_AddSingleParam(0x000F0118, 0); //setup shader SHDR_UseProgram(shader, 0); GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00); GPU_SetTextureEnable(GPU_TEXUNIT0); GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_MODULATE, 0xFFFFFFFF); GPU_SetDummyTexEnv(1); GPU_SetDummyTexEnv(2); GPU_SetDummyTexEnv(3); GPU_SetDummyTexEnv(4); GPU_SetDummyTexEnv(5); //texturing stuff GPU_SetTexture(GPU_TEXUNIT0, (u32*)osConvertVirtToPhys((u32)texData),128,128,GPU_TEXTURE_MAG_FILTER(GPU_NEAREST)|GPU_TEXTURE_MIN_FILTER(GPU_NEAREST),GPU_RGBA8); GPU_SetAttributeBuffers(3, (u32*)osConvertVirtToPhys((u32)texData), GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 2, GPU_FLOAT)|GPU_ATTRIBFMT(2, 3, GPU_FLOAT), 0xFFC, 0x210, 1, (u32[]){0x00000000}, (u64[]){0x210}, (u8[]){3}); //setup lighting (this is specific to our shader) vect3Df_s lightDir=vnormf(vect3Df(cos(lightAngle), -1.0f, sin(lightAngle))); GPU_SetUniform(SHDR_GetUniformRegister(shader, "lightDirection", 0), (u32*)(float[]){0.0f, -lightDir.z, -lightDir.y, -lightDir.x}, 1);
void myCSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1) { u32 physaddr0 = 0; u32 physaddr1 = 0; physaddr0 = osConvertVirtToPhys((u32)vaddr0); physaddr1 = osConvertVirtToPhys((u32)vaddr1); CSND_sharedmemtype0_cmde(channel, looping, encoding, samplerate, unk0, unk1, physaddr0, physaddr1, totalbytesize); CSND_sharedmemtype0_cmd8(channel, samplerate); if(looping) { if(physaddr1>physaddr0)totalbytesize = (u32)physaddr1 - (u32)physaddr0; CSND_sharedmemtype0_cmd3(channel, physaddr1, totalbytesize); } CSND_sharedmemtype0_cmd8(channel, samplerate); CSND_sharedmemtype0_cmd9(channel, 0xffff); CSND_setchannel_playbackstate(channel, 1); }
void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); //Don't even try to understand what I'm doing here (because I don't even understand it). //Matrices are boring. int w2 = (texture->width * x_scale)/2.0f; int h2 = (texture->height * y_scale)/2.0f; vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, 0.5f}; float u0 = tex_x/(float)texture->pow2_w; float v0 = tex_y/(float)texture->pow2_h; float u1 = (tex_x+tex_w)/(float)texture->pow2_w; float v1 = (tex_y+tex_h)/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){u0, v0}; vertices[1].texcoord = (sf2d_vector_2f){u1, v0}; vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; float m[4*4]; matrix_set_z_rotation(m, rad); sf2d_vector_3f rot[4]; int i; for (i = 0; i < 4; i++) { vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]); } vertices[0].position = (sf2d_vector_3f){rot[0].x + x + w2, rot[0].y + y + h2, rot[0].z}; vertices[1].position = (sf2d_vector_3f){rot[1].x + x * x_scale + w2, rot[1].y + y + h2, rot[1].z}; vertices[2].position = (sf2d_vector_3f){rot[2].x + x + w2, rot[2].y + y * y_scale + h2, rot[2].z}; vertices[3].position = (sf2d_vector_3f){rot[3].x + x * x_scale + w2, rot[3].y + y * y_scale + h2, rot[3].z}; sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
//Custom CSND_playsound to prevent audio desynchronization and enable stereo sounds void My_CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 l_vol, u32 r_vol) { u32 physaddr0 = 0; u32 physaddr1 = 0; physaddr0 = osConvertVirtToPhys((u32)vaddr0); physaddr1 = osConvertVirtToPhys((u32)vaddr1); CSND_sharedmemtype0_cmde(channel, looping, encoding, samplerate, 2, 0, physaddr0, physaddr1, totalbytesize); CSND_sharedmemtype0_cmd8(channel, samplerate); if(looping) { if(physaddr1>physaddr0)totalbytesize-= (u32)physaddr1 - (u32)physaddr0; CSND_sharedmemtype0_cmd3(channel, physaddr1, totalbytesize); } CSND_sharedmemtype0_cmd8(channel, samplerate); u32 cmdparams[0x18>>2]; memset(cmdparams, 0, 0x18); cmdparams[0] = channel & 0x1f; cmdparams[1] = l_vol | (r_vol<<16); CSND_writesharedmem_cmdtype0(0x9, (u8*)&cmdparams); }
void drawPortals(portal_s* portals[], int n, renderSceneCallback_t callback, camera_s* c, int depth, u8 stencil) { if(!portals || !portalVertexData || !callback || !c || !depth)return; int i; gsSwitchRenderMode(-1); GPU_SetAttributeBuffers( 1, // number of attributes (u32*)osConvertVirtToPhys(portalBaseAddr), // we use the start of linear heap as base since that's where all our buffers are located GPU_ATTRIBFMT(0, 3, GPU_FLOAT), // we want v0 (vertex position) 0xFFE, // mask : we want v0 0x0, // permutation : we use identity 1, // number of buffers : we have one attribute per buffer (u32[]){(u32)portalOutlineVertexData-portalBaseAddr}, // buffer offsets (placeholders) (u64[]){0x0}, // attribute permutations for each buffer (u8[]){1} // number of attributes for each buffer ); gsPushMatrix(); shaderInstanceSetBool(portalProgram.vertexShader, 0, true); gsSetShader(&portalProgram); //TEMP int colorUniformLoc = shaderInstanceGetUniformLocation(portalProgram.vertexShader, "color"); GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_MODULATE, 0xFFFFFFFF); for(i=0; i<n; i++) { portal_s* p = portals[i]; if(!p->draw)continue; GPU_SetFloatUniform(GPU_VERTEX_SHADER, colorUniformLoc, (u32*)(float[]){1.0f, p->color.z, p->color.y, p->color.x}, 1); gsPushMatrix(); gsTranslate(p->position.x, p->position.y, p->position.z); gsMultMatrix(p->matrix); gsUpdateTransformation(); GPU_DrawArray(GPU_TRIANGLE_STRIP, portalNumVertices); gsPopMatrix(); }
void myCSND_SetSound(u32 chn, u32 flags, u32 sampleRate, void* data0, void *data1, u32 size, u32 leftvol, u32 rightvol) { u32 paddr0 = 0, paddr1 = 0; int encoding = (flags >> 12) & 3; int loopMode = (flags >> 10) & 3; if (encoding != CSND_ENCODING_PSG) { if (data0) paddr0 = osConvertVirtToPhys((u32)data0); if (data1) paddr1 = osConvertVirtToPhys((u32)data1); if (encoding == CSND_ENCODING_ADPCM) { int adpcmSample = ((s16*)data0)[-2]; int adpcmIndex = ((u8*)data0)[-2]; CSND_SetAdpcmState(chn, 0, adpcmSample, adpcmIndex); } } u32 timer = CSND_TIMER(sampleRate); if (timer < 0x0042) timer = 0x0042; else if (timer > 0xFFFF) timer = 0xFFFF; flags &= ~0xFFFF001F; flags |= SOUND_ENABLE | SOUND_CHANNEL(chn) | (timer << 16); CSND_SetChnRegs(flags, paddr0, paddr1, size); if (loopMode == CSND_LOOPMODE_NORMAL && paddr1 > paddr0) { // Now that the first block is playing, configure the size of the subsequent blocks size -= paddr1 - paddr0; CSND_SetBlock(chn, 1, paddr1, size); } CSND_SetVol(chn, leftvol, rightvol); CSND_SetPlayState(chn, 1); }
void drawPlayerGun(player_s* p) { if(!p)return; gsPushMatrix(); useCamera(&p->camera); gsLoadIdentity(); GPU_SetDepthTestAndWriteMask(true, GPU_ALWAYS, GPU_WRITE_DEPTH); gsSwitchRenderMode(-1); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys(rectangleBaseAddr), // we use the start of linear heap as base since that's where all our buffers are located GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 2, GPU_FLOAT), // we want v0 (vertex position) and v1 (texcoord) 0xFFC, // mask : we want v0 and v1 0x10, // permutation : we use identity 1, // number of buffers : we have one attribute per buffer (u32[]){(u32)rectangleVertexData-rectangleBaseAddr}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); gsSetShader(&passthroughProgram); GPU_DrawArray(GPU_TRIANGLES, 6); GPU_SetDepthTestAndWriteMask(true, GPU_ALWAYS, GPU_WRITE_ALL); GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_CONFIG0, (u32)crosshairVertexData-rectangleBaseAddr); textureBind(&crosshairTexture, GPU_TEXUNIT0); GPU_DrawArray(GPU_TRIANGLES, 6); GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL); gsSwitchRenderMode(md2GsMode); gsTranslate(1.3, -1.65, -3.1); gsRotateY(p->tempAngle.y); gsRotateX(-p->tempAngle.x); gsRotateX(-0.1); gsRotateZ(M_PI/2); gsRotateY(-M_PI/2); gsRotateX(-M_PI/2); gsScale(3.0f/8, 3.0f/8, 3.0f/8); md2InstanceDraw(&p->gunInstance); gsPopMatrix(); }
void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); int w2 = texture->width/2.0f; int h2 = texture->height/2.0f; vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, 0.5f}; float u = texture->width/(float)texture->pow2_w; float v = texture->height/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f}; vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f}; vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; float m[4*4]; matrix_set_z_rotation(m, rad); sf2d_vector_3f rot[4]; int i; for (i = 0; i < 4; i++) { vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]); } for (i = 0; i < 4; i++) { vertices[i].position = (sf2d_vector_3f){rot[i].x + x + w2, rot[i].y + y + h2, rot[i].z}; } sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
void gpuDrawVbo(u32 vbo) { VboData* vboData = (VboData*) vbo; if(vboData == NULL || vboData->data == NULL) { return; } gpuUpdateState(); static u32 attributeBufferOffset = 0; GPU_SetAttributeBuffers(vboData->attributeCount, (u32*) osConvertVirtToPhys((u32) vboData->data), vboData->attributes, vboData->attributeMask, vboData->attributePermutations, 1, &attributeBufferOffset, &vboData->attributePermutations, &vboData->attributeCount); if(vboData->indices != NULL) { GPU_DrawElements((GPU_Primitive_t) vboData->primitive, (u32*) vboData->indices, vboData->numVertices); } else { GPU_DrawArray((GPU_Primitive_t) vboData->primitive, vboData->numVertices); } }
void drawEmancipationGrid(emancipationGrid_s* eg) { if(!eg)return; float l=fabs(eg->length); // TODO : animate surface texture gsPushMatrix(); gsSwitchRenderMode(md2GsMode); gsTranslate(eg->position.x, eg->position.y, eg->position.z); if(eg->direction)gsRotateY(-(M_PI/2)); if(eg->length<0)gsRotateY((M_PI/2)*2); md2InstanceDraw(&gridInstance); gsPushMatrix(); gsTranslate(l,0,0); gsRotateY((M_PI/2)*2); md2InstanceDraw(&gridInstance); gsPopMatrix(); gsSwitchRenderMode(-1); GPU_SetAttributeBuffers( 1, // number of attributes (u32*)osConvertVirtToPhys(emancipationBaseAddr), // we use the start of linear heap as base since that's where all our buffers are located GPU_ATTRIBFMT(0, 3, GPU_FLOAT), // we want v0 (vertex position) 0xFFE, // mask : we want v0 0x0, // permutation : we use identity 1, // number of buffers : we have one attribute per buffer (u32[]){(u32)emancipationRectangleVertexData-emancipationBaseAddr}, // buffer offsets (placeholders) (u64[]){0x0}, // attribute permutations for each buffer (u8[]){1} // number of attributes for each buffer ); gsSetShader(&emancipationProgram); gsScale(l, 4.0f, 1.0f); gsUpdateTransformation(); textureBind(&gridSurfaceTexture, GPU_TEXUNIT0); GPU_SetFloatUniform(GPU_VERTEX_SHADER, emancipationUniformTextureDimensions, (u32*)(float[]){0.0f, 0.0f, 0.7f, l/8}, 1);
void drawRoom(room_s* r) { if(!r)return; gsSwitchRenderMode(-1); gsSetShader(&roomProgram); GPU_SetAttributeBuffers( 3, // number of attributes (u32*)osConvertVirtToPhys(roomBaseAddr), // we use the start of linear heap as base since that's where all our buffers are located GPU_ATTRIBFMT(0, 3, GPU_SHORT)|GPU_ATTRIBFMT(1, 2, GPU_SHORT)|GPU_ATTRIBFMT(2, 2, GPU_SHORT), // we want v0, v1 and v2 0xFF8, // mask : we want v0, v1 and v2 0x210, // permutation : we use identity 1, // number of buffers : we have one attribute per buffer (u32[]){(u32)r->vertexBuffer-roomBaseAddr}, // buffer offsets (placeholders) (u64[]){0x210}, // attribute permutations for each buffer (u8[]){3} // number of attributes for each buffer ); GPU_SetTextureEnable(GPU_TEXUNIT0|GPU_TEXUNIT1); GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_TEXTURE1, GPU_PRIMARY_COLOR), GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVOPERANDS(0,2,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_MODULATE, 0xFFFFFFFF); gsPushMatrix(); gsScale(TILESIZE_FLOAT*2, HEIGHTUNIT_FLOAT, TILESIZE_FLOAT*2); gsUpdateTransformation(); int i; for(i=0; i<r->numIndexBuffers; i++) { textureBind(r->indexBufferTextures[i], GPU_TEXUNIT0); textureBind(r->lightingData.data.lightMap.texture, GPU_TEXUNIT1); GPU_SetFloatUniform(GPU_VERTEX_SHADER, roomUniformTextureDimensions, (u32*)(float[]){0.0f, 0.0f, 1.0f / r->indexBufferTextures[i]->height, 1.0f / r->indexBufferTextures[i]->width}, 1); GPU_DrawElements(GPU_UNKPRIM, (u32*)((u32)r->indexBuffers[i]-roomBaseAddr), r->numIndices[i]); }
void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); int ws = texture->width * x_scale; int hs = texture->height * y_scale; vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, 0.5f}; vertices[1].position = (sf2d_vector_3f){(float)x+ws, (float)y, 0.5f}; vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+hs, 0.5f}; vertices[3].position = (sf2d_vector_3f){(float)x+ws, (float)y+hs, 0.5f}; float u = texture->width/(float)texture->pow2_w; float v = texture->height/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f}; vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f}; vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; sf2d_bind_texture(texture, GPU_TEXUNIT0); GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, //0b1100 0x10, 1, //number of buffers (u32[]){0x0}, // buffer offsets (placeholders) (u64[]){0x10}, // attribute permutations for each buffer (u8[]){2} // number of attributes for each buffer ); GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); }
void sf2d_bind_texture(const sf2d_texture *texture, GPU_TEXUNIT unit) { GPU_SetTextureEnable(unit); GPU_SetTexEnv( 0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_TEXTURE0, GPU_TEXTURE0), GPU_TEVSOURCES(GPU_TEXTURE0, GPU_TEXTURE0, GPU_TEXTURE0), GPU_TEVOPERANDS(0, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_REPLACE, GPU_REPLACE, 0xFFFFFFFF ); GPU_SetTexture( unit, (u32 *)osConvertVirtToPhys((u32)texture->data), // width and height swapped? texture->pow2_h, texture->pow2_w, GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST), texture->pixel_format ); }
// topscreen void renderMenuFrame(u32* outBuffer, u32* outDepthBuffer) { GPU_SetViewport((u32*)osConvertVirtToPhys((u32)outDepthBuffer),(u32*)osConvertVirtToPhys((u32)outBuffer),0,0,240,400); GPU_DepthMap(-1.0f, 0.0f); GPU_SetFaceCulling(GPU_CULL_FRONT_CCW); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00); GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP); GPU_SetBlendingColor(0,0,0,0); GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL); GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0); GPUCMD_AddWrite(GPUREG_0118, 0); GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00); GPU_SetTextureEnable(GPU_TEXUNIT0); GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_MODULATE, 0xFFFFFFFF); GPU_SetDummyTexEnv(1); GPU_SetDummyTexEnv(2); GPU_SetDummyTexEnv(3); GPU_SetDummyTexEnv(4); GPU_SetDummyTexEnv(5); gsMatrixMode(GS_MODELVIEW); gsPushMatrix(); gsLoadIdentity(); useCamera(&menuCamera); gsSwitchRenderMode(md2GsMode); md2InstanceDraw(&gladosInstance); md2InstanceDraw(&gladosLairInstance); gsPopMatrix(); GPU_SetDepthTestAndWriteMask(true, GPU_ALWAYS, GPU_WRITE_ALL); if(currentCameraState==2) { gsPushMatrix(); gsSwitchRenderMode(-1); GPU_SetAttributeBuffers( 1, // number of attributes (u32*)osConvertVirtToPhys(logoBaseAddr), // we use the start of linear heap as base since that's where all our buffers are located GPU_ATTRIBFMT(0, 3, GPU_FLOAT), // we want v0 (vertex position) 0xFFE, // mask : we want v0 0x0, // permutation : we use identity 1, // number of buffers : we have one attribute per buffer (u32[]){(u32)logoRectangleVertexData-logoBaseAddr}, // buffer offsets (placeholders) (u64[]){0x0}, // attribute permutations for each buffer (u8[]){1} // number of attributes for each buffer ); gsSetShader(&logoProgram); gsMatrixMode(GS_MODELVIEW); gsLoadIdentity(); gsPushMatrix(); gsTranslate(0.15f, 0.325f, 0.0f); gsScale(64.0f * 2.0f / 240.0f, 64.0f * 2.0f / 400.0f, 1.0f); gsTranslate(0.5f, 0.5f, 0.0f); gsRotateZ(logoangle+=0.01f); gsTranslate(-0.5f, -0.5f, 0.0f); gsUpdateTransformation(); textureBind(&rotateLogoTexture, GPU_TEXUNIT0); GPU_SetFloatUniform(GPU_VERTEX_SHADER, logoUniformTextureDimensions, (u32*)(float[]){0.0f, 0.0f, 1.0f, 1.0f}, 1);
void RectangleShape::draw() { if (!_device->isInitialized() || !_visible) return; updateTransform(); if (_color.a > 0) { ShaderProgram::setUniform(UNIFORM_MODELVIEW_NAME, getCombinedTransform()); #ifdef _3DS auto vertices = VertexPool::getInstance()-> pushVertices<VertexPositionTexture>(4); vertices[0].position = Vec2(0, 0); vertices[1].position = Vec2(_size.x, 0); vertices[2].position = Vec2(0, _size.y); vertices[3].position = Vec2(_size.x, _size.y); vertices[0].texcoord = Vec2::Zero; vertices[1].texcoord = Vec2::Zero; vertices[2].texcoord = Vec2::Zero; vertices[3].texcoord = Vec2::Zero; //========================================================================= GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, GPU_CONSTANT), GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, GPU_CONSTANT), GPU_TEVOPERANDS(0, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_REPLACE, GPU_REPLACE, _color.r | _color.g << 8 | _color.b << 16 | _color.a << 24); u32 bufferOffsets[] = { 0x00 }; u64 bufferPermutations[] = { 0x10 }; u8 bufferNumAttributes[] = { 2 }; GPU_SetAttributeBuffers( 2, (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 2, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFFC, 0x10, 1, bufferOffsets, bufferPermutations, bufferNumAttributes); GPU_DrawArray(GPU_TRIANGLE_STRIP, 0, 4); #else Vec4 c = _color.toVector(); float vertices[] = { 0, 0, -0.5f, c.x, c.y, c.z, c.w, 0, 0, _size.x, 0, -0.5f, c.x, c.y, c.z, c.w, 0, 0, 0, _size.y, -0.5f, c.x, c.y, c.z, c.w, 0, 0, _size.x, _size.y, -0.5f, c.x, c.y, c.z, c.w, 0, 0 }; glUniform1i(ShaderProgram::getCurrentProgram()-> getUniformLocation("textureEnabled"), false); glBindBuffer(GL_ARRAY_BUFFER, _vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 36, vertices); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(_vao); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); #endif // _3DS } if (getOutlineColor().a > 0) { _outline.setTransform(getCombinedTransform()); _outline.setLine(0, 0, _size.x, 0); _outline.draw(); _outline.setLine(_size.x, 0, _size.x, _size.y); _outline.draw(); _outline.setLine(0, _size.y, _size.x, _size.y); _outline.draw(); _outline.setLine(0, 0, 0, _size.y); _outline.draw(); } Node::draw(); }
void RenderTopScreen() { // notes on the drawing process // GPU hangs if we attempt to draw an even number of arrays :/ which is why we draw the border 'twice' // textures used here are actually 512x256. TODO: investigate if GPU_SetTexture() really has the params in the wrong order // or if we did something wrong. //general setup GPU_SetViewport((u32*)osConvertVirtToPhys((u32)gpuDOut),(u32*)osConvertVirtToPhys((u32)gpuOut),0,0,240*2,400); GPU_DepthRange(-1.0f, 0.0f); GPU_SetFaceCulling(GPU_CULL_BACK_CCW); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00); GPU_SetDepthTest(false, GPU_ALWAYS, 0x1F); // ? GPUCMD_AddSingleParam(0x00010062, 0x00000000); //param always 0x0 according to code GPUCMD_AddSingleParam(0x000F0118, 0x00000000); //setup shader SHDR_UseProgram(shader, 0); //? GPUCMD_AddSingleParam(0x000F0100, 0x00E40100); GPUCMD_AddSingleParam(0x000F0101, 0x01010000); GPUCMD_AddSingleParam(0x000F0104, 0x00000010); //texturing stuff GPUCMD_AddSingleParam(0x0002006F, 0x00000100); GPUCMD_AddSingleParam(0x000F0080, 0x00011001); //enables/disables texturing //texenv GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, 0, 0), GPU_TEVSOURCES(GPU_CONSTANT, 0, 0), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_REPLACE, GPU_REPLACE, 0xFFFFFFFF); GPU_SetDummyTexEnv(1); GPU_SetDummyTexEnv(2); GPU_SetDummyTexEnv(3); GPU_SetDummyTexEnv(4); GPU_SetDummyTexEnv(5); //texturing stuff GPU_SetTexture((u32*)osConvertVirtToPhys((u32)BorderTex),256,512,0,GPU_RGBA8); // texture is actually 512x256 //setup matrices setUniformMatrix(0x24, mvMatrix); setUniformMatrix(0x20, projMatrix); // border GPU_SetAttributeBuffers(2, (u32*)osConvertVirtToPhys((u32)borderVertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 2, GPU_FLOAT), 0xFFC, 0x10, 1, (u32[]){0x00000000}, (u64[]){0x10}, (u8[]){2}); GPU_DrawArray(GPU_TRIANGLES, 3); GPU_DrawArray(GPU_TRIANGLES, 2*3); GPU_DepthRange(-1.0f, 0.0f); GPU_SetFaceCulling(GPU_CULL_BACK_CCW); GPU_SetStencilTest(false, GPU_ALWAYS, 0x00); GPU_SetDepthTest(false, GPU_ALWAYS, 0x1F); GPUCMD_AddSingleParam(0x00010062, 0x00000000); GPUCMD_AddSingleParam(0x000F0118, 0x00000000); GPUCMD_AddSingleParam(0x000F0100, 0x00000100); GPUCMD_AddSingleParam(0x000F0101, 0x01010000); GPUCMD_AddSingleParam(0x000F0104, 0x00000010); //texturing stuff GPUCMD_AddSingleParam(0x0002006F, 0x00000700); // enables/disables texcoord output GPUCMD_AddSingleParam(0x000F0080, 0x00011007); //enables/disables texturing // TEXTURE ENV STAGES // --- // blending operation: (Main.Color +- (Sub.Color * Main.Alpha)) * Sub.Alpha // Main.Alpha = 0/255 depending on color math // Sub.Alpha = 128/255 depending on color div2 // note: the main/sub intensities are halved to prevent overflow during the operations. // (each TEV stage output is clamped to [0,255]) // stage 4 makes up for this // --- // STAGE 1: Out.Color = Sub.Color * Main.Alpha, Out.Alpha = Sub.Alpha + (1-Main.Alpha) (cancel out div2 when color math doesn't happen) GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE1, GPU_TEXTURE0, 0), GPU_TEVSOURCES(GPU_TEXTURE1, GPU_TEXTURE0, 0), GPU_TEVOPERANDS(0,2,0), GPU_TEVOPERANDS(0,1,0), GPU_MODULATE, GPU_ADD, 0xFFFFFFFF); // STAGE 2: Out.Color = Main.Color +- Prev.Color, Out.Alpha = Prev.Alpha GPU_SetTexEnv(1, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PREVIOUS, 0), GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), (PPU_ColorMath & 0x80) ? GPU_SUBTRACT:GPU_ADD, GPU_REPLACE, 0xFFFFFFFF); // STAGE 3: Out.Color = Prev.Color * Prev.Alpha, Out.Alpha = Prev.Alpha GPU_SetTexEnv(2, GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0), GPU_TEVOPERANDS(0,2,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_REPLACE, 0xFFFFFFFF); // STAGE 4: Out.Color = Prev.Color + Prev.Color (doubling color intensity), Out.Alpha = Const.Alpha GPU_SetTexEnv(3, GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVSOURCES(GPU_CONSTANT, 0, 0), GPU_TEVOPERANDS(0,0,0), GPU_TEVOPERANDS(0,0,0), GPU_ADD, GPU_REPLACE, 0xFFFFFFFF); // STAGE 5: master brightness - Out.Color = Prev.Color * Bright.Alpha, Out.Alpha = Const.Alpha GPU_SetTexEnv(4, GPU_TEVSOURCES(GPU_PREVIOUS, GPU_TEXTURE2, 0), GPU_TEVSOURCES(GPU_CONSTANT, 0, 0), GPU_TEVOPERANDS(0,2,0), GPU_TEVOPERANDS(0,0,0), GPU_MODULATE, GPU_REPLACE, 0xFFFFFFFF); // STAGE 6: dummy GPU_SetDummyTexEnv(5); GPU_SetAttributeBuffers(3, (u32*)osConvertVirtToPhys((u32)screenVertices), GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 2, GPU_FLOAT)|GPU_ATTRIBFMT(2, 2, GPU_FLOAT), 0xFFC, 0x210, 1, (u32[]){0x00000000}, (u64[]){0x210}, (u8[]){3}); GPU_SetTexture((u32*)osConvertVirtToPhys((u32)MainScreenTex),256,512,0,GPU_RGBA8); GPU_SetTexture1((u32*)osConvertVirtToPhys((u32)SubScreenTex),256,512,0,GPU_RGBA8); GPU_SetTexture2((u32*)osConvertVirtToPhys((u32)BrightnessTex),256,8,0x200,GPU_A8); GPU_DrawArray(GPU_TRIANGLES, 2*3); }
void gpuUpdateState() { u32 dirtyUpdate = dirtyState; dirtyState = 0; if(dirtyUpdate & STATE_VIEWPORT) { GPU_SetViewport((u32*) osConvertVirtToPhys((u32) gpuDepthBuffer), (u32*) osConvertVirtToPhys((u32) gpuFrameBuffer), viewportX, viewportY, viewportWidth, viewportHeight); } if(dirtyUpdate & STATE_SCISSOR_TEST) { GPU_SetScissorTest((GPU_SCISSORMODE) scissorMode, scissorX, scissorY, scissorWidth, scissorHeight); } if(dirtyUpdate & STATE_DEPTH_MAP) { GPU_DepthMap(depthNear, depthFar); } if(dirtyUpdate & STATE_CULL) { GPU_SetFaceCulling((GPU_CULLMODE) cullMode); } if(dirtyUpdate & STATE_STENCIL_TEST) { GPU_SetStencilTest(stencilEnable, (GPU_TESTFUNC) stencilFunc, stencilRef, stencilMask, stencilReplace); GPU_SetStencilOp((GPU_STENCILOP) stencilFail, (GPU_STENCILOP) stencilZFail, (GPU_STENCILOP) stencilZPass); } if(dirtyUpdate & STATE_BLEND) { GPU_SetBlendingColor(blendRed, blendGreen, blendBlue, blendAlpha); GPU_SetAlphaBlending((GPU_BLENDEQUATION) blendColorEquation, (GPU_BLENDEQUATION) blendAlphaEquation, (GPU_BLENDFACTOR) blendColorSrc, (GPU_BLENDFACTOR) blendColorDst, (GPU_BLENDFACTOR) blendAlphaSrc, (GPU_BLENDFACTOR) blendAlphaDst); } if(dirtyUpdate & STATE_ALPHA_TEST) { GPU_SetAlphaTest(alphaEnable, (GPU_TESTFUNC) alphaFunc, alphaRef); } if(dirtyUpdate & STATE_DEPTH_TEST_AND_MASK) { GPU_SetDepthTestAndWriteMask(depthEnable, (GPU_TESTFUNC) depthFunc, (GPU_WRITEMASK) componentMask); } if((dirtyUpdate & STATE_ACTIVE_SHADER) && activeShader != NULL && activeShader->dvlb != NULL) { shaderProgramUse(&activeShader->program); } if((dirtyUpdate & STATE_TEX_ENV) && dirtyTexEnvs != 0) { u32 texEnvs = dirtyTexEnvs; dirtyTexEnvs = 0; for(u8 env = 0; env < TEX_ENV_COUNT; env++) { if(texEnvs & (1 << env)) { GPU_SetTexEnv(env, texEnv[env].rgbSources, texEnv[env].alphaSources, texEnv[env].rgbOperands, texEnv[env].alphaOperands, (GPU_COMBINEFUNC) texEnv[env].rgbCombine, (GPU_COMBINEFUNC) texEnv[env].alphaCombine, texEnv[env].constantColor); } } } if((dirtyUpdate & STATE_TEXTURES) && dirtyTextures != 0) { u32 textures = dirtyTextures; dirtyTextures = 0; for(u8 unit = 0; unit < TEX_UNIT_COUNT; unit++) { if(textures & (1 << unit)) { TexUnit texUnit = unit == 0 ? TEXUNIT0 : unit == 1 ? TEXUNIT1 : TEXUNIT2; TextureData* textureData = activeTextures[unit]; if(textureData != NULL && textureData->data != NULL) { GPU_SetTexture((GPU_TEXUNIT) texUnit, (u32*) osConvertVirtToPhys((u32) textureData->data), (u16) textureData->height, (u16) textureData->width, textureData->params, (GPU_TEXCOLOR) textureData->format); enabledTextures |= texUnit; } else { enabledTextures &= ~texUnit; } } } GPU_SetTextureEnable((GPU_TEXUNIT) enabledTextures); } }
int main(int argc, char **argv) { gfxInitDefault(); PrintConsole botScreen; PrintConsole topScreen; consoleInit(GFX_TOP, &topScreen); consoleInit(GFX_BOTTOM, &botScreen); consoleSelect(&topScreen); constexpr size_t NUM_SAMPLES = 160*200; u32 *audio_buffer = (u32*)linearAlloc(NUM_SAMPLES * sizeof(u32)); fillBuffer(audio_buffer, NUM_SAMPLES); AudioState state; { auto dspfirm = loadDspFirmFromFile(); if (!dspfirm) { printf("Couldn't load firmware\n"); goto end; } auto ret = audioInit(*dspfirm); if (!ret) { printf("Couldn't init audio\n"); goto end; } state = *ret; } state.waitForSync(); initSharedMem(state); state.write().dsp_configuration->mixer1_enabled_dirty = true; state.write().dsp_configuration->mixer1_enabled = true; //state.write().dsp_configuration->limiter_enabled = 1; state.notifyDsp(); printf("init\n"); state.waitForSync(); state.notifyDsp(); state.waitForSync(); for (auto& gain : state.write().source_configurations->config[0].gain) { for (auto& g : gain) { g = 0.0; } } state.write().source_configurations->config[0].gain[0][0] = 1.0; state.write().source_configurations->config[0].gain[1][0] = 1.0; state.write().source_configurations->config[0].gain[1][1] = 0.5; state.write().source_configurations->config[0].gain_1_dirty = true; state.notifyDsp(); state.waitForSync(); state.notifyDsp(); state.waitForSync(); state.notifyDsp(); { while (true) { state.waitForSync(); printf("sync = %i, play = %i, cbi = %i\n", state.read().source_statuses->status[0].sync, state.read().source_statuses->status[0].is_enabled, state.read().source_statuses->status[0].current_buffer_id); if (state.read().source_statuses->status[0].sync == 1) break; state.notifyDsp(); } printf("fi: %i\n", state.frame_id); u16 buffer_id = 0; //unsigned next_queue_position = 0; state.write().source_configurations->config[0].play_position = 0; state.write().source_configurations->config[0].physical_address = osConvertVirtToPhys(audio_buffer); state.write().source_configurations->config[0].length = NUM_SAMPLES; state.write().source_configurations->config[0].mono_or_stereo = DSP::HLE::SourceConfiguration::Configuration::MonoOrStereo::Stereo; state.write().source_configurations->config[0].format = DSP::HLE::SourceConfiguration::Configuration::Format::PCM16; state.write().source_configurations->config[0].fade_in = false; state.write().source_configurations->config[0].adpcm_dirty = false; state.write().source_configurations->config[0].is_looping = false; state.write().source_configurations->config[0].buffer_id = ++buffer_id; state.write().source_configurations->config[0].partial_reset_flag = true; state.write().source_configurations->config[0].play_position_dirty = true; state.write().source_configurations->config[0].embedded_buffer_dirty = true; state.write().source_configurations->config[0].enable = true; state.write().source_configurations->config[0].enable_dirty = true; state.notifyDsp(); bool continue_reading = true; for (size_t frame_count = 0; continue_reading; frame_count++) { state.waitForSync(); if (state.read().source_statuses->status[0].current_buffer_id) { printf("%i cbi = %i\n", frame_count, state.read().source_statuses->status[0].current_buffer_id); } for (size_t i = 0; i < 160; i++) { if (state.write().intermediate_mix_samples->mix1.pcm32[0][i]) { printf("[intermediate] frame=%i, sample=%i\n", frame_count, i); for (size_t j = 0; j < 20; j++) { printf("%08lx ", (u32)state.write().intermediate_mix_samples->mix1.pcm32[0][j]); } printf("\n"); break; } } for (size_t i = 0; i < 160 * 2; i++) { if (state.read().final_samples->pcm16[i]) { printf("[final] frame=%i, sample=%i\n", frame_count, i); for (size_t j = 0; j < 20; j++) { printf("%04x ", (u16)state.read().final_samples->pcm16[j]); } printf("\n"); continue_reading = false; break; } } state.notifyDsp(); } state.waitForSync(); state.write().source_configurations->config[0].sync = 2; state.write().source_configurations->config[0].sync_dirty = true; state.notifyDsp(); while (true) { state.waitForSync(); printf("sync = %i, play = %i\n", state.read().source_statuses->status[0].sync, state.read().source_statuses->status[0].is_enabled); if (state.read().source_statuses->status[0].sync == 2) break; state.notifyDsp(); } state.notifyDsp(); printf("Done!\n"); } end: audioExit(state); waitForKey(); gfxExit(); return 0; }
void mvd_video() { Result ret; size_t video_size, nalunitsize; u32 video_pos=0; u32 cur_nalunit_pos=0, prev_nalunit_pos=0; u32 nalcount=0; u8 *video; u32 flagval=0; FILE *f = NULL; u8* gfxtopadr=NULL; MVDSTD_Config config; u32 prefix_offset; u8 prefix[4] = {0x00, 0x00, 0x00, 0x01}; printf("Loading video...\n"); //This loads the entire video into memory, normally you'd use a library to stream it. f = fopen("romfs:/video.h264", "r"); if(f==NULL) { printf("Faile to open the video in romfs.\n"); return; } video = &inaddr[0x100000]; video_size = fread(video, 1, 0xF00000, f); fclose(f); if(video_size==0 || video_size>=0xF00000) { printf("Failed to read video / video is too large.\n"); return; } ret = mvdstdInit(MVDMODE_VIDEOPROCESSING, MVD_INPUT_H264, MVD_OUTPUT_BGR565, MVD_DEFAULT_WORKBUF_SIZE, NULL); printf("mvdstdInit(): 0x%08x\n", (unsigned int)ret); if(ret!=0)return; printf("Processing 0x%08x-byte video...\n", (unsigned int)video_size); mvdstdGenerateDefaultConfig(&config, 240, 400, 240, 400, NULL, (u32*)outaddr, (u32*)outaddr);//Normally you'd set the input dimensions here to dimensions loaded from the actual video. //Normally you'd use a library to load each NAL-unit, this example just parses the data manually. while(video_pos < video_size+1) { cur_nalunit_pos = video_pos; video_pos++; prefix_offset = 1; if(cur_nalunit_pos<video_size) { /* { if(memcmp(&video[cur_nalunit_pos], &prefix[1], 3)==0 && cur_nalunit_pos==0x2dd) { prefix_offset = 0; } } if(prefix_offset)*/ //else { if(memcmp(&video[cur_nalunit_pos], prefix, 4)) { continue; } else { video_pos++; } } } if(nalcount && prev_nalunit_pos!=cur_nalunit_pos) { nalunitsize = cur_nalunit_pos - prev_nalunit_pos - prefix_offset; if(nalunitsize > 0x100000) { printf("The NAL-unit at offset 0x%08x is too large.\n", (unsigned int)nalunitsize); break; } memcpy(inaddr, &video[prev_nalunit_pos+prefix_offset], nalunitsize); GSPGPU_FlushDataCache(inaddr, nalunitsize); MVDSTD_ProcessNALUnitOut tmpout;//Normally you don't really need to use this. //printf("Processing NAL-unit at offset 0x%08x size 0x%08x...\n", (unsigned int)prev_nalunit_pos, (unsigned int)nalunitsize); ret = mvdstdProcessVideoFrame(inaddr, nalunitsize, flagval, &tmpout); if(!MVD_CHECKNALUPROC_SUCCESS(ret)) { printf("mvdstdProcessVideoFrame() at NAL-unit offset 0x%08x size 0x%08x returned: 0x%08x. remaining_size=0x%08x.\n", (unsigned int)prev_nalunit_pos, (unsigned int)nalunitsize, (unsigned int)ret, (unsigned int)tmpout.remaining_size); break; } if(ret!=MVD_STATUS_PARAMSET && ret!=MVD_STATUS_INCOMPLETEPROCESSING) { gfxtopadr = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL); config.physaddr_outdata0 = osConvertVirtToPhys(gfxtopadr); //This sets the MVD output to the framebuffer directly. This is to avoid doing the video->framebuffer image rotation on the ARM11. //Normally you'd use a seperate MVD output buffer, then transfer that to the framebuffer(such as with GPU rendering). ret = mvdstdRenderVideoFrame(&config, true); if(ret!=MVD_STATUS_OK) { printf("mvdstdRenderVideoFrame() at NAL-unit offset 0x%08x returned: 0x%08x\n", (unsigned int)prev_nalunit_pos, (unsigned int)ret); break; } hidScanInput(); if(hidKeysDown() & KEY_B)break; //Enable/disable the flag passed to mvdstdProcessVideoFrame(). if(hidKeysDown() & KEY_DOWN) { flagval-= 0x1; printf("0x%08x\n", (unsigned int)flagval); } if(hidKeysDown() & KEY_UP) { flagval+= 0x1; printf("0x%08x\n", (unsigned int)flagval); } //gspWaitForVBlank();//Can't use this under this example without a major slowdown. This is due to this example not doing any buffering for the frames. gfxSwapBuffersGpu(); } } nalcount++; prev_nalunit_pos = cur_nalunit_pos; } mvdstdExit(); }
static u32* test_texture=NULL; static const u16 test_texture_w=256; static const u16 test_texture_h=256; extern const struct { u32 width; u32 height; u32 bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ u8 pixel_data[256 * 256 * 4 + 1]; } texture_data; void DrawSmallSquare() { //Setup the buffers data GPU_SetAttributeBuffers( 3, // number of attributes (u32 *) osConvertVirtToPhys((u32) test_data1), GPU_ATTRIBFMT(0, 3, GPU_FLOAT)|GPU_ATTRIBFMT(1, 4, GPU_UNSIGNED_BYTE)|GPU_ATTRIBFMT(2, 2, GPU_FLOAT), 0xFFF8,//Attribute mask, in our case 0b1110 since we use only the first one 0x210,//Attribute permutations (here it is the identity) 1, //number of buffers (u32[]) {0x0}, // buffer offsets (placeholders) (u64[]) {0x210}, // attribute permutations for each buffer (identity again) (u8[]) {3} // number of attributes for each buffer ); //Display the buffers data GPU_DrawArray(GPU_TRIANGLES, sizeof(test_mesh1) / sizeof(test_mesh1[0])); } void DrawBigSquare() { GPU_SetAttributeBuffers(
void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount, PrimitiveType type, const RenderStates& states) { // Nothing to draw? if (!vertices || (vertexCount == 0)) return; // Vertices allocated in the stack (common) can't be converted to physical address #ifndef EMULATION if (osConvertVirtToPhys((u32)vertices) == 0) { err() << "RenderTarget::draw() called with vertex array in inaccessible memory space." << std::endl; return; } #endif // GL_QUADS is unavailable on OpenGL ES if (type == Quads) { err() << "cpp3ds::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl; return; } #define GL_QUADS 0 if (activate(true)) { // First set the persistent OpenGL states if it's the very first call if (!m_cache.glStatesSet) resetGLStates(); // Check if the vertex count is low enough so that we can pre-transform them bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize); if (useVertexCache) { // Pre-transform the vertices and store them into the vertex cache for (unsigned int i = 0; i < vertexCount; ++i) { Vertex& vertex = m_cache.vertexCache[i]; vertex.position = states.transform * vertices[i].position; vertex.color = vertices[i].color; vertex.texCoords = vertices[i].texCoords; } // Since vertices are transformed, we must use an identity transform to render them if (!m_cache.useVertexCache) applyTransform(Transform::Identity); } else { applyTransform(states.transform); } // Apply the view if (m_cache.viewChanged) applyCurrentView(); // Apply the blend mode if (states.blendMode != m_cache.lastBlendMode) applyBlendMode(states.blendMode); // Apply the texture Uint64 textureId = states.texture ? states.texture->m_cacheId : 0; if (textureId != m_cache.lastTextureId) applyTexture(states.texture); // Apply the shader if (states.shader) applyShader(states.shader); // If we pre-transform the vertices, we must use our internal vertex cache if (useVertexCache) { // ... and if we already used it previously, we don't need to set the pointers again if (!m_cache.useVertexCache) vertices = m_cache.vertexCache; else vertices = NULL; } // Setup the pointers to the vertices' components if (vertices) { #ifdef EMULATION const char* data = reinterpret_cast<const char*>(vertices); glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0)); glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8)); // 8 = sizeof(Vector2f) glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12)); // 12 = 8 + sizeof(Color) #else // Temorary workaround until gl3ds can get VAO gl*Pointer functions working u32 bufferOffsets[] = {0}; u64 bufferPermutations[] = {0x210}; u8 bufferAttribCounts[] = {3}; GPU_SetAttributeBuffers( 3, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), GPU_ATTRIBFMT(0, 2, GPU_FLOAT) | GPU_ATTRIBFMT(1, 4, GPU_UNSIGNED_BYTE) | GPU_ATTRIBFMT(2, 2, GPU_FLOAT), 0xFF8, //0b1100 0x210, 1, //number of buffers bufferOffsets, bufferPermutations, bufferAttribCounts // number of attributes for each buffer ); #endif } // Find the OpenGL primitive type static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS }; GLenum mode = modes[type]; // Draw the primitives glCheck(glDrawArrays(mode, 0, vertexCount)); // Unbind the shader, if any if (states.shader) applyShader(NULL); // Update the cache m_cache.useVertexCache = useVertexCache; } }