/*---------------------------------------------------------------------------------
nehe lesson 3 port to GX by WinterMute
---------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include <gccore.h>
#include <wiiuse/wpad.h>
#define DEFAULT_FIFO_SIZE (256*1024)
static void *frameBuffer[2] = { NULL, NULL};
GXRModeObj *rmode;
//---------------------------------------------------------------------------------
int main( int argc, char **argv ){
//---------------------------------------------------------------------------------
f32 yscale;
u32 xfbHeight;
Mtx view;
Mtx44 perspective;
Mtx model, modelview;
int scissor_mode = 0;
u32 fb = 0; // initial framebuffer index
GXColor background = {0, 0, 0, 0xff};
// init the vi.
VIDEO_Init();
WPAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
// allocate 2 framebuffers for double buffering
frameBuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
frameBuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
// setup the fifo and then init the flipper
void *gp_fifo = NULL;
gp_fifo = memalign(32,DEFAULT_FIFO_SIZE);
memset(gp_fifo,0,DEFAULT_FIFO_SIZE);
GX_Init(gp_fifo,DEFAULT_FIFO_SIZE);
// clears the bg to color and clears the z buffer
GX_SetCopyClear(background, 0x00ffffff);
// other gx setup
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
yscale = GX_GetYScaleFactor(rmode->efbHeight,rmode->xfbHeight);
xfbHeight = GX_SetDispCopyYScale(yscale);
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
GX_SetDispCopyDst(rmode->fbWidth,xfbHeight);
GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter);
GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE));
GX_SetCullMode(GX_CULL_NONE);
GX_CopyDisp(frameBuffer[fb],GX_TRUE);
GX_SetDispCopyGamma(GX_GM_1_0);
// setup the vertex descriptor
// tells the flipper to expect direct data
GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
// setup the vertex attribute table
// describes the data
// args: vat location 0-7, type of data, data format, size, scale
// so for ex. in the first call we are sending position data with
// 3 values X,Y,Z of size F32. scale sets the number of fractional
// bits for non float data.
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGB8, 0);
GX_SetNumChans(1);
GX_SetNumTexGens(0);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
// setup our camera at the origin
// looking down the -z axis with y up
guVector cam = {0.0F, 0.0F, 0.0F},
up = {0.0F, 1.0F, 0.0F},
look = {0.0F, 0.0F, -1.0F};
guLookAt(view, &cam, &up, &look);
// setup our projection matrix
// this creates a perspective matrix with a view angle of 90,
// and aspect ratio based on the display resolution
f32 w = rmode->viWidth;
f32 h = rmode->viHeight;
guPerspective(perspective, 45, (f32)w/h, 0.1F, 300.0F);
GX_LoadProjectionMtx(perspective, GX_PERSPECTIVE);
while(1) {
WPAD_ScanPads();
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0);
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_LEFT)
if (scissor_mode > 0)
scissor_mode -= 1;
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_RIGHT)
if (scissor_mode < 5)
scissor_mode += 1;
// do this before drawing
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
switch (scissor_mode)
{
case 0:
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
break;
case 1:
// "normal" scissor
GX_SetScissor(150, 150, rmode->fbWidth - 300, rmode->efbHeight - 300);
break;
case 2:
// left/right inverted
GX_SetScissor(rmode->fbWidth - 150, 150, -(rmode->fbWidth - 300), rmode->efbHeight - 300);
break;
case 3:
// top/bottom inverted
GX_SetScissor(150, rmode->efbHeight - 150, rmode->fbWidth - 300, -(rmode->efbHeight - 300));
break;
case 4:
// zero width
GX_SetScissor(150, 150, 0, rmode->efbHeight - 300);
break;
case 5:
// zero height
GX_SetScissor(150, 150, rmode->fbWidth - 300, 0);
break;
}
guMtxIdentity(model);
guMtxTransApply(model, model, -1.5f,0.0f,-6.0f);
guMtxConcat(view,model,modelview);
// load the modelview matrix into matrix memory
GX_LoadPosMtxImm(modelview, GX_PNMTX0);
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
GX_Position3f32( 0.0f, 1.0f, 0.0f); // Top
GX_Color3f32(1.0f,0.0f,0.0f); // Set The Color To Red
GX_Position3f32(-1.0f,-1.0f, 0.0f); // Bottom Left
GX_Color3f32(0.0f,1.0f,0.0f); // Set The Color To Green
GX_Position3f32( 1.0f,-1.0f, 0.0f); // Bottom Right
GX_Color3f32(0.0f,0.0f,1.0f); // Set The Color To Blue
GX_End();
guMtxTransApply(model, model, 3.0f,0.0f,0.0f);
guMtxConcat(view,model,modelview);
// load the modelview matrix into matrix memory
GX_LoadPosMtxImm(modelview, GX_PNMTX0);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4); // Draw A Quad
GX_Position3f32(-1.0f, 1.0f, 0.0f); // Top Left
GX_Color3f32(0.5f,0.5f,1.0f); // Set The Color To Blue
GX_Position3f32( 1.0f, 1.0f, 0.0f); // Top Right
GX_Color3f32(0.5f,0.5f,1.0f); // Set The Color To Blue
GX_Position3f32( 1.0f,-1.0f, 0.0f); // Bottom Right
GX_Color3f32(0.5f,0.5f,1.0f); // Set The Color To Blue
GX_Position3f32(-1.0f,-1.0f, 0.0f); // Bottom Left
GX_Color3f32(0.5f,0.5f,1.0f); // Set The Color To Blue
GX_End(); // Done Drawing The Quad
// do this stuff after drawing
GX_DrawDone();
fb ^= 1; // flip framebuffer
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
GX_SetColorUpdate(GX_TRUE);
GX_CopyDisp(frameBuffer[fb],GX_TRUE);
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
VIDEO_Flush();
VIDEO_WaitVSync();
}
return 0;
}