#include "PreRender.h" #include "libultra/libultra.h" #include "gfxalloc.h" #include "sys_ucode.h" #include "libforest/gbi_extensions.h" extern void wallpaper_draw1(PreRenderBackground2DParams* bg2D, Gfx** gfxp) { Gfx* gfx; uObjBg* bg; int alphaCompare; Gfx* gfxTemp; int loadS2DEX2; loadS2DEX2 = (bg2D->flags & BG2D_FLAGS_LOAD_S2DEX2) != 0; alphaCompare = (bg2D->flags & BG2D_FLAGS_AC_THRESHOLD) ? G_AC_THRESHOLD : G_AC_NONE; gfxTemp = *gfxp; bg = (uObjBg*)gfxalloc(&gfxTemp, sizeof(uObjBg)); gfx = gfxTemp; bg->b.imageX = 0; bg->b.imageW = (bg2D->width * (1 << 2)) + 1; bg->b.frameX = bg2D->x * (1 << 2); bg->b.imageY = 0; bg->b.imageH = (bg2D->height * (1 << 2)) + 1; bg->b.frameY = bg2D->y * (1 << 2); bg->b.imagePtr = bg2D->timg; bg->b.imageLoad = G_BGLT_LOADTILE; bg->b.imageFmt = bg2D->fmt; bg->b.imageSiz = bg2D->siz; bg->b.imagePal = 0; bg->b.imageFlip = 0; if (loadS2DEX2 != 0) { gSPLoadUcode(gfx++, ucode_GetSpriteTextStart(), ucode_GetSpriteDataStart()); } if ((bg2D->fmt == G_IM_FMT_CI) && (bg2D->tlut != NULL)) { gDPLoadTLUT(gfx++, bg2D->tlutCount, 256, bg2D->tlut); } else { gDPPipeSync(gfx++); } if (bg2D->flags & BG2D_FLAGS_COPY) { bg->b.frameW = bg2D->width * (1 << 2); bg->b.frameH = bg2D->height * (1 << 2); if (!(bg2D->flags & BG2D_FLAGS_SAVE_OTHERMODE)) { gDPSetOtherMode(gfx++, bg2D->tt | G_CYC_COPY, alphaCompare); } gSPBgRectCopy(gfx++, bg); } else { bg->b.frameW = ((u32)bg2D->width << 2) * bg2D->xScale; bg->b.frameH = ((u32)bg2D->height << 2) * bg2D->yScale; bg->b.tmemW = (1 << 10) / bg2D->xScale; bg->b.tmemH = (1 << 10) / bg2D->yScale; bg->s.imageYorig = bg->b.imageY; if (!(bg2D->flags & BG2D_FLAGS_SAVE_OTHERMODE)) { gDPSetOtherMode(gfx++, bg2D->tt | G_AD_DISABLE | G_CD_DISABLE | G_TC_FILT, AA_EN | CVG_X_ALPHA | ALPHA_CVG_SEL | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA) | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA) | alphaCompare); } if (!(bg2D->flags & BG2D_FLAGS_SAVE_COMBINER)) { gDPSetCombineLERP(gfx++, 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1); } gSPObjRenderMode(gfx++, G_OBJRM_ANTIALIAS | G_OBJRM_BILERP); gSPBgRect1Cyc(gfx++, bg); } gDPPipeSync(gfx++); if (loadS2DEX2) { gSPLoadUcode(gfx++, ucode_GetPolyTextStart(), ucode_GetPolyDataStart()); } *gfxp = gfx; } extern void wallpaper_draw(Gfx** const gfxp, u16* const timg, u16* const tlut, const u16 width, const u16 height, const u8 fmt, const u8 siz, const u16 tt, const u16 tlutCount, f32 x, const f32 y, const f32 xScale, const f32 yScale, const u32 flags) { PreRenderBackground2DParams bg2D; bg2D.timg = timg; bg2D.tlut = tlut; bg2D.width = width; bg2D.height = height; bg2D.fmt = fmt; bg2D.siz = siz; bg2D.tt = tt; bg2D.tlutCount = tlutCount; bg2D.x = x; bg2D.y = y; bg2D.xScale = xScale; bg2D.yScale = yScale; bg2D.flags = flags; wallpaper_draw1(&bg2D, gfxp); } static Gfx* gfx_SetUpCFB(Gfx* gfx, void* ptr, u32 width, u32 heiht) { gDPPipeSync(gfx + 0); gDPSetColorImage(gfx + 1, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, ptr); gDPSetScissor(gfx + 2, G_SC_NON_INTERLACE, 0, 0, width, heiht); return gfx + 3; } extern void PreRender_setup_savebuf(PreRender* render, u32 width, u32 height, void* fbuf, void* zbuf, void* cvg) { render->width_bak = width; render->height_bak = height; render->framebuffer_bak = fbuf; render->cvg_bak = cvg; render->zbuffer_bak = zbuf; render->ulx_bak = 0; render->uly_bak = 0; render->lrx_bak = width - 1; render->lry_bak = height - 1; } extern void PreRender_init(PreRender* render) { bzero(render, sizeof(PreRender)); } extern void PreRender_setup_renderbuf(PreRender* render, u32 width, u32 height, void* fbuf, void* zbuf) { render->width = width; render->height = height; render->framebuffer = fbuf; render->zbuffer = zbuf; render->ulx = 0; render->uly = 0; render->lrx = width - 1; render->lry = height - 1; } extern void PreRender_cleanup(PreRender* render) { // nothing } static void PreRender_ShowCoveredge(Gfx** gfxp, u16 ulx, u16 uly, u16 lrx, u16 lry) { Gfx* gfx = *gfxp; gDPPipeSync(gfx++); gDPSetBlendColor(gfx++, 255, 255, 255, 8); gDPSetPrimDepth(gfx++, -1, -1); gDPSetOtherMode(gfx++, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | G_RM_VISCVG | G_RM_VISCVG2); gDPFillRectangle(gfx++, ulx, uly, lrx, lry); gDPPipeSync(gfx++); *gfxp = gfx; } extern void PreRender_CopyRGBC(PreRender* render, Gfx** gfxp, int width, int height) { Gfx* gfx = *gfxp; u32 remain; u32 term; u32 uls; u32 ult; u32 lrs; u32 lrt; u32 w; u32 h; u32 lrs_max; u32 lrt_max; if ((render->width_bak + width) <= 0 || (render->height_bak + height) <= 0) { return; } gDPPipeSync(gfx++); gfx = gfx_SetUpCFB(gfx, render->framebuffer, render->width, render->height); gDPSetOtherMode(gfx++, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | G_RM_OPA_SURF | G_RM_OPA_SURF2); gDPSetCombineLERP(gfx++, 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1); wallpaper_draw(&gfx, render->framebuffer_bak, 0, render->width_bak, render->height_bak, G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0, width, height, 1.0f, 1.0f, BG2D_FLAGS_SAVE_OTHERMODE | BG2D_FLAGS_SAVE_COMBINER | BG2D_FLAGS_LOAD_S2DEX2); gfx = gfx_SetUpCFB(gfx, render->framebuffer_bak, render->width_bak, render->height_bak); PreRender_ShowCoveredge(&gfx, 0, 0, render->width_bak, render->height_bak); gfx = gfx_SetUpCFB(gfx, render->framebuffer, render->width, render->height); gDPSetOtherMode(gfx++, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_2CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | AA_EN | IM_RD | CVG_DST_WRAP | ZMODE_OPA | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL | G_RM_PASS | GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_1)); gDPSetCombineLERP(gfx++, 0, 0, 0, 0, 1, 0, TEXEL0, ENVIRONMENT, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED); gDPSetEnvColor(gfx++, 255, 255, 255, 32); remain = (1 << 12) / (u32)((u16)render->width_bak << 1); term = render->width_bak; if (width < 0) { uls = -width; lrs = 0; } else { uls = 0; lrs = width; } if (height < 0) { ult = -height; lrt = 0; term = render->height_bak + height; } else { term = render->height_bak; lrt = height; ult = 0; } w = (render->width_bak + width); lrs_max = (u32)render->width_bak; while (term > 0) { if (remain > term) { remain = term; } lrt_max = ult + remain; if (lrt_max > render->width_bak) { lrt_max = render->width_bak; remain = render->width_bak - ult; } h = lrt + remain; gDPLoadTextureTile(gfx++, render->framebuffer_bak, G_IM_FMT_I, G_IM_SIZ_8b, (render->width_bak << 1), (render->height_bak << 1), (uls * 2), ult, ((lrs_max * 2) - 1), (lrt_max - 1), 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD); gSPTextureRectangle(gfx++, ((u32)lrs) * 4, ((u32)lrt) << G_TEXTURE_IMAGE_FRAC, ((u32)w) << G_TEXTURE_IMAGE_FRAC, ((u32)h) << G_TEXTURE_IMAGE_FRAC, G_TX_RENDERTILE, (uls * 2) << 5, ult << 5, (1 << 1) << 10, 1 << 10); term -= remain; ult += remain; lrt += remain; } gDPPipeSync(gfx++); *gfxp = gfx; }