mirror of
https://github.com/thug1src/thug.git
synced 2024-11-30 12:06:44 +00:00
1705 lines
63 KiB
C++
1705 lines
63 KiB
C++
/*---------------------------------------------------------------------------*
|
||
Project: Dolphin hw Library
|
||
File: hwInit.c
|
||
|
||
Copyright 1998-2001 Nintendo. All rights reserved.
|
||
|
||
These coded instructions, statements, and computer programs contain
|
||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
||
Company Ltd., and are protected by Federal copyright law. They may
|
||
not be disclosed to third parties or copied or duplicated in any form,
|
||
in whole or in part, without the prior written consent of Nintendo.
|
||
|
||
$Log: /Dolphin/build/libraries/hw/src/hwInit.c $
|
||
|
||
52 8/24/01 6:30p Carl
|
||
Added more thorough output for GP hang diagnosis.
|
||
|
||
51 8/22/01 8:26p Carl
|
||
BypassWorkaround is now GPHangWorkaround.
|
||
Added code for GP hang diagnosis.
|
||
|
||
50 7/03/01 11:03a Hirose
|
||
Deleted obsolete fragment memory management system. Changed viewport
|
||
parameters to support Y-scaling modes rather than full-frame AA mode
|
||
which requires complicated settings in any case.
|
||
|
||
49 5/11/01 5:57p Hirose
|
||
changed default gamma correction back to 1.0.
|
||
|
||
48 5/10/01 7:06p Carl
|
||
Added comments concerning VI-related settings.
|
||
|
||
47 11/30/00 6:41p Tian
|
||
Fixed memory leak in hwReInit.
|
||
|
||
46 11/27/00 4:57p Carl
|
||
Added hwSetTevColorIn and hwSetTevOp.
|
||
|
||
45 10/28/00 5:57p Hirose
|
||
|
||
44 10/27/00 1:47a Hirose
|
||
Simplification / Clean up. Removed obsolete flags.
|
||
|
||
43 10/26/00 10:32a Tian
|
||
Added hwReInit and hwEnableBypassWorkaround. When used, the
|
||
standard hwBeforeRender and hwDoneRender functions will attempt to
|
||
repair the graphics pipe after a timeout.
|
||
|
||
42 8/27/00 5:45p Alligator
|
||
print warning messages through a callback function
|
||
|
||
41 8/18/00 2:44p Dante
|
||
Added !defined(WIN32) directive
|
||
|
||
40 8/08/00 4:21p Hirose
|
||
moved GXDrawDone call from hwSwapBuffers to hwDoneRender
|
||
|
||
39 8/02/00 3:06p Tian
|
||
Allocate framebuffers from beginning of heap to avoid VI bug (FB's must
|
||
be in lower 16MB).
|
||
|
||
38 7/21/00 1:48p Carl
|
||
Removed full-frame aa-specific code
|
||
(moved back to hw; see frb-aa-full.c).
|
||
Added hwSwapBuffers().
|
||
|
||
37 7/18/00 7:08p Hashida
|
||
Fixed a problem that MAC build failed.
|
||
|
||
36 7/17/00 11:59a Hashida
|
||
Added bad memory support.
|
||
|
||
35 7/07/00 7:09p Dante
|
||
PC Compatibility
|
||
|
||
34 6/26/00 5:43p Alligator
|
||
print stats before copy, but still include copy time, lose first
|
||
counter on first loop.
|
||
|
||
33 6/13/00 12:03p Alligator
|
||
use hwPrintf *after* sampling stat counters
|
||
|
||
32 6/12/00 1:46p Alligator
|
||
updated hw statistics to support new api
|
||
|
||
31 6/07/00 10:38a Howardc
|
||
add comment about gamma correction
|
||
|
||
30 6/05/00 1:55p Carl
|
||
Added hwDoneRenderBottom
|
||
|
||
29 5/24/00 3:18a Carl
|
||
OddField is gone; use hwDrawField instead.
|
||
|
||
28 5/24/00 1:02a Ryan
|
||
added default gamma setting of 1.7
|
||
|
||
27 5/19/00 1:09p Carl
|
||
GXSetVerifyLevel needed to be #ifdef _DEBUG
|
||
|
||
26 5/18/00 3:02a Alligator
|
||
add hwStat suff, set verify level to 0
|
||
|
||
25 5/02/00 4:05p Hirose
|
||
added function descriptions / deleted tabs
|
||
defined some global variables as static
|
||
attached prefix to exported global variables
|
||
|
||
24 4/07/00 5:57p Carl
|
||
Updated GXSetCopyFilter call.
|
||
|
||
23 3/24/00 6:48p Carl
|
||
Overscan adjust no longer changes predefined modes.
|
||
|
||
22 3/23/00 5:26p Carl
|
||
Added code to adjust for overscan.
|
||
|
||
21 3/23/00 1:22a Hirose
|
||
changed to call hwPadInit instead of PADInit
|
||
|
||
20 3/16/00 6:14p Danm
|
||
Cleaned up code per code review.
|
||
|
||
19 2/29/00 5:54p Ryan
|
||
update for dvddata folder rename
|
||
|
||
18 2/29/00 5:05p Danm
|
||
Select render mode based on TV format.
|
||
|
||
17 2/21/00 7:56p Tian
|
||
Changed order of PAD and VI init, since PAD requires that VI be
|
||
initialized
|
||
|
||
16 2/18/00 6:31p Carl
|
||
Changed __SINGLEFRAME #ifdefs to CSIM_OUTPUT
|
||
(__SINGLEFRAME is not applicable to library code, only test code).
|
||
Removed even/odd field #ifdefs; use OddField variable instead.
|
||
|
||
15 2/17/00 6:08p Carl
|
||
Removed clear from GXCopyDisp at end of single-frame test
|
||
|
||
14 2/17/00 6:03p Hashida
|
||
Changed the way to allocate frame buffer.
|
||
|
||
13 2/14/00 6:40p Danm
|
||
Enabled GXCopyDisp in hwDoneRender.
|
||
|
||
12 2/12/00 5:16p Alligator
|
||
Integrate ArtX source tree changes
|
||
|
||
11 2/11/00 3:23p Danm
|
||
Chaged dst stride on GXCopyDisp from pixel stride to byte stride.
|
||
|
||
10 2/08/00 1:50p Alligator
|
||
do copy in hwInit to clear the color and Z buffer prior to rendering
|
||
the first frame.
|
||
|
||
9 1/28/00 10:55p Hashida
|
||
Added VIFlush().
|
||
Changed to wait for two frames after tv mode is changed.
|
||
|
||
8 1/26/00 3:59p Hashida
|
||
Changed to use VIConfigure.
|
||
|
||
7 1/25/00 4:12p Danm
|
||
Changed default render mode for all platforms to GXNtsc480IntDf.
|
||
|
||
6 1/21/00 4:41p Alligator
|
||
added even/odd field select for __SINGLEFRAME field tests
|
||
|
||
5 1/19/00 3:43p Danm
|
||
Added GXRenderModeObj *hwGetRenderModeObj(void) function.
|
||
|
||
4 1/13/00 8:53p Danm
|
||
Added GXRenderModeObj * parameter to hwInit()
|
||
|
||
3 1/13/00 5:55p Alligator
|
||
integrate with ArtX GX library code
|
||
|
||
2 1/11/00 3:18p Danm
|
||
Reversed init of VI and GX for single field support
|
||
|
||
16 11/16/99 9:43a Hashida
|
||
Moved DVDInit before using arenaLo.
|
||
|
||
15 11/01/99 6:09p Tian
|
||
Framebuffers no longer allocated if generating CSIM output.
|
||
|
||
14 10/13/99 4:32p Alligator
|
||
change GXSetViewport, GXSetScissor to use xorig, yorig, wd, ht
|
||
|
||
13 10/07/99 12:14p Alligator
|
||
initialize rmode before using it in BeforeRender
|
||
|
||
12 10/06/99 10:38a Alligator
|
||
changed enums for compressed Z format
|
||
updated Init functions to make GX_ZC_LINEAR default
|
||
|
||
11 9/30/99 10:32p Yasu
|
||
Renamed and clean up functions and enums.
|
||
|
||
10 9/28/99 4:14p Hashida
|
||
Moved GXCopyDisp to GXDoneRender
|
||
|
||
9 9/23/99 3:23p Tian
|
||
New GXFifo/GXInit APIs, cleanup.
|
||
|
||
8 9/22/99 7:08p Yasu
|
||
Fixed paramter of GXSetViewPort
|
||
|
||
7 9/22/99 6:12p Yasu
|
||
Changed the parameters of GXSetDispCopySrc().
|
||
Fixed small bugs.
|
||
|
||
6 9/21/99 2:33p Alligator
|
||
add aa flag, if aa set 16b pix format
|
||
|
||
5 9/20/99 11:02a Ryan
|
||
|
||
4 9/17/99 5:24p Ryan
|
||
commented GXCopy temporarily
|
||
|
||
3 9/17/99 1:33p Ryan
|
||
update to include new VI API's
|
||
|
||
2 7/28/99 4:21p Ryan
|
||
Added DVDInit() and DVDSetRoot
|
||
|
||
1 7/20/99 6:06p Alligator
|
||
$NoKeywords: $
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
This hw library provides a common application
|
||
framework that is used in all the GX hws distributed
|
||
with the Dolphin SDK.
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
|
||
#include <dolphin.h>
|
||
#include "p_hw.h"
|
||
#include <charpipeline/GQRSetup.h>
|
||
#include "libsn.h"
|
||
#include "gfx\ngc\nx\nx_init.h"
|
||
#include "sys\ngc\p_aram.h"
|
||
#include "gfx/ngc/nx/mesh.h"
|
||
#include "sys\ngc\p_gx.h"
|
||
#include "sys\timer.h"
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
External functions
|
||
*---------------------------------------------------------------------------*/
|
||
//extern void hwUpdateStats ( GXBool inc );
|
||
//extern void hwPrintStats ( void );
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Global variables
|
||
*---------------------------------------------------------------------------*/
|
||
void* hwFrameBuffer1;
|
||
void* hwFrameBuffer2;
|
||
void* hwCurrentBuffer;
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Static variables
|
||
*---------------------------------------------------------------------------*/
|
||
static GXBool hwFirstFrame = GX_TRUE;
|
||
|
||
//static void* DefaultFifo;
|
||
static char DefaultFifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32);
|
||
static GXFifoObj* DefaultFifoObj;
|
||
|
||
GXRenderModeObj *rmode;
|
||
GXRenderModeObj rmodeobj;
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Automatic frame skipping to work around GP hang condition.
|
||
*---------------------------------------------------------------------------*/
|
||
static BOOL GPHangWorkaround = FALSE;
|
||
|
||
// used to count missed frames by VI retrace callback handler
|
||
static vu32 FrameCount;
|
||
static u32 FrameMissThreshold; // number of frames to be considered a timeout
|
||
|
||
// tokens are used instead of GXDrawDone
|
||
#define hw_START_FRAME_TOKEN 0xFEEB
|
||
#define hw_END_FRAME_TOKEN 0xB00B
|
||
|
||
// we need to create a thread to catch hangs at high watermark ("overflow")
|
||
static OSThread OVThread; // OS data for overflow thread
|
||
static u8 OVThreadStack[4096]; // Stack for overflow thread
|
||
|
||
static u32 fbSize;
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Fragmented memory systems
|
||
*---------------------------------------------------------------------------*/
|
||
typedef struct
|
||
{
|
||
void* start;
|
||
void* end;
|
||
} meminfo;
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Foward references
|
||
*---------------------------------------------------------------------------*/
|
||
static void __hwInitRenderMode ( GXRenderModeObj* mode );
|
||
static void __hwInitMem ( void );
|
||
static void __hwInitGX ( void );
|
||
static void __hwInitVI ( void );
|
||
//static void __hwInitForEmu ( void );
|
||
|
||
static void __NoHangRetraceCallback ( u32 count );
|
||
static void __NoHangDoneRender ( void );
|
||
|
||
static void __hwDiagnoseHang ( void );
|
||
static void* __hwOverflowThread ( void* param );
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Functions
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
/*===========================================================================*
|
||
|
||
|
||
Initialization
|
||
|
||
|
||
*===========================================================================*/
|
||
|
||
extern int resetDown;
|
||
|
||
void reset_callback( void )
|
||
{
|
||
resetDown = 1;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwInit
|
||
|
||
Description: This function initializes the components of
|
||
the operating system and its device drivers.
|
||
The mode parameter allows the application to
|
||
override the default render mode. It then allocates
|
||
all of main memory except the area for external
|
||
framebuffer into a heap than can be managed
|
||
with OSAlloc. This function initializes the video
|
||
controller to run at 640x480 interlaced display,
|
||
with 60Hz refresh (actually, 640x448; see below).
|
||
|
||
Arguments: mode : render mode
|
||
Default render mode will be used when
|
||
NULL is given as this argument.
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void hwInit( GXRenderModeObj *mode )
|
||
{
|
||
/*----------------------------------------------------------------*
|
||
* Initialize OS *
|
||
*----------------------------------------------------------------*/
|
||
OSInit();
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Initialize DVD *
|
||
* (need to initialize DVD BEFORE program uses *
|
||
* arena because DVDInit might change arena lo.) *
|
||
*----------------------------------------------------------------*/
|
||
DVDInit();
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Initialize VI *
|
||
*----------------------------------------------------------------*/
|
||
VIInit();
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Initialize game PAD (PADInit is called by hwPadInit) *
|
||
*----------------------------------------------------------------*/
|
||
hwPadInit();
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Set up rendering mode *
|
||
* (which reflects the GX/VI configurations and XFB size below) *
|
||
*----------------------------------------------------------------*/
|
||
__hwInitRenderMode(mode);
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Initialize memory configuration (framebuffers / heap) *
|
||
*----------------------------------------------------------------*/
|
||
__hwInitMem();
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Configure VI by given render mode *
|
||
*----------------------------------------------------------------*/
|
||
VIConfigure(rmode);
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Initialize Graphics *
|
||
*----------------------------------------------------------------*/
|
||
// Alloc default 256K fifo
|
||
// DefaultFifo = OSAlloc(DEFAULT_FIFO_SIZE);
|
||
DefaultFifoObj = GX::Init(DefaultFifo, DEFAULT_FIFO_SIZE);
|
||
|
||
// Configure GX
|
||
__hwInitGX();
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Emulator only initialization portion *
|
||
*----------------------------------------------------------------*/
|
||
#ifdef EMU
|
||
__hwInitForEmu();
|
||
#endif
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Start up VI *
|
||
*----------------------------------------------------------------*/
|
||
__hwInitVI();
|
||
|
||
// Creates a new thread in order to diagnose hangs during high watermark.
|
||
// The thread is suspended by default.
|
||
OSCreateThread(
|
||
&OVThread, // ptr to the thread obj to init
|
||
__hwOverflowThread, // ptr to the start routine
|
||
0, // param passed to start routine
|
||
OVThreadStack+sizeof(OVThreadStack),// initial stack address
|
||
sizeof(OVThreadStack),
|
||
31, // scheduling priority (low)
|
||
OS_THREAD_ATTR_DETACH); // detached by default
|
||
|
||
OSResumeThread(&OVThread); // Allow the thread to run
|
||
|
||
GQRSetup6( GQR_SCALE_64, // Pos
|
||
GQR_TYPE_S16,
|
||
GQR_SCALE_64,
|
||
GQR_TYPE_S16 );
|
||
GQRSetup7( 14, // Normal
|
||
GQR_TYPE_S16,
|
||
14,
|
||
GQR_TYPE_S16 );
|
||
|
||
// hwEnableGPHangWorkaround( 60 );
|
||
|
||
|
||
// static unsigned long profdata[2048]; // long aligned,
|
||
// // 4K to 64K bytes
|
||
// if(snProfInit(_4KHZ, profdata, sizeof(profdata)) != 0)
|
||
// printf("Profiler init failed\n"); // see SN_PRF<52> in LIBSN.H
|
||
// // rest of user code follows on from here...
|
||
|
||
OSSetResetCallback( reset_callback );
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __hwInitRenderMode
|
||
|
||
Description: This function sets up rendering mode which configures
|
||
GX and VI. If mode == NULL, this function use a default
|
||
rendering mode according to the TV format.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void __hwInitRenderMode( GXRenderModeObj* mode )
|
||
{
|
||
// If an application specific render mode is provided,
|
||
// override the default render mode
|
||
if (mode != NULL)
|
||
{
|
||
rmode = mode;
|
||
}
|
||
else
|
||
{
|
||
rmode = &GXNtsc480IntDf;
|
||
|
||
// Trim off from top & bottom 16 scanlines (which will be overscanned).
|
||
// So almost all hws actually render only 448 lines (in NTSC case.)
|
||
// Since this setting is just for SDK hws, you can specify this
|
||
// in order to match your application requirements.
|
||
GX::AdjustForOverscan(rmode, &rmodeobj, 0, 16);
|
||
|
||
rmode = &rmodeobj;
|
||
|
||
OSReport( "TV format: %d\n", VIGetTvFormat() );
|
||
|
||
switch (VIGetTvFormat())
|
||
{
|
||
case VI_NTSC:
|
||
if ( NxNgc::EngineGlobals.use_480p )
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_NTSC_PROG;
|
||
rmode->xFBmode = VI_XFBMODE_SF;
|
||
}
|
||
break;
|
||
case VI_PAL:
|
||
case VI_EURGB60:
|
||
case VI_DEBUG_PAL:
|
||
if ( rmode->viTVmode == VI_TVMODE_NTSC_INT )
|
||
{
|
||
if ( NxNgc::EngineGlobals.use_60hz )
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_EURGB60_INT;
|
||
}
|
||
else
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_PAL_INT;
|
||
rmode->viYOrigin = 23;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( NxNgc::EngineGlobals.use_60hz )
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_EURGB60_DS;
|
||
}
|
||
else
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_PAL_DS;
|
||
rmode->viYOrigin = 23;
|
||
}
|
||
}
|
||
if ( NxNgc::EngineGlobals.use_60hz )
|
||
{
|
||
rmode->xfbHeight = 448;
|
||
}
|
||
else
|
||
{
|
||
rmode->xfbHeight = ( rmode->xfbHeight * 528 ) / 448;
|
||
rmode->viHeight = 528;
|
||
}
|
||
break;
|
||
case VI_MPAL:
|
||
rmode = &GXMpal480IntDf;
|
||
break;
|
||
default:
|
||
//OSHalt("hwInit: invalid TV format\n");
|
||
break;
|
||
}
|
||
|
||
// Nintendo's recommended settings.
|
||
rmode->viWidth = 650;
|
||
rmode->viXOrigin = 35;
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __hwInitMem
|
||
|
||
Description: This function allocates external framebuffers from
|
||
arena and sets up a heap
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void __hwInitMem( void )
|
||
{
|
||
void* arenaLo;
|
||
void* arenaHi;
|
||
|
||
arenaLo = OSGetArenaLo();
|
||
arenaHi = OSGetArenaHi();
|
||
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Allocate external framebuffers *
|
||
*----------------------------------------------------------------*/
|
||
|
||
// In HW1, we should allocate the buffers at the beginning of arena (<16MB)
|
||
// Need to do this before OSInitAlloc is called.
|
||
fbSize = VIPadFrameBufferWidth(rmode->fbWidth) * rmode->xfbHeight *
|
||
(u32)VI_DISPLAY_PIX_SZ;
|
||
hwFrameBuffer1 = (void*)OSRoundUp32B((u32)arenaLo);
|
||
hwFrameBuffer2 = (void*)OSRoundUp32B((u32)hwFrameBuffer1 + fbSize);
|
||
hwCurrentBuffer = hwFrameBuffer2;
|
||
|
||
arenaLo = (void*)OSRoundUp32B((u32)hwFrameBuffer2 + fbSize);
|
||
OSSetArenaLo(arenaLo);
|
||
|
||
// /*----------------------------------------------------------------*
|
||
// * Create a heap *
|
||
// *----------------------------------------------------------------*/
|
||
//
|
||
// // OSInitAlloc should only ever be invoked once.
|
||
// arenaLo = OSGetArenaLo();
|
||
// arenaHi = OSGetArenaHi();
|
||
// arenaLo = OSInitAlloc(arenaLo, arenaHi, 1); // 1 heap
|
||
// OSSetArenaLo(arenaLo);
|
||
//
|
||
// // Ensure boundaries are 32B aligned
|
||
// arenaLo = (void*)OSRoundUp32B(arenaLo);
|
||
// arenaHi = (void*)OSRoundDown32B(arenaHi);
|
||
//
|
||
// // The boundaries given to OSCreateHeap should be 32B aligned
|
||
// OSSetCurrentHeap(OSCreateHeap(arenaLo, arenaHi));
|
||
// // From here on out, OSAlloc and OSFree behave like malloc and free
|
||
// // respectively
|
||
// OSSetArenaLo(arenaLo=arenaHi);
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Allocate ARAM buffers *
|
||
*----------------------------------------------------------------*/
|
||
|
||
ARInit(NULL, 0);
|
||
ARQInit();
|
||
AIInit( NULL );
|
||
AXInit();
|
||
AXSetMode( AX_MODE_DPL2 );
|
||
AXSetCompressor( AX_COMPRESSOR_OFF );
|
||
NsARAM::init();
|
||
|
||
// Allocate the 1st 1024 bytes for our own use.
|
||
NxNgc::EngineGlobals.aram_zero = NsARAM::alloc( aram_zero_size );
|
||
|
||
// Allocate 2.8mb for the DSP data.
|
||
NxNgc::EngineGlobals.aram_dsp = NsARAM::alloc( aram_dsp_size );
|
||
|
||
// Allocate 32k each for the 3 streams.
|
||
NxNgc::EngineGlobals.aram_stream0 = NsARAM::alloc( aram_stream0_size );
|
||
NxNgc::EngineGlobals.aram_stream1 = NsARAM::alloc( aram_stream1_size );
|
||
NxNgc::EngineGlobals.aram_stream2 = NsARAM::alloc( aram_stream2_size );
|
||
|
||
// Allocate 32k for the music buffer.
|
||
NxNgc::EngineGlobals.aram_music = NsARAM::alloc( aram_music_size );
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __hwInitGX
|
||
|
||
Description: This function performs GX configuration by using
|
||
current rendering mode
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void __hwInitGX( void )
|
||
{
|
||
/*----------------------------------------------------------------*
|
||
* GX configuration by a render mode obj *
|
||
*----------------------------------------------------------------*/
|
||
|
||
// These are all necessary function calls to take a render mode
|
||
// object and set up the relevant GX configuration.
|
||
|
||
GX::SetViewport(0.0F, 0.0F, (f32)rmode->fbWidth, (f32)rmode->efbHeight,
|
||
0.0F, 1.0F);
|
||
GX::SetScissor(0, 0, (u32)rmode->fbWidth, (u32)rmode->efbHeight);
|
||
GX::SetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight);
|
||
GX::SetDispCopyDst(rmode->fbWidth, rmode->xfbHeight);
|
||
|
||
GX::SetDispCopyYScale((f32)(rmode->xfbHeight) / (f32)(rmode->efbHeight));
|
||
|
||
GX::SetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter);
|
||
|
||
// Note that following is an appropriate setting for full-frame AA mode.
|
||
// You should use "xfbHeight" instead of "efbHeight" to specify actual
|
||
// view size. Since this library doesn't support such special case, please
|
||
// call these in each application to override the normal setting.
|
||
#if 0
|
||
GX::SetViewport(0.0F, 0.0F, (f32)rmode->fbWidth, (f32)rmode->xfbHeight,
|
||
0.0F, 1.0F);
|
||
GX::SetDispCopyYScale(1.0F);
|
||
#endif
|
||
|
||
if (rmode->aa)
|
||
{
|
||
GX::SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
|
||
}
|
||
else
|
||
{
|
||
GX::SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||
// GX::SetPixelFmt(/*GX_PF_RGB8_Z24*/GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
|
||
// GXSetPixelFmt(/*GX_PF_RGB8_Z24*/GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------*
|
||
* Miscellaneous GX initialization for hws *
|
||
* (Since these are not actually necessary for all applications, *
|
||
* you may remove them if you feel they are unnecessary.) *
|
||
*----------------------------------------------------------------*/
|
||
|
||
// Clear embedded framebuffer for the first frame
|
||
GX::CopyDisp(hwCurrentBuffer, GX_TRUE);
|
||
|
||
// Verify (warning) messages are turned off by default
|
||
#ifdef _DEBUG
|
||
// GXSetVerifyLevel(GX_WARN_NONE);
|
||
GXSetVerifyLevel(GX_WARN_NONE);
|
||
#endif
|
||
|
||
// Gamma correction
|
||
//
|
||
// You may want to use 1.7 or 2.2 if all artwork made on PCs
|
||
// become darker. However, recommended setting is 1.0.
|
||
GX::SetDispCopyGamma(GX_GM_1_0);
|
||
|
||
// 2D Primitives.
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
|
||
|
||
|
||
|
||
//#ifdef SHORT_VERT
|
||
// // Environment geometry. 1=1.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
//
|
||
// // Environment geometry. 1=2.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_S16, 1 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
//
|
||
// // Environment geometry. 1=4.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_S16, 2 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
//
|
||
// // Environment geometry. 1=8.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_S16, 3 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
//
|
||
// // Environment geometry. 1=16.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_S16, 4 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
//
|
||
// // Environment geometry. 1=32.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_S16, 5 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
//#else
|
||
// // Environment/skinned geometry. 1=64.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
//#endif // SHORT_VERT
|
||
// // Environment/skinned geometry. 1=64.
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
// GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 );
|
||
|
||
// Environment.
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX1, GX_TEX_ST, GX_S16, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX2, GX_TEX_ST, GX_S16, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX3, GX_TEX_ST, GX_S16, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX4, GX_TEX_ST, GX_S16, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX5, GX_TEX_ST, GX_S16, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX6, GX_TEX_ST, GX_S16, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_TEX7, GX_TEX_ST, GX_S16, 0 );
|
||
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_S16, 2 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX1, GX_TEX_ST, GX_S16, 2 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX2, GX_TEX_ST, GX_S16, 2 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX3, GX_TEX_ST, GX_S16, 2 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX4, GX_TEX_ST, GX_S16, 2 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX5, GX_TEX_ST, GX_S16, 2 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX6, GX_TEX_ST, GX_S16, 2 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_TEX7, GX_TEX_ST, GX_S16, 2 );
|
||
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX0, GX_TEX_ST, GX_S16, 4 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX1, GX_TEX_ST, GX_S16, 4 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX2, GX_TEX_ST, GX_S16, 4 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX3, GX_TEX_ST, GX_S16, 4 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX4, GX_TEX_ST, GX_S16, 4 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX5, GX_TEX_ST, GX_S16, 4 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX6, GX_TEX_ST, GX_S16, 4 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_TEX7, GX_TEX_ST, GX_S16, 4 );
|
||
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX1, GX_TEX_ST, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX2, GX_TEX_ST, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX3, GX_TEX_ST, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX4, GX_TEX_ST, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX5, GX_TEX_ST, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX6, GX_TEX_ST, GX_S16, 6 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX7, GX_TEX_ST, GX_S16, 6 );
|
||
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_S16, 8 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX1, GX_TEX_ST, GX_S16, 8 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX2, GX_TEX_ST, GX_S16, 8 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX3, GX_TEX_ST, GX_S16, 8 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX4, GX_TEX_ST, GX_S16, 8 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX5, GX_TEX_ST, GX_S16, 8 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX6, GX_TEX_ST, GX_S16, 8 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_TEX7, GX_TEX_ST, GX_S16, 8 );
|
||
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST, GX_S16, 10 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX1, GX_TEX_ST, GX_S16, 10 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX2, GX_TEX_ST, GX_S16, 10 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX3, GX_TEX_ST, GX_S16, 10 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX4, GX_TEX_ST, GX_S16, 10 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX5, GX_TEX_ST, GX_S16, 10 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX6, GX_TEX_ST, GX_S16, 10 );
|
||
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_TEX7, GX_TEX_ST, GX_S16, 10 );
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __hwInitVI
|
||
|
||
Description: This function performs VI start up settings that are
|
||
necessary at the beginning of each hw
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void __hwInitVI( void )
|
||
{
|
||
u32 nin;
|
||
|
||
// Double-buffering initialization
|
||
VISetNextFrameBuffer(hwFrameBuffer1);
|
||
hwCurrentBuffer = hwFrameBuffer2;
|
||
|
||
// Tell VI device driver to write the current VI settings so far
|
||
VIFlush();
|
||
|
||
// Wait for retrace to start first frame
|
||
VIWaitForRetrace();
|
||
|
||
// Because of hardware restriction, we need to wait one more
|
||
// field to make sure mode is safely changed when we change
|
||
// INT->DS or DS->INT. (VIInit() sets INT mode as a default)
|
||
nin = (u32)rmode->viTVmode & 1;
|
||
if (nin)
|
||
VIWaitForRetrace();
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __hwInitForEmu
|
||
|
||
Description: This function performs emulator only portion of
|
||
initialization.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
//static void __hwInitForEmu( void )
|
||
//{
|
||
// // Set up DVDRoot
|
||
//#ifdef MACOS
|
||
// DVDSetRoot("DOLPHIN/dvddata/");
|
||
//#endif
|
||
//
|
||
//#ifdef WIN32
|
||
// unsigned char path[270] = "";
|
||
// strcat(path, installPath);
|
||
// strcat(path, "/dvddata");
|
||
// DVDSetRoot(path);
|
||
//#endif
|
||
//}
|
||
|
||
|
||
|
||
/*===========================================================================*
|
||
|
||
|
||
Basic hw framework control functions
|
||
|
||
|
||
*===========================================================================*/
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwBeforeRender
|
||
|
||
Description: This function sets up the viewport to render the
|
||
appropriate field if field rendering is enabled.
|
||
Field rendering is a property of the render mode.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void hwBeforeRender( void )
|
||
{
|
||
|
||
#ifndef EMU
|
||
if (GPHangWorkaround)
|
||
{
|
||
// This will overwrite the end frame token from the previous frame.
|
||
GX::SetDrawSync( hw_START_FRAME_TOKEN);
|
||
|
||
// Reset the counters for post-hang diagnosis.
|
||
GX::ClearGPMetric();
|
||
}
|
||
#endif // !EMU
|
||
|
||
|
||
// Set up viewport (This is inappropriate for full-frame AA.)
|
||
if (rmode->field_rendering)
|
||
{
|
||
GX::SetViewportJitter(
|
||
0.0F, 0.0F, (float)rmode->fbWidth, (float)rmode->efbHeight,
|
||
0.0F, 1.0F, VIGetNextField());
|
||
}
|
||
else
|
||
{
|
||
GX::SetViewport(
|
||
0.0F, 0.0F, (float)rmode->fbWidth, (float)rmode->efbHeight,
|
||
0.0F, 1.0F);
|
||
}
|
||
|
||
// Invalidate vertex cache in GP
|
||
GX::InvalidateVtxCache();
|
||
|
||
#ifndef EMU
|
||
// Invalidate texture cache in GP
|
||
GX::InvalidateTexAll();
|
||
#endif // !EMU
|
||
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwDoneRender
|
||
|
||
Description: This function copies the embedded frame buffer (EFB)
|
||
to the external frame buffer (XFB) via GXCopyDisp,
|
||
and then calls hwSwapBuffers.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void hwDoneRender( bool clear )
|
||
{
|
||
// GP hang workaround version (Turned off by default)
|
||
if (GPHangWorkaround)
|
||
{
|
||
// ASSERTMSG(!hwStatEnable,
|
||
// "DEMOStats and GP hang diagnosis are mutually exclusive");
|
||
__NoHangDoneRender();
|
||
return;
|
||
}
|
||
|
||
// Statistics support (Turned off by default)
|
||
// if (hwStatEnable)
|
||
// {
|
||
// GXDrawDone(); // make sure data through pipe
|
||
// hwUpdateStats(GX_TRUE); // sample counters here
|
||
// hwPrintStats(); // don't include time to print stats
|
||
// GXDrawDone(); // make sure data through pipe
|
||
// hwUpdateStats(GX_FALSE); // reset counters here, include copy time
|
||
// }
|
||
|
||
// Set Z/Color update to make sure eFB will be cleared at GXCopyDisp.
|
||
// (If you want to control these modes by yourself in your application,
|
||
// please comment out this part.)
|
||
GX::SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
||
|
||
// Issue display copy command
|
||
GX::CopyDisp( hwCurrentBuffer, ( clear ) ? GX_TRUE : GX_FALSE );
|
||
|
||
// Wait until everything is drawn and copied into XFB.
|
||
GX::DrawDone();
|
||
|
||
// Set the next frame buffer
|
||
hwSwapBuffers();
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: RADDEMOLockBackBuffer
|
||
|
||
Description: This function returns the back buffer info, so that you
|
||
can write right into it.
|
||
*---------------------------------------------------------------------------*/
|
||
int hwLockBackBuffer( void ** buf_addr, unsigned int * width, unsigned int * height )
|
||
{
|
||
if ( buf_addr )
|
||
*buf_addr = hwCurrentBuffer;
|
||
if ( width )
|
||
*width = rmode->fbWidth;
|
||
if ( height )
|
||
*height = rmode->xfbHeight;
|
||
return( 1 );
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: RADDEMOUnlockBackBuffer
|
||
|
||
Description: This function returns the back buffer info, so that you
|
||
can write right into it.
|
||
*---------------------------------------------------------------------------*/
|
||
void hwUnlockBackBuffer( int updated )
|
||
{
|
||
if ( updated )
|
||
{
|
||
DCStoreRange( hwCurrentBuffer, fbSize );
|
||
}
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwSwapBuffers
|
||
|
||
Description: This function finishes copying via GXDrawDone, sets
|
||
the next video frame buffer, waits for vertical
|
||
retrace, and swaps internal rendering buffers.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void hwSwapBuffers( void )
|
||
{
|
||
// Display the buffer which was just filled by GXCopyDisplay
|
||
VISetNextFrameBuffer(hwCurrentBuffer);
|
||
|
||
// If this is the first frame, turn off VIBlack
|
||
if(hwFirstFrame)
|
||
{
|
||
VISetBlack(FALSE);
|
||
hwFirstFrame = GX_FALSE;
|
||
}
|
||
|
||
// Tell VI device driver to write the current VI settings so far
|
||
VIFlush();
|
||
|
||
// Wait for vertical retrace.
|
||
// VIWaitForRetrace();
|
||
Tmr::VSync1();
|
||
|
||
// Swap buffers
|
||
if(hwCurrentBuffer == hwFrameBuffer1)
|
||
hwCurrentBuffer = hwFrameBuffer2;
|
||
else
|
||
hwCurrentBuffer = hwFrameBuffer1;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwSetTevColorIn
|
||
|
||
Description: This function is a Rev A compatible version of
|
||
GXSetTevColorIn. It will set the swap mode if
|
||
one of TEXC/TEXRRR/TEXGGG/TEXBBB is selected.
|
||
|
||
It doesn't error check for multiple swaps, however.
|
||
|
||
Note that it is available for Rev A or Rev B.
|
||
For Rev A, it is defined as an inline in hw.h.
|
||
|
||
Arguments: Same as GXSetTevColorIn
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
#if ( GX_REV > 1 )
|
||
void hwSetTevColorIn(GXTevStageID stage,
|
||
GXTevColorArg a, GXTevColorArg b,
|
||
GXTevColorArg c, GXTevColorArg d )
|
||
{
|
||
// u32 swap = 0;
|
||
//
|
||
// if (a == GX_CC_TEXC)
|
||
// { swap = GX_CC_TEXRRR - 1; }
|
||
// else if (a >= GX_CC_TEXRRR)
|
||
// { swap = a; a = GX_CC_TEXC; }
|
||
//
|
||
// if (b == GX_CC_TEXC)
|
||
// { swap = GX_CC_TEXRRR - 1; }
|
||
// else if (b >= GX_CC_TEXRRR)
|
||
// { swap = b; b = GX_CC_TEXC; }
|
||
//
|
||
// if (c == GX_CC_TEXC)
|
||
// { swap = GX_CC_TEXRRR - 1; }
|
||
// else if (c >= GX_CC_TEXRRR)
|
||
// { swap = c; c = GX_CC_TEXC; }
|
||
//
|
||
// if (d == GX_CC_TEXC)
|
||
// { swap = GX_CC_TEXRRR - 1; }
|
||
// else if (d >= GX_CC_TEXRRR)
|
||
// { swap = d; d = GX_CC_TEXC; }
|
||
//
|
||
// GXSetTevColorIn(stage, a, b, c, d);
|
||
//
|
||
// if (swap > 0)
|
||
// GXSetTevSwapMode(stage, GX_TEV_SWAP0,
|
||
// (GXTevSwapSel)(swap - GX_CC_TEXRRR + 1));
|
||
}
|
||
#endif
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwSetTevOp
|
||
|
||
Description: This function is a Rev-A compatible version of
|
||
GXSetTevOp. It will set the swap mode if
|
||
GX_CC_TEXC is selected for an input.
|
||
|
||
Note that it is available for Rev A or Rev B.
|
||
For Rev A, it is defined as an inline in hw.h.
|
||
|
||
Arguments: Same as GXSetTevOp
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
#if ( GX_REV > 1 )
|
||
//void hwSetTevOp(GXTevStageID id, GXTevMode mode)
|
||
//{
|
||
// GXTevColorArg carg = GX_CC_RASC;
|
||
// GXTevAlphaArg aarg = GX_CA_RASA;
|
||
//
|
||
// if (id != GX_TEVSTAGE0) {
|
||
// carg = GX_CC_CPREV;
|
||
// aarg = GX_CA_APREV;
|
||
// }
|
||
//
|
||
// switch (mode) {
|
||
// case GX_MODULATE:
|
||
// hwSetTevColorIn(id, GX_CC_ZERO, GX_CC_TEXC, carg, GX_CC_ZERO);
|
||
// GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO);
|
||
// break;
|
||
// case GX_DECAL:
|
||
// hwSetTevColorIn(id, carg, GX_CC_TEXC, GX_CC_TEXA, GX_CC_ZERO);
|
||
// GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg);
|
||
// break;
|
||
// case GX_BLEND:
|
||
// hwSetTevColorIn(id, carg, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
|
||
// GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO);
|
||
// break;
|
||
// case GX_REPLACE:
|
||
// hwSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
|
||
// GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
||
// break;
|
||
// case GX_PASSCLR:
|
||
// hwSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, carg);
|
||
// GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg);
|
||
// break;
|
||
// default:
|
||
// ASSERTMSG(0, "hwSetTevOp: Invalid Tev Mode");
|
||
// break;
|
||
// }
|
||
//
|
||
// GXSetTevColorOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
|
||
// GXSetTevAlphaOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
|
||
//}
|
||
#endif
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwGetRenderModeObj
|
||
|
||
Description: This function returns the current rendering mode.
|
||
It is most useful to inquire what the default
|
||
rendering mode is.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
GXRenderModeObj* hwGetRenderModeObj( void )
|
||
{
|
||
return rmode;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwGetCurrentBuffer
|
||
|
||
Description: This function returns the pointer to external
|
||
framebuffer currently active. Since this library
|
||
swiches double buffer hwFrameBuffer1/hwFrameBuffer2,
|
||
the returned pointer will be one of them.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void* hwGetCurrentBuffer( void )
|
||
{
|
||
return hwCurrentBuffer;
|
||
}
|
||
|
||
|
||
|
||
/*===========================================================================*
|
||
|
||
|
||
GP hang work-around auto-recovery system
|
||
|
||
|
||
*===========================================================================*/
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwEnableGPHangWorkaround
|
||
|
||
Description: Sets up the DEMO library to skip past any GP hangs and
|
||
attempt to repair the graphics pipe whenever a timeout
|
||
of /timeoutFrames/ occurs. This will serve as a
|
||
temporary work-around for any GP hangs that may occur.
|
||
|
||
|
||
Arguments: timeoutFrames The number of 60hz frames to wait in
|
||
hwDoneRender before aborting the
|
||
graphics pipe. Should be at least
|
||
equal to your standard frame rate
|
||
(e.g. 60hz games should use a value of 1,
|
||
30hz games should use a value of 2)
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void hwEnableGPHangWorkaround ( u32 timeoutFrames )
|
||
{
|
||
#ifdef EMU
|
||
#pragma unused (timeoutFrames)
|
||
#else
|
||
if (timeoutFrames)
|
||
{
|
||
// ASSERTMSG(!hwStatEnable,
|
||
// "DEMOStats and GP hang diagnosis are mutually exclusive");
|
||
GPHangWorkaround = TRUE;
|
||
FrameMissThreshold = timeoutFrames;
|
||
VISetPreRetraceCallback( __NoHangRetraceCallback );
|
||
|
||
// Enable counters for post-hang diagnosis
|
||
hwSetGPHangMetric( GX_TRUE );
|
||
}
|
||
else
|
||
{
|
||
GPHangWorkaround = FALSE;
|
||
FrameMissThreshold = 0;
|
||
hwSetGPHangMetric( GX_FALSE );
|
||
VISetPreRetraceCallback( NULL );
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __NoHangRetraceCallback
|
||
|
||
Description: VI callback to count missed frames for GPHangWorkaround
|
||
|
||
Arguments: Unused
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void __NoHangRetraceCallback ( u32 count )
|
||
{
|
||
// #pragma unused (count)
|
||
FrameCount++;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __NoHangDoneRender
|
||
|
||
Description: Called in lieu of the standard hwDoneRender if
|
||
GPHangWorkaround == TRUE.
|
||
|
||
Uses a token to check for end of frame so that we can
|
||
also count missed frames at the same time.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void __NoHangDoneRender()
|
||
{
|
||
BOOL abort = FALSE;
|
||
GX::CopyDisp(hwCurrentBuffer, GX_TRUE);
|
||
GX::SetDrawSync( hw_END_FRAME_TOKEN );
|
||
|
||
FrameCount = 0;
|
||
|
||
while( (GX::ReadDrawSync() != hw_END_FRAME_TOKEN ) && !abort )
|
||
{
|
||
if (FrameCount >= FrameMissThreshold)
|
||
{
|
||
OSReport("---------WARNING : ABORTING FRAME----------\n");
|
||
abort = TRUE;
|
||
__hwDiagnoseHang();
|
||
hwReInit(rmode); // XXX RMODE?
|
||
// re-enable counters for post-hang diagnosis
|
||
hwSetGPHangMetric( GX_TRUE );
|
||
}
|
||
}
|
||
|
||
hwSwapBuffers();
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwSetGPHangMetric
|
||
|
||
Description: Sets up the GP performance counters in such a way to
|
||
enable us to detect the cause of a GP hang. Note that
|
||
this takes over the performance counters, and you cannot
|
||
use GXSetGPMetric or GXInitXFRasMetric while you have
|
||
hwSetGPHangMetric enabled.
|
||
|
||
Arguments: enable: set to GX_TRUE to enable the counters.
|
||
set to GX_FALSE to disable the counters.
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void hwSetGPHangMetric( GXBool enable )
|
||
{
|
||
#ifdef EMU
|
||
#pragma unused (enable)
|
||
#else
|
||
if (enable)
|
||
{
|
||
// Ensure other counters are off
|
||
GX::SetGPMetric( GX_PERF0_NONE, GX_PERF1_NONE );
|
||
|
||
GX::EnableHang();
|
||
}
|
||
else
|
||
{
|
||
GX::DisableHang();
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __hwDiagnoseHang
|
||
|
||
Description: Reads performance counters (which should have been set
|
||
up appropriately already) in order to determine why the
|
||
GP hung. The counters must be set as follows:
|
||
|
||
GXSetGPHangMetric( GX_TRUE );
|
||
|
||
The above call actually sets up multiple counters, which
|
||
are read using a non-standard method.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void __hwDiagnoseHang()
|
||
{
|
||
u32 xfTop0, xfBot0, suRdy0, r0Rdy0;
|
||
u32 xfTop1, xfBot1, suRdy1, r0Rdy1;
|
||
u32 xfTopD, xfBotD, suRdyD, r0RdyD;
|
||
GXBool readIdle, cmdIdle, junk;
|
||
|
||
// Read the counters twice in order to see which are changing.
|
||
// This method of reading the counters works in this particular case.
|
||
// You should not use this method to read GPMetric counters.
|
||
GX::ReadXfRasMetric( &xfBot0, &xfTop0, &r0Rdy0, &suRdy0 );
|
||
GX::ReadXfRasMetric( &xfBot1, &xfTop1, &r0Rdy1, &suRdy1 );
|
||
|
||
// XF Top & Bot counters indicate busy, others indicate ready.
|
||
// Convert readings into indications of who is ready/idle.
|
||
xfTopD = (xfTop1 - xfTop0) == 0;
|
||
xfBotD = (xfBot1 - xfBot0) == 0;
|
||
suRdyD = (suRdy1 - suRdy0) > 0;
|
||
r0RdyD = (r0Rdy1 - r0Rdy0) > 0;
|
||
|
||
// Get CP status
|
||
GX::GetGPStatus(&junk, &junk, &readIdle, &cmdIdle, &junk);
|
||
|
||
OSReport("GP status %d%d%d%d%d%d --> ",
|
||
readIdle, cmdIdle, xfTopD, xfBotD, suRdyD, r0RdyD);
|
||
|
||
// Depending upon which counters are changing, diagnose the hang.
|
||
// This may not be 100% conclusive, but it's what we've observed so far.
|
||
if (!xfBotD && suRdyD)
|
||
{
|
||
OSReport("GP hang due to XF stall bug.\n");
|
||
}
|
||
else if (!xfTopD && xfBotD && suRdyD)
|
||
{
|
||
OSReport("GP hang due to unterminated primitive.\n");
|
||
}
|
||
else if (!cmdIdle && xfTopD && xfBotD && suRdyD)
|
||
{
|
||
OSReport("GP hang due to illegal instruction.\n");
|
||
}
|
||
else if (readIdle && cmdIdle && xfTopD && xfBotD && suRdyD && r0RdyD)
|
||
{
|
||
OSReport("GP appears to be not hung (waiting for input).\n");
|
||
}
|
||
else
|
||
{
|
||
OSReport("GP is in unknown state.\n");
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: __hwOverflowThread
|
||
|
||
Description: This thread is designed to detect a hang when the main
|
||
thread is suspended due to the high watermark interrupt.
|
||
If the GP hangs during this time, it is not typically
|
||
recoverable. However, we can still diagnose it.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void* __hwOverflowThread( void* param )
|
||
{
|
||
// #pragma unused (param)
|
||
GXBool overhi, junk;
|
||
u32 count;
|
||
OSTick tick1, tick2;
|
||
|
||
// There are at least two reasons why this thread may run:
|
||
// 1. Main thread suspended during high watermark.
|
||
// 2. Main thread suspended during GXDrawDone.
|
||
// Low watermark and GP finish can suspend this thread.
|
||
|
||
while (1)
|
||
{
|
||
// Wait for an overflow (hit to high watermark) to occur.
|
||
do
|
||
{
|
||
GX::GetGPStatus(&overhi, &junk, &junk, &junk, &junk);
|
||
}
|
||
while (!overhi);
|
||
|
||
// If GP hang workaround is off, don't do anything.
|
||
if (!FrameMissThreshold)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// Get a reading for this overflow and the current tick.
|
||
count = GX::GetOverflowCount();
|
||
tick1 = OSGetTick();
|
||
|
||
// Wait until either we time-out or until the next overflow.
|
||
// One frame is approximately 17 milliseconds.
|
||
do {
|
||
tick2 = OSGetTick();
|
||
} while (
|
||
OSTicksToMilliseconds(tick2 - tick1) < FrameMissThreshold * 17 &&
|
||
count == GX::GetOverflowCount() );
|
||
|
||
// Exiting the above loop does not imply a hang.
|
||
// We must check the overflow status once more to be certain.
|
||
GX::GetGPStatus(&overhi, &junk, &junk, &junk, &junk);
|
||
|
||
// If a new overflow started, then start timing again from the top.
|
||
if (!overhi || count != GX::GetOverflowCount())
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// We timed out. Report and diagnose the hang.
|
||
OSReport("---------WARNING : HANG AT HIGH WATERMARK----------\n");
|
||
|
||
__hwDiagnoseHang();
|
||
|
||
// We cannot easily recover from this situation. Halt program.
|
||
OSHalt("Halting program");
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: hwReInit
|
||
|
||
Description: Re-initializes the graphics pipe. Makes no assumptions
|
||
about the Fifo (allowing you to change it in your program
|
||
if needed).
|
||
|
||
Arguments: mode render mode object
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void hwReInit( GXRenderModeObj *mode )
|
||
{
|
||
// If an application specific render mode is provided,
|
||
// override the default render mode
|
||
if (mode != NULL)
|
||
{
|
||
rmode = mode;
|
||
}
|
||
else
|
||
{
|
||
rmode = &GXNtsc480IntDf;
|
||
|
||
// Trim off from top & bottom 16 scanlines (which will be overscanned).
|
||
// So almost all hws actually render only 448 lines (in NTSC case.)
|
||
// Since this setting is just for SDK hws, you can specify this
|
||
// in order to match your application requirements.
|
||
GX::AdjustForOverscan(rmode, &rmodeobj, 0, 16);
|
||
|
||
rmode = &rmodeobj;
|
||
|
||
OSReport( "TV format: %d\n", VIGetTvFormat() );
|
||
|
||
switch (VIGetTvFormat())
|
||
{
|
||
case VI_NTSC:
|
||
if ( NxNgc::EngineGlobals.use_480p )
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_NTSC_PROG;
|
||
rmode->xFBmode = VI_XFBMODE_SF;
|
||
}
|
||
break;
|
||
case VI_PAL:
|
||
if ( rmode->viTVmode == VI_TVMODE_NTSC_INT )
|
||
{
|
||
if ( NxNgc::EngineGlobals.use_60hz )
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_EURGB60_INT;
|
||
}
|
||
else
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_PAL_INT;
|
||
rmode->viYOrigin = 23;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( NxNgc::EngineGlobals.use_60hz )
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_EURGB60_DS;
|
||
}
|
||
else
|
||
{
|
||
rmode->viTVmode = VI_TVMODE_PAL_DS;
|
||
rmode->viYOrigin = 23;
|
||
}
|
||
}
|
||
if ( NxNgc::EngineGlobals.use_60hz )
|
||
{
|
||
rmode->xfbHeight = 448;
|
||
}
|
||
else
|
||
{
|
||
rmode->xfbHeight = ( rmode->xfbHeight * 528 ) / 448;
|
||
rmode->viHeight = 528;
|
||
}
|
||
break;
|
||
case VI_MPAL:
|
||
rmode = &GXMpal480IntDf;
|
||
break;
|
||
default:
|
||
OSHalt("hwInit: invalid TV format\n");
|
||
break;
|
||
}
|
||
rmode->viWidth = 650;
|
||
rmode->viXOrigin = 35;
|
||
|
||
VIConfigure(rmode);
|
||
__hwInitVI();
|
||
}
|
||
|
||
|
||
|
||
// // Create a temporary FIFO while the current one is reset
|
||
// GXFifoObj tmpobj;
|
||
// char* tmpFifo = new char[64*1024];
|
||
//
|
||
// // Get data on current Fifo.
|
||
// GXFifoObj* realFifoObj = GXGetCPUFifo();
|
||
// void* realFifoBase = GXGetFifoBase(realFifoObj);
|
||
// u32 realFifoSize = GXGetFifoSize(realFifoObj);
|
||
//
|
||
// // Abort the GP
|
||
// GXAbortFrame();
|
||
//
|
||
// GXInitFifoBase( &tmpobj, tmpFifo, 64*1024);
|
||
//
|
||
// GXSetCPUFifo(&tmpobj);
|
||
// GXSetGPFifo(&tmpobj);
|
||
//
|
||
// /*----------------------------------------------------------------*
|
||
// * Initialize Graphics again
|
||
// *----------------------------------------------------------------*/
|
||
// __hwInitRenderMode(mode);
|
||
//
|
||
// // This will re-initialize the pointers for the original FIFO.
|
||
// DefaultFifoObj = GXInit(realFifoBase, realFifoSize);
|
||
//
|
||
// __hwInitGX();
|
||
//
|
||
// // NOTE: the VI settings do not necessarily have to be reset, but
|
||
// // just to be safe, we do so anyway
|
||
// VIConfigure(rmode);
|
||
// __hwInitVI();
|
||
//
|
||
// // remove the temporary fifo
|
||
// delete tmpFifo;
|
||
}
|
||
|
||
void hwGXInit( void )
|
||
{
|
||
__hwInitGX();
|
||
}
|
||
|