/*---------------------------------------------------------------------------- gfxClearCfb Clear frame buffer/Z buffer ----------------------------------------------------------------------------*/ void gfxClearCfb(void) { /* clear Z buffer*/ gDPSetDepthImage(glist_ptr++, OS_K0_TO_PHYSICAL(zbuffer)); gDPPipeSync(glist_ptr++); gDPSetCycleType(glist_ptr++, G_CYC_FILL); gDPSetColorImage(glist_ptr++, G_IM_FMT_RGBA, G_IM_SIZ_16b,SCREEN_WD, OS_K0_TO_PHYSICAL(zbuffer)); gDPSetFillColor(glist_ptr++,(GPACK_ZDZ(G_MAXFBZ,0) << 16 | GPACK_ZDZ(G_MAXFBZ,0))); gDPFillRectangle(glist_ptr++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); gDPPipeSync(glist_ptr++); /* clear frame buffer */ gDPSetColorImage(glist_ptr++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WD, osVirtualToPhysical(cfb[gfx_cfbdrawbuffer])); gDPSetFillColor(glist_ptr++, (GPACK_RGBA5551(0, 0, 0, 1) << 16 | GPACK_RGBA5551(0, 0, 0, 1))); gDPFillRectangle(glist_ptr++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); gDPPipeSync(glist_ptr++); }
/* * gameloop -- main loop of game * Called by gameproc; runs in gameThread. * Parameter: rsp_static_addr, the R4300 address where the * rsp_static segment was loaded */ static void gameloop(char *rsp_static_addr) { int oddframe = 0; /* Odd or even rendered frame? Start with even. */ int firstframe = 1; /* First frame? */ dynamic_stuff *generate; /* Dynamic info we're generating now */ Gfx *glistp0; /* Start of this frame's dynamic display list */ Gfx *glistp; /* Current position in dynamic display list */ OSTask *gentask; /* Task we're generating */ float t; /* Weight of 1st set of morph verticies */ int dir; /* Direction in which we're morphing */ int pausecnt; /* Countdown for "stickiness" at morph extremes */ t = 0.0; dir = 1; pausecnt = 0; while (1) { /* Start task on RSP, built in previous iteration of loop. */ if (!firstframe) osSpTaskStart(gentask); /* * Set up pointers to dynamic stuff. We're always generating one set * of dynamic data and drawing another. */ generate = &(dynamic[(oddframe ? 0 : 1)]); /* glist portion of generated dynamic data */ glistp0 = &(generate->glist[0]); glistp = glistp0; /* This one will be incremented as list is built */ /* * Tell RSP where each segment is */ gSPSegment(glistp++, 0, 0x0); /* Physical address segment */ /* Static segment (mapping never changes) */ gSPSegment(glistp++, STATIC_SEG, OS_K0_TO_PHYSICAL(rsp_static_addr)); /* Dynamic segment (mapping changes every frame) */ gSPSegment(glistp++, DYNAMIC_SEG, OS_K0_TO_PHYSICAL(generate)); /* RSP and RDP setup, and screen clear */ gSPDisplayList(glistp++, rspinit_dl); gSPDisplayList(glistp++, rdpinit_dl); #ifdef FB32BIT gDPSetColorImage(glistp++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(oddframe ? cfb_A : cfb_B)); #else gDPSetColorImage(glistp++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WD, OS_K0_TO_PHYSICAL(oddframe ? cfb_A : cfb_B)); #endif gSPDisplayList(glistp++, scrnclr_dl); /* Must set color image again after zbuffer clear */ #ifdef FB32BIT gDPSetColorImage(glistp++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(oddframe ? cfb_A : cfb_B)); #else gDPSetColorImage(glistp++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WD, OS_K0_TO_PHYSICAL(oddframe ? cfb_A : cfb_B)); #endif /* Set Z-buffer */ gDPSetDepthImage(glistp++, OS_K0_TO_PHYSICAL(zbuffer)); /* * Matrix setup, and call display list that does real work */ drawframe(generate, &glistp, t); /* * Put an END on the top-level display list, and check that we * haven't overflowed the buffer. */ gDPFullSync(glistp++); /* Only need this if you want 'accurate' SP done? */ gSPEndDisplayList(glistp++); #ifdef DEBUG if ((int)(glistp - glistp0) > GLIST_SIZE) { /* does this check work?? */ osSyncPrintf("*** GLIST OVERFLOW ***\n"); /* Could quit here or something */ } #endif /* Update morph parameter t */ if (pausecnt == 0) { t += dir*(1.0/60.0); /* A full 60 frames to do the morph */ if (t < 0.0) {t = 0.0; dir = 1; pausecnt = 60;} if (t > 1.0) {t = 1.0; dir = -1; pausecnt = 60;} } else { pausecnt--; } /* * Build graphics task * Note that all addresses are KSEG0, even if used by the RSP. * Conversion is done by the task routines. */ gentask = &(task[oddframe ? 0 : 1]); gentask->t.type = M_GFXTASK; gentask->t.flags = 0x0; gentask->t.ucode_boot = (u64*) rspbootTextStart; gentask->t.ucode_boot_size = ((int)rspbootTextEnd - (int)rspbootTextStart); gentask->t.ucode = (u64*) gspF3DEX2_xbusTextStart; /* use XBUS */ gentask->t.ucode_data = (u64*) gspF3DEX2_xbusDataStart; gentask->t.ucode_size = 4096; gentask->t.ucode_data_size = 2048; gentask->t.dram_stack = (u64*) dram_stack; gentask->t.dram_stack_size = SP_DRAM_STACK_SIZE64; gentask->t.output_buff = (u64*) NULL; gentask->t.output_buff_size= (u64*) NULL; gentask->t.yield_data_ptr = (u64*) NULL; /* Graphics only - no yielding */ gentask->t.yield_data_size = 0x0; gentask->t.data_ptr = (u64*) glistp0; gentask->t.data_size = ((int) glistp - (int) glistp0); /* * Flush the whole cache. Should just do parts of it. */ osWritebackDCacheAll(); if (!firstframe) { /* Wait for task completion (message from RDP) */ osRecvMesg(&RDPDoneMessageQ, NULL, OS_MESG_BLOCK); /* * Specify frame buffer to be displayed starting at next retrace. * We display the one that we've just finished rendering. */ osViSwapBuffer(oddframe ? cfb_B : cfb_A); } /* * Wait for the retrace before rendering next frame * (otherwise we might overwrite the frame which is being displayed). * But first, make sure that the retrace queue is empty in case we * took too long to render the last frame. */ if (MQ_IS_FULL(&RetraceMessageQ)) osRecvMesg(&RetraceMessageQ, NULL, OS_MESG_NOBLOCK); osRecvMesg(&RetraceMessageQ, NULL, OS_MESG_BLOCK); /* Switch to our other set of variables */ oddframe ^= 1; /* No longer the first frame */ firstframe = 0; } /* while(1) */ } /* gameloop */
void RDP_SetZImg( u32 w0, u32 w1 ) { gDPSetDepthImage( w1 ); // img }