/* # ______ ____ ___ # | \/ ____| |___| # | | | \ | | #----------------------------------------------------------------------- # Copyright 2020, tyra - https://github.com/h4570/tyra # Licenced under Apache License 2.0 # Sandro Sobczyński */ #include "../include/modules/vif_sender.hpp" #include #include #include #include "../include/utils/math.hpp" #include "../include/utils/debug.hpp" const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also const u32 VU1_PACKAGES_PER_PACKET = 6; const u32 VU1_PACKET_SIZE = 128; // ---- // Constructors/Destructors // ---- VifSender::VifSender() { PRINT_LOG("Initializing VifSender"); PRINT_LOG("VifSender initialized!"); packets[0] = packet2_create_chain(VU1_PACKET_SIZE, P2_TYPE_NORMAL, true); packets[1] = packet2_create_chain(VU1_PACKET_SIZE, P2_TYPE_NORMAL, true); matricesPacket = packet2_create_chain(4, P2_TYPE_NORMAL, true); context = 0; setDoubleBuffer(); } VifSender::~VifSender() { packet2_free(packets[0]); packet2_free(packets[1]); packet2_free(matricesPacket); } // ---- // Methods // ---- void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation) { vec3ToNative(position, t_position, 1.0F); vec3ToNative(rotation, t_rotation, 1.0F); create_local_world(localWorld, position, rotation); create_local_screen(localScreen, localWorld, t_renderData.worldView->data, t_renderData.perspective->data); packet2_reset(matricesPacket, false); vu_add_unpack_data(matricesPacket, 0, &localScreen, 8, 0); vu_add_end_tag(matricesPacket); dma_channel_send_packet2(matricesPacket, DMA_CHANNEL_VIF1, 1); dma_channel_wait(DMA_CHANNEL_VIF1, 0); } void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer) { // we have to split 3D object into small parts, because of small memory of VU1 for (u32 i = 0; i < vertCount2;) { currPacket = packets[context]; packet2_reset(currPacket, false); for (u8 j = 0; j < VU1_PACKAGES_PER_PACKET; j++) // how many "packages" per one packet { if (i != 0) // we have to go back to avoid the visual artifacts i -= 3; const u32 endI = i + (VU1_PACKAGE_VERTS_PER_BUFF - 1) > vertCount2 ? vertCount2 : i + (VU1_PACKAGE_VERTS_PER_BUFF - 1); drawVertices(t_mesh, i, endI, vertices, coordinates, t_renderData->prim, textureBuffer); if (endI == vertCount2) // if there are no more vertices to draw, break { i = vertCount2; break; } i += (VU1_PACKAGE_VERTS_PER_BUFF - 1); i++; } vu_add_end_tag(currPacket); dma_channel_send_packet2(currPacket, DMA_CHANNEL_VIF1, 1); dma_channel_wait(DMA_CHANNEL_VIF1, 0); context = !context; } } void VifSender::setDoubleBuffer() { packet2_t *settings = packet2_create_chain(2, P2_TYPE_NORMAL, true); vu_add_double_buffer_settings(settings, 8, 496); vu_add_end_tag(settings); dma_channel_send_packet2(settings, DMA_CHANNEL_VIF1, 1); dma_channel_wait(DMA_CHANNEL_VIF1, 0); packet2_free(settings); } /** Draw using PATH1 */ void VifSender::drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer) { const u32 vertCount = t_end - t_start; vu_open_unpack(currPacket); // TODO get this via screensettings vu_unpack_add_float(currPacket, 2048.0F); // scale vu_unpack_add_float(currPacket, 2048.0F); // scale vu_unpack_add_float(currPacket, ((float)0xFFFFFF) / 32.0F); // scale vu_unpack_add_u32(currPacket, vertCount); // vertex count vu_unpack_add_set(currPacket, 1); vu_unpack_add_lod(currPacket, &t_mesh.lod); vu_unpack_add_texbuff_clut(currPacket, textureBuffer, &t_mesh.clut); vu_unpack_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0); for (u8 j = 0; j < 4; j++) vu_unpack_add_u32(currPacket, 128); // Clipping tests start // // const float minZ = 1; // // const float maxZ = 65535; // // const int iGuardDimXY = 2048; // // vu1.addFloat(1.0F); // f_TODO clipping maybe there is problem? // // vu1.addFloat(1.0F); // // vu1.addFloat(1.0F); // // vu1.addFloat(1.0F); // // float xClip = (float)2048.0f/(drawContext.GetFBWidth() * 0.5f * 2.0f); // // packet += Math::Max( xClip, 1.0f ); // // float yClip = (float)2048.0f/(drawContext.GetFBHeight() * 0.5f * 2.0f); // // packet += Math::Max( yClip, 1.0f ); // // float depthClip = 2048.0f / depthClipToGs; // // // F_FIXME: maybe these 2048's should be 2047.5s... // // depthClip *= 1.003f; // round up a bit for fp error (????) // // packet += depthClip; // // // enable/disable clipping // // packet += (drawContext.GetDoClipping()) ? 1 : 0; // u32 depthBits = 24; // or 28(fog) or 16 // float depthClipToGs = (float)((1 << depthBits) - 1) / 2.0f; // vu1.addFloat(2048.0f / (640.0F * 0.5f * 2.0f)); // vu1.addFloat(2048.0f / (480.0F * 0.5f * 2.0f)); // vu1.addFloat((2048.0f / depthClipToGs) * 1.003F); // // vu1.addFloat(2048.0F); // scale // // vu1.addFloat(2048.0F); // scale // // vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale // vu1.addFloat(0.0F); // // vu1.addFloat(0.5f * iGuardDimXY); // // vu1.addFloat(-0.5f * iGuardDimXY); // // vu1.addFloat(1.0F); // // vu1.addFloat(500.0F); // far vu_unpack_add_float(currPacket, 0.0F); vu_unpack_add_float(currPacket, 0.0F); vu_unpack_add_float(currPacket, 0.0F); vu_unpack_add_float(currPacket, 0.0F); //// Clipping tests end vu_close_unpack(currPacket); vu_add_unpack_data(currPacket, 0, t_vertices + t_start, 2 * vertCount, 1); vu_add_unpack_data(currPacket, 0, t_coordinates + t_start, 2 * vertCount, 1); vu_add_start_program(currPacket, 0); }