2008-08-06 03:09:59 +02:00
/****************************************************************************
2008-09-12 07:28:40 +02:00
* Snes9x 1.51 Nintendo Wii / Gamecube Port
2008-08-06 03:09:59 +02:00
*
* softdev July 2006
* crunchy2 May 2007
2008-09-23 06:13:33 +02:00
* Michniewski 2008
2008-09-11 06:41:58 +02:00
*
* video . cpp
*
* Video routines
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
# include <gccore.h>
# include <ogcsys.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2008-08-06 03:39:43 +02:00
# include <unistd.h>
# include <wiiuse/wpad.h>
2008-08-06 03:09:59 +02:00
# include "snes9x.h"
# include "memmap.h"
# include "aram.h"
2008-08-06 04:31:44 +02:00
# include "snes9xGX.h"
2008-08-06 03:09:59 +02:00
2008-09-09 05:02:11 +02:00
# include "gui.h"
2008-08-06 03:09:59 +02:00
/*** Snes9x GFX Buffer ***/
static unsigned char snes9xgfx [ 1024 * 512 * 2 ] ;
/*** Memory ROM Loading ***/
extern unsigned long ARAM_ROMSIZE ;
extern unsigned int SMBTimer ;
/*** 2D Video ***/
unsigned int * xfb [ 2 ] = { NULL , NULL } ; /*** Double buffered ***/
int whichfb = 0 ; /*** Switch ***/
2008-08-24 01:15:58 +02:00
GXRModeObj * vmode ; /*** Menu video mode ***/
2008-08-06 03:39:43 +02:00
int screenheight ;
2008-08-06 03:45:56 +02:00
extern u32 * backdrop ;
2008-08-06 03:09:59 +02:00
/*** GX ***/
# define TEX_WIDTH 512
# define TEX_HEIGHT 512
# define DEFAULT_FIFO_SIZE 256 * 1024
unsigned int copynow = GX_FALSE ;
static unsigned char gp_fifo [ DEFAULT_FIFO_SIZE ] ATTRIBUTE_ALIGN ( 32 ) ;
static unsigned char texturemem [ TEX_WIDTH * ( TEX_HEIGHT + 8 ) ] ATTRIBUTE_ALIGN ( 32 ) ;
GXTexObj texobj ;
2008-09-09 05:02:11 +02:00
Mtx view ;
2008-08-06 03:09:59 +02:00
int vwidth , vheight , oldvwidth , oldvheight ;
2008-09-23 05:49:57 +02:00
float zoom_level = 1 ;
int zoom_xshift = 0 ;
int zoom_yshift = 0 ;
2008-08-06 03:09:59 +02:00
u32 FrameTimer = 0 ;
2008-08-06 03:39:43 +02:00
u8 vmode_60hz = 0 ;
2008-09-11 04:23:48 +02:00
bool progressive = 0 ;
2008-08-06 03:39:43 +02:00
2008-08-24 01:15:58 +02:00
# define HASPECT 320
# define VASPECT 240
2008-08-06 03:09:59 +02:00
/* New texture based scaler */
typedef struct tagcamera
{
Vector pos ;
Vector up ;
Vector view ;
}
camera ;
/*** Square Matrix
This structure controls the size of the image on the screen .
Think of the output as a - 80 x 80 by - 60 x 60 graph .
* * */
s16 square [ ] ATTRIBUTE_ALIGN ( 32 ) =
{
/*
* X , Y , Z
* Values set are for roughly 4 : 3 aspect
*/
- HASPECT , VASPECT , 0 , // 0
HASPECT , VASPECT , 0 , // 1
HASPECT , - VASPECT , 0 , // 2
- HASPECT , - VASPECT , 0 , // 3
} ;
2008-08-24 01:15:58 +02:00
2008-08-06 03:09:59 +02:00
static camera cam = { { 0.0F , 0.0F , 0.0F } ,
{ 0.0F , 0.5F , 0.0F } ,
{ 0.0F , 0.0F , - 0.5F }
} ;
2008-08-24 01:15:58 +02:00
2008-09-10 19:33:35 +02:00
/***
* * * Custom Video modes ( used to emulate original console video modes )
2008-08-24 01:15:58 +02:00
* * */
/** Original SNES PAL Resolutions: **/
/* 239 lines progressive (PAL 50Hz) */
GXRModeObj TV_239p =
{
VI_TVMODE_PAL_DS , // viDisplayMode
256 , // fbWidth
239 , // efbHeight
239 , // xfbHeight
2008-09-10 23:09:53 +02:00
( VI_MAX_WIDTH_PAL - 640 ) / 2 , // viXOrigin
2008-09-09 18:24:42 +02:00
( VI_MAX_HEIGHT_PAL / 2 - 478 / 2 ) / 2 , // viYOrigin
2008-09-10 23:09:53 +02:00
640 , // viWidth
2008-09-09 18:24:42 +02:00
478 , // viHeight
2008-08-24 01:15:58 +02:00
VI_XFBMODE_SF , // xFBmode
GX_FALSE , // field_rendering
GX_FALSE , // aa
// sample points arranged in increasing Y order
{
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 0, 3 sample points, 1/12 units, 4 bits each
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 1
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 2
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } // pix 3
} ,
// vertical filter[7], 1/64 units, 6 bits each
{
0 , // line n-1
0 , // line n-1
21 , // line n
22 , // line n
21 , // line n
0 , // line n+1
0 // line n+1
}
} ;
/* 478 lines interlaced (PAL 50Hz, Deflicker) */
GXRModeObj TV_478i =
{
VI_TVMODE_PAL_INT , // viDisplayMode
512 , // fbWidth
478 , // efbHeight
478 , // xfbHeight
2008-09-10 23:09:53 +02:00
( VI_MAX_WIDTH_PAL - 640 ) / 2 , // viXOrigin
2008-09-09 18:24:42 +02:00
( VI_MAX_HEIGHT_PAL / 2 - 478 / 2 ) / 2 , // viYOrigin
2008-09-10 23:09:53 +02:00
640 , // viWidth
2008-09-09 18:24:42 +02:00
478 , // viHeight
2008-08-24 01:15:58 +02:00
VI_XFBMODE_DF , // xFBmode
GX_FALSE , // field_rendering
GX_FALSE , // aa
// sample points arranged in increasing Y order
{
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 0, 3 sample points, 1/12 units, 4 bits each
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 1
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 2
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } // pix 3
} ,
// vertical filter[7], 1/64 units, 6 bits each
{
8 , // line n-1
8 , // line n-1
10 , // line n
12 , // line n
10 , // line n
8 , // line n+1
8 // line n+1
}
} ;
/** Original SNES NTSC Resolutions: **/
/* 224 lines progressive (NTSC or PAL 60Hz) */
GXRModeObj TV_224p =
{
VI_TVMODE_EURGB60_DS , // viDisplayMode
256 , // fbWidth
224 , // efbHeight
224 , // xfbHeight
2008-09-10 23:09:53 +02:00
( VI_MAX_WIDTH_NTSC - 640 ) / 2 , // viXOrigin
2008-09-09 18:24:42 +02:00
( VI_MAX_HEIGHT_NTSC / 2 - 448 / 2 ) / 2 , // viYOrigin
2008-09-10 23:09:53 +02:00
640 , // viWidth
2008-09-09 18:24:42 +02:00
448 , // viHeight
2008-08-24 01:15:58 +02:00
VI_XFBMODE_SF , // xFBmode
GX_FALSE , // field_rendering
GX_FALSE , // aa
// sample points arranged in increasing Y order
{
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 0, 3 sample points, 1/12 units, 4 bits each
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 1
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 2
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } // pix 3
} ,
// vertical filter[7], 1/64 units, 6 bits each
{
0 , // line n-1
0 , // line n-1
21 , // line n
22 , // line n
21 , // line n
0 , // line n+1
0 // line n+1
}
} ;
/* 448 lines interlaced (NTSC or PAL 60Hz, Deflicker) */
GXRModeObj TV_448i =
{
VI_TVMODE_EURGB60_INT , // viDisplayMode
512 , // fbWidth
448 , // efbHeight
448 , // xfbHeight
2008-09-10 23:09:53 +02:00
( VI_MAX_WIDTH_NTSC - 640 ) / 2 , // viXOrigin
2008-09-09 18:24:42 +02:00
( VI_MAX_HEIGHT_NTSC / 2 - 448 / 2 ) / 2 , // viYOrigin
2008-09-10 23:09:53 +02:00
640 , // viWidth
2008-09-09 18:24:42 +02:00
448 , // viHeight
2008-08-24 01:15:58 +02:00
VI_XFBMODE_DF , // xFBmode
GX_FALSE , // field_rendering
GX_FALSE , // aa
// sample points arranged in increasing Y order
{
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 0, 3 sample points, 1/12 units, 4 bits each
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 1
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } , // pix 2
{ 6 , 6 } , { 6 , 6 } , { 6 , 6 } // pix 3
} ,
// vertical filter[7], 1/64 units, 6 bits each
{
8 , // line n-1
8 , // line n-1
10 , // line n
12 , // line n
10 , // line n
8 , // line n+1
8 // line n+1
}
} ;
/* TV Modes table */
GXRModeObj * tvmodes [ 4 ] = {
& TV_239p , & TV_478i , /* Snes PAL video modes */
& TV_224p , & TV_448i , /* Snes NTSC video modes */
} ;
2008-08-06 03:09:59 +02:00
# ifdef VIDEO_THREADING
/****************************************************************************
* VideoThreading
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
# define TSTACK 16384
lwpq_t videoblankqueue ;
lwp_t vbthread ;
static unsigned char vbstack [ TSTACK ] ;
/****************************************************************************
* vbgetback
*
* This callback enables the emulator to keep running while waiting for a
2008-08-10 05:14:39 +02:00
* vertical blank .
2008-08-06 03:09:59 +02:00
*
* Putting LWP to good use : )
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
static void *
vbgetback ( void * arg )
{
2008-08-24 01:15:58 +02:00
while ( 1 )
{
VIDEO_WaitVSync ( ) ; /**< Wait for video vertical blank */
LWP_SuspendThread ( vbthread ) ;
}
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
return NULL ;
2008-08-06 03:09:59 +02:00
}
/****************************************************************************
* InitVideoThread
*
* libOGC provides a nice wrapper for LWP access .
* This function sets up a new local queue and attaches the thread to it .
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
void
InitVideoThread ( )
{
/*** Initialise a new queue ***/
2008-08-24 01:15:58 +02:00
LWP_InitQueue ( & videoblankqueue ) ;
2008-08-06 03:09:59 +02:00
/*** Create the thread on this queue ***/
2008-08-24 01:15:58 +02:00
LWP_CreateThread ( & vbthread , vbgetback , NULL , vbstack , TSTACK , 80 ) ;
2008-08-06 03:09:59 +02:00
}
# endif
/****************************************************************************
* copy_to_xfb
*
* Stock code to copy the GX buffer to the current display mode .
* Also increments the frameticker , as it ' s called for each vb .
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
static void
copy_to_xfb ( u32 arg )
{
2008-08-24 01:15:58 +02:00
if ( copynow = = GX_TRUE )
{
GX_CopyDisp ( xfb [ whichfb ] , GX_TRUE ) ;
GX_Flush ( ) ;
copynow = GX_FALSE ;
}
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
FrameTimer + + ;
SMBTimer + + ;
2008-08-06 03:09:59 +02:00
}
/****************************************************************************
2008-08-24 01:15:58 +02:00
* Scaler Support Functions
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
static void
draw_init ( )
{
2008-08-24 01:15:58 +02:00
GX_ClearVtxDesc ( ) ;
GX_SetVtxDesc ( GX_VA_POS , GX_INDEX8 ) ;
GX_SetVtxDesc ( GX_VA_CLR0 , GX_INDEX8 ) ;
GX_SetVtxDesc ( GX_VA_TEX0 , GX_DIRECT ) ;
GX_SetVtxAttrFmt ( GX_VTXFMT0 , GX_VA_POS , GX_POS_XYZ , GX_S16 , 0 ) ;
GX_SetVtxAttrFmt ( GX_VTXFMT0 , GX_VA_CLR0 , GX_CLR_RGBA , GX_RGBA8 , 0 ) ;
GX_SetVtxAttrFmt ( GX_VTXFMT0 , GX_VA_TEX0 , GX_TEX_ST , GX_F32 , 0 ) ;
GX_SetArray ( GX_VA_POS , square , 3 * sizeof ( s16 ) ) ;
GX_SetNumTexGens ( 1 ) ;
GX_SetNumChans ( 0 ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetTexCoordGen ( GX_TEXCOORD0 , GX_TG_MTX2x4 , GX_TG_TEX0 , GX_IDENTITY ) ;
2008-09-23 05:49:57 +02:00
2008-08-24 01:15:58 +02:00
GX_SetTevOp ( GX_TEVSTAGE0 , GX_REPLACE ) ;
GX_SetTevOrder ( GX_TEVSTAGE0 , GX_TEXCOORD0 , GX_TEXMAP0 , GX_COLORNULL ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
memset ( & view , 0 , sizeof ( Mtx ) ) ;
guLookAt ( view , & cam . pos , & cam . up , & cam . view ) ;
GX_LoadPosMtxImm ( view , GX_PNMTX0 ) ;
2008-08-06 03:09:59 +02:00
}
static void
draw_vert ( u8 pos , u8 c , f32 s , f32 t )
{
2008-08-24 01:15:58 +02:00
GX_Position1x8 ( pos ) ;
GX_Color1x8 ( c ) ;
GX_TexCoord2f32 ( s , t ) ;
2008-08-06 03:09:59 +02:00
}
static void
draw_square ( Mtx v )
{
2008-08-24 01:15:58 +02:00
Mtx m ; // model matrix.
Mtx mv ; // modelview matrix.
guMtxIdentity ( m ) ;
guMtxTransApply ( m , m , 0 , 0 , - 100 ) ;
guMtxConcat ( v , m , mv ) ;
GX_LoadPosMtxImm ( mv , GX_PNMTX0 ) ;
GX_Begin ( GX_QUADS , GX_VTXFMT0 , 4 ) ;
draw_vert ( 0 , 0 , 0.0 , 0.0 ) ;
draw_vert ( 1 , 0 , 1.0 , 0.0 ) ;
draw_vert ( 2 , 0 , 1.0 , 1.0 ) ;
draw_vert ( 3 , 0 , 0.0 , 1.0 ) ;
GX_End ( ) ;
2008-08-06 03:09:59 +02:00
}
/****************************************************************************
* StartGX
*
* This function initialises the GX .
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
static void
StartGX ( )
{
2008-08-24 01:15:58 +02:00
Mtx p ;
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
GXColor background = { 0 , 0 , 0 , 0xff } ;
2008-08-06 03:09:59 +02:00
/*** Clear out FIFO area ***/
2008-08-24 01:15:58 +02:00
memset ( & gp_fifo , 0 , DEFAULT_FIFO_SIZE ) ;
2008-08-06 03:09:59 +02:00
/*** Initialise GX ***/
2008-08-24 01:15:58 +02:00
GX_Init ( & gp_fifo , DEFAULT_FIFO_SIZE ) ;
GX_SetCopyClear ( background , 0x00ffffff ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetViewport ( 0 , 0 , vmode - > fbWidth , vmode - > efbHeight , 0 , 1 ) ;
GX_SetDispCopyYScale ( ( f32 ) vmode - > xfbHeight / ( f32 ) vmode - > efbHeight ) ;
GX_SetScissor ( 0 , 0 , vmode - > fbWidth , vmode - > efbHeight ) ;
GX_SetDispCopySrc ( 0 , 0 , vmode - > fbWidth , vmode - > efbHeight ) ;
GX_SetDispCopyDst ( vmode - > fbWidth , vmode - > xfbHeight ) ;
GX_SetCopyFilter ( vmode - > aa , vmode - > sample_pattern , GX_TRUE , vmode - > vfilter ) ;
GX_SetFieldMode ( vmode - > field_rendering , ( ( vmode - > viHeight = = 2 * vmode - > xfbHeight ) ? GX_ENABLE : GX_DISABLE ) ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetPixelFmt ( GX_PF_RGB8_Z24 , GX_ZC_LINEAR ) ;
GX_SetCullMode ( GX_CULL_NONE ) ;
GX_SetDispCopyGamma ( GX_GM_1_0 ) ;
2008-08-25 07:57:43 +02:00
GX_SetZMode ( GX_TRUE , GX_LEQUAL , GX_TRUE ) ;
2008-08-24 01:15:58 +02:00
GX_SetColorUpdate ( GX_TRUE ) ;
2008-09-10 19:33:35 +02:00
2008-09-09 05:02:11 +02:00
gui_alphasetup ( ) ;
2008-08-24 01:15:58 +02:00
guOrtho ( p , vmode - > efbHeight / 2 , - ( vmode - > efbHeight / 2 ) , - ( vmode - > fbWidth / 2 ) , vmode - > fbWidth / 2 , 10 , 1000 ) ; // matrix, t, b, l, r, n, f
GX_LoadProjectionMtx ( p , GX_ORTHOGRAPHIC ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_CopyDisp ( xfb [ whichfb ] , GX_TRUE ) ; // reset xfb
vwidth = 100 ;
vheight = 100 ;
2008-08-06 03:09:59 +02:00
}
2008-08-06 03:39:43 +02:00
/****************************************************************************
2008-08-24 01:15:58 +02:00
* UpdatePadsCB
2008-08-06 03:39:43 +02:00
*
* called by postRetraceCallback in InitGCVideo - scans gcpad and wpad
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-24 01:15:58 +02:00
void
UpdatePadsCB ( )
2008-08-06 03:39:43 +02:00
{
2008-08-06 03:45:56 +02:00
# ifdef HW_RVL
2008-08-06 03:39:43 +02:00
WPAD_ScanPads ( ) ;
2008-08-06 03:45:56 +02:00
# endif
2008-08-06 03:39:43 +02:00
PAD_ScanPads ( ) ;
}
2008-08-10 05:14:39 +02:00
2008-08-06 03:09:59 +02:00
/****************************************************************************
* InitGCVideo
*
* This function MUST be called at startup .
2008-08-24 01:15:58 +02:00
* - also sets up menu video mode
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
void
InitGCVideo ( )
{
2008-08-24 01:15:58 +02:00
// init video
2008-08-06 03:09:59 +02:00
VIDEO_Init ( ) ;
2008-09-11 06:41:58 +02:00
2008-08-24 01:15:58 +02:00
// get default video mode
2008-08-06 03:39:43 +02:00
vmode = VIDEO_GetPreferredMode ( NULL ) ;
2008-08-24 01:15:58 +02:00
switch ( vmode - > viTVMode > > 2 )
2008-08-06 03:39:43 +02:00
{
2008-09-11 06:41:58 +02:00
case VI_PAL :
2008-09-11 04:23:48 +02:00
// 576 lines (PAL 50Hz)
// display should be centered vertically (borders)
2008-08-24 01:15:58 +02:00
vmode = & TVPal574IntDfScale ;
vmode - > xfbHeight = 480 ;
vmode - > viYOrigin = ( VI_MAX_HEIGHT_PAL - 480 ) / 2 ;
vmode - > viHeight = 480 ;
2008-09-11 06:41:58 +02:00
2008-09-11 04:23:48 +02:00
vmode_60hz = 0 ;
2008-08-06 03:39:43 +02:00
break ;
2008-09-11 06:41:58 +02:00
case VI_NTSC :
2008-09-11 04:23:48 +02:00
// 480 lines (NTSC 60hz)
2008-08-24 01:15:58 +02:00
vmode_60hz = 1 ;
break ;
2008-09-11 06:41:58 +02:00
default :
2008-09-11 04:23:48 +02:00
// 480 lines (PAL 60Hz)
2008-08-06 03:39:43 +02:00
vmode_60hz = 1 ;
break ;
}
2008-09-10 19:33:35 +02:00
2008-09-09 05:02:11 +02:00
// check for progressive scan
2008-09-11 04:23:48 +02:00
if ( vmode - > viTVMode = = VI_TVMODE_NTSC_PROG )
progressive = true ;
2008-09-11 06:41:58 +02:00
2008-08-10 05:14:39 +02:00
2008-08-06 03:09:59 +02:00
VIDEO_Configure ( vmode ) ;
2008-08-10 05:14:39 +02:00
2008-08-06 03:09:59 +02:00
screenheight = vmode - > xfbHeight ;
2008-09-10 19:33:35 +02:00
2008-08-10 05:14:39 +02:00
2008-08-24 01:15:58 +02:00
// Allocate the video buffers
2008-08-06 03:39:43 +02:00
xfb [ 0 ] = ( u32 * ) MEM_K0_TO_K1 ( SYS_AllocateFramebuffer ( vmode ) ) ;
xfb [ 1 ] = ( u32 * ) MEM_K0_TO_K1 ( SYS_AllocateFramebuffer ( vmode ) ) ;
2008-08-10 05:14:39 +02:00
2008-08-24 01:15:58 +02:00
// A console is always useful while debugging.
2008-08-06 03:39:43 +02:00
console_init ( xfb [ 0 ] , 20 , 64 , vmode - > fbWidth , vmode - > xfbHeight , vmode - > fbWidth * 2 ) ;
2008-08-10 05:14:39 +02:00
2008-08-24 01:15:58 +02:00
// Clear framebuffers etc.
2008-08-06 03:09:59 +02:00
VIDEO_ClearFrameBuffer ( vmode , xfb [ 0 ] , COLOR_BLACK ) ;
VIDEO_ClearFrameBuffer ( vmode , xfb [ 1 ] , COLOR_BLACK ) ;
VIDEO_SetNextFramebuffer ( xfb [ 0 ] ) ;
2008-08-10 05:14:39 +02:00
2008-08-24 01:15:58 +02:00
// video callbacks
2008-08-06 03:39:43 +02:00
VIDEO_SetPostRetraceCallback ( ( VIRetraceCallback ) UpdatePadsCB ) ;
VIDEO_SetPreRetraceCallback ( ( VIRetraceCallback ) copy_to_xfb ) ;
2008-09-10 19:33:35 +02:00
2008-08-06 03:09:59 +02:00
VIDEO_SetBlack ( FALSE ) ;
VIDEO_Flush ( ) ;
VIDEO_WaitVSync ( ) ;
if ( vmode - > viTVMode & VI_NON_INTERLACE )
2008-08-24 01:15:58 +02:00
VIDEO_WaitVSync ( ) ;
2008-08-10 05:14:39 +02:00
2008-08-06 03:09:59 +02:00
copynow = GX_FALSE ;
StartGX ( ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
draw_init ( ) ;
2008-08-10 05:14:39 +02:00
2008-08-06 03:09:59 +02:00
# ifdef VIDEO_THREADING
InitVideoThread ( ) ;
# endif
2008-08-10 05:14:39 +02:00
2008-08-24 01:15:58 +02:00
// Finally, the video is up and ready for use :)
2008-08-06 04:31:44 +02:00
}
2008-08-06 03:09:59 +02:00
/****************************************************************************
2008-09-12 07:28:40 +02:00
* ResetVideo_Emu
*
* Reset the video / rendering mode for the emulator rendering
2008-08-24 01:15:58 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
void
2008-08-24 01:15:58 +02:00
ResetVideo_Emu ( )
2008-08-06 03:09:59 +02:00
{
2008-08-24 01:15:58 +02:00
GXRModeObj * rmode ;
Mtx p ;
2008-09-10 19:33:35 +02:00
2008-09-11 04:23:48 +02:00
switch ( vmode - > viTVMode > > 2 )
{
case VI_PAL : /* 576 lines (PAL 50Hz) */
// set video signal mode
TV_239p . viTVMode = VI_TVMODE_PAL_DS ;
TV_478i . viTVMode = VI_TVMODE_PAL_INT ;
TV_224p . viTVMode = VI_TVMODE_PAL_DS ;
TV_448i . viTVMode = VI_TVMODE_PAL_INT ;
2008-09-23 05:49:57 +02:00
// set VI position
2008-09-11 04:23:48 +02:00
TV_239p . viXOrigin = TV_478i . viXOrigin = TV_224p . viXOrigin = TV_448i . viXOrigin = ( VI_MAX_WIDTH_PAL - 640 ) / 2 ;
TV_239p . viYOrigin = TV_478i . viYOrigin = ( VI_MAX_HEIGHT_PAL / 2 - 478 / 2 ) / 2 ;
TV_224p . viYOrigin = TV_448i . viYOrigin = ( VI_MAX_HEIGHT_PAL / 2 - 448 / 2 ) / 2 ;
break ;
case VI_NTSC : /* 480 lines (NTSC 60hz) */
// set video signal mode
TV_239p . viTVMode = VI_TVMODE_NTSC_DS ;
TV_478i . viTVMode = VI_TVMODE_NTSC_INT ;
TV_224p . viTVMode = VI_TVMODE_NTSC_DS ;
TV_448i . viTVMode = VI_TVMODE_NTSC_INT ;
2008-09-23 05:49:57 +02:00
// set VI position
2008-09-11 04:23:48 +02:00
TV_239p . viXOrigin = TV_224p . viXOrigin = TV_478i . viXOrigin = TV_448i . viXOrigin = ( VI_MAX_WIDTH_NTSC - 640 ) / 2 ;
TV_239p . viYOrigin = TV_478i . viYOrigin = ( VI_MAX_HEIGHT_NTSC / 2 - 478 / 2 ) / 2 ;
TV_224p . viYOrigin = TV_448i . viYOrigin = ( VI_MAX_HEIGHT_NTSC / 2 - 448 / 2 ) / 2 ;
break ;
default : /* 480 lines (PAL 60Hz) */
// set video signal mode
TV_239p . viTVMode = VI_TVMODE ( vmode - > viTVMode > > 2 , VI_NON_INTERLACE ) ;
TV_478i . viTVMode = VI_TVMODE ( vmode - > viTVMode > > 2 , VI_INTERLACE ) ;
TV_224p . viTVMode = VI_TVMODE ( vmode - > viTVMode > > 2 , VI_NON_INTERLACE ) ;
TV_448i . viTVMode = VI_TVMODE ( vmode - > viTVMode > > 2 , VI_INTERLACE ) ;
2008-09-23 05:49:57 +02:00
// set VI position
2008-09-11 04:23:48 +02:00
TV_239p . viXOrigin = TV_224p . viXOrigin = TV_478i . viXOrigin = TV_448i . viXOrigin = ( VI_MAX_WIDTH_NTSC - 640 ) / 2 ;
TV_239p . viYOrigin = TV_478i . viYOrigin = ( VI_MAX_HEIGHT_NTSC / 2 - 478 / 2 ) / 2 ;
TV_224p . viYOrigin = TV_448i . viYOrigin = ( VI_MAX_HEIGHT_NTSC / 2 - 448 / 2 ) / 2 ;
break ;
}
2008-09-11 06:41:58 +02:00
2008-09-23 05:49:57 +02:00
int i = - 1 ;
2008-09-11 04:23:48 +02:00
if ( GCSettings . render = = 0 ) // original render mode
2008-08-24 01:15:58 +02:00
{
for ( i = 0 ; i < 4 ; i + + ) {
2008-09-09 05:02:11 +02:00
if ( tvmodes [ i ] - > efbHeight = = vheight ) {
2008-09-11 04:23:48 +02:00
// FIX: ok?
2008-09-09 05:02:11 +02:00
tvmodes [ i ] - > fbWidth = vwidth ; // update width - some games are 512x224 (super pang)
break ;
}
2008-08-24 01:15:58 +02:00
}
rmode = tvmodes [ i ] ;
2008-09-10 19:33:35 +02:00
}
2008-09-11 04:23:48 +02:00
else if ( GCSettings . render = = 2 ) // unfiltered
{
rmode = vmode ;
2008-09-11 06:41:58 +02:00
}
2008-09-11 04:23:48 +02:00
else // filtered
{
2008-08-24 01:15:58 +02:00
rmode = vmode ; // same mode as menu
2008-09-11 04:23:48 +02:00
}
2008-08-24 01:15:58 +02:00
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
VIDEO_Configure ( rmode ) ;
VIDEO_ClearFrameBuffer ( rmode , xfb [ whichfb ] , COLOR_BLACK ) ;
VIDEO_Flush ( ) ;
VIDEO_WaitVSync ( ) ;
if ( rmode - > viTVMode & VI_NON_INTERLACE ) VIDEO_WaitVSync ( ) ;
else while ( VIDEO_GetNextField ( ) ) VIDEO_WaitVSync ( ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetViewport ( 0 , 0 , rmode - > fbWidth , rmode - > efbHeight , 0 , 1 ) ;
GX_SetDispCopyYScale ( ( f32 ) rmode - > xfbHeight / ( f32 ) rmode - > efbHeight ) ;
GX_SetScissor ( 0 , 0 , rmode - > fbWidth , rmode - > efbHeight ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetDispCopySrc ( 0 , 0 , rmode - > fbWidth , rmode - > efbHeight ) ;
GX_SetDispCopyDst ( rmode - > fbWidth , rmode - > xfbHeight ) ;
2008-09-11 04:23:48 +02:00
GX_SetCopyFilter ( rmode - > aa , rmode - > sample_pattern , ( GCSettings . render = = 1 ) ? GX_TRUE : GX_FALSE , rmode - > vfilter ) ; // AA on only for filtered mode
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetFieldMode ( rmode - > field_rendering , ( ( rmode - > viHeight = = 2 * rmode - > xfbHeight ) ? GX_ENABLE : GX_DISABLE ) ) ;
GX_SetPixelFmt ( GX_PF_RGB8_Z24 , GX_ZC_LINEAR ) ;
guOrtho ( p , rmode - > efbHeight / 2 , - ( rmode - > efbHeight / 2 ) , - ( rmode - > fbWidth / 2 ) , rmode - > fbWidth / 2 , 10 , 1000 ) ; // matrix, t, b, l, r, n, f
GX_LoadProjectionMtx ( p , GX_ORTHOGRAPHIC ) ;
2008-09-10 19:33:35 +02:00
2008-09-23 05:49:57 +02:00
# ifdef _DEBUG_VIDEO
// log stuff
fprintf ( debughandle , " \n \n rmode = tvmodes[%d], field_rendering: %d " , i , ( rmode - > viHeight = = 2 * rmode - > xfbHeight ) ) ;
fprintf ( debughandle , " \n Interlaced: %i, \t vwidth: %d, vheight: %d, \t fb_W: %u, efb_H: %u " , IPPU . Interlace , vwidth , vheight , rmode - > fbWidth , rmode - > efbHeight ) ;
# endif
2008-08-06 03:09:59 +02:00
}
/****************************************************************************
2008-09-12 07:28:40 +02:00
* ResetVideo_Menu
*
* Reset the video / rendering mode for the menu
2008-08-24 01:15:58 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
void
2008-08-24 01:15:58 +02:00
ResetVideo_Menu ( )
2008-08-06 03:09:59 +02:00
{
2008-08-24 01:15:58 +02:00
Mtx p ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
VIDEO_Configure ( vmode ) ;
VIDEO_ClearFrameBuffer ( vmode , xfb [ whichfb ] , COLOR_BLACK ) ;
VIDEO_Flush ( ) ;
VIDEO_WaitVSync ( ) ;
if ( vmode - > viTVMode & VI_NON_INTERLACE ) VIDEO_WaitVSync ( ) ;
else while ( VIDEO_GetNextField ( ) ) VIDEO_WaitVSync ( ) ;
GX_SetViewport ( 0 , 0 , vmode - > fbWidth , vmode - > efbHeight , 0 , 1 ) ;
GX_SetDispCopyYScale ( ( f32 ) vmode - > xfbHeight / ( f32 ) vmode - > efbHeight ) ;
GX_SetScissor ( 0 , 0 , vmode - > fbWidth , vmode - > efbHeight ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetDispCopySrc ( 0 , 0 , vmode - > fbWidth , vmode - > efbHeight ) ;
GX_SetDispCopyDst ( vmode - > fbWidth , vmode - > xfbHeight ) ;
GX_SetCopyFilter ( vmode - > aa , vmode - > sample_pattern , GX_TRUE , vmode - > vfilter ) ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
GX_SetFieldMode ( vmode - > field_rendering , ( ( vmode - > viHeight = = 2 * vmode - > xfbHeight ) ? GX_ENABLE : GX_DISABLE ) ) ;
GX_SetPixelFmt ( GX_PF_RGB8_Z24 , GX_ZC_LINEAR ) ;
guOrtho ( p , vmode - > efbHeight / 2 , - ( vmode - > efbHeight / 2 ) , - ( vmode - > fbWidth / 2 ) , vmode - > fbWidth / 2 , 10 , 1000 ) ; // matrix, t, b, l, r, n, f
GX_LoadProjectionMtx ( p , GX_ORTHOGRAPHIC ) ;
2008-08-06 03:09:59 +02:00
}
/****************************************************************************
2008-08-10 05:14:39 +02:00
* MakeTexture
2008-08-06 03:09:59 +02:00
*
* Proper GNU Asm rendition of the above , converted by shagkur . - Thanks !
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
void
MakeTexture ( const void * src , void * dst , s32 width , s32 height )
{
register u32 tmp0 = 0 , tmp1 = 0 , tmp2 = 0 , tmp3 = 0 ;
__asm__ __volatile__ ( " srwi %6,%6,2 \n "
" srwi %7,%7,2 \n "
" subi %3,%4,4 \n "
" mr %4,%3 \n "
" subi %4,%4,4 \n "
" 2: mtctr %6 \n "
" mr %0,%5 \n "
2008-08-10 05:14:39 +02:00
//
2008-08-06 03:09:59 +02:00
" 1: lwz %1,0(%5) \n "
" stwu %1,8(%4) \n "
" lwz %2,4(%5) \n "
" stwu %2,8(%3) \n "
" lwz %1,1024(%5) \n "
" stwu %1,8(%4) \n "
" lwz %2,1028(%5) \n "
" stwu %2,8(%3) \n "
" lwz %1,2048(%5) \n "
" stwu %1,8(%4) \n "
" lwz %2,2052(%5) \n "
" stwu %2,8(%3) \n "
" lwz %1,3072(%5) \n "
" stwu %1,8(%4) \n "
" lwz %2,3076(%5) \n "
" stwu %2,8(%3) \n "
" addi %5,%5,8 \n "
" bdnz 1b \n "
" addi %5,%0,4096 \n "
" subic. %7,%7,1 \n "
" bne 2b "
2008-08-10 05:14:39 +02:00
// 0 1 2 3 4 5 6 7
2008-08-06 03:09:59 +02:00
: " =&r " ( tmp0 ) , " =&r " ( tmp1 ) , " =&r " ( tmp2 ) ,
" =&r " ( tmp3 ) , " +r " ( dst ) : " r " ( src ) , " r " ( width ) ,
" r " ( height ) ) ;
}
/****************************************************************************
* Update Video
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-25 07:57:43 +02:00
uint32 prevRenderedFrameCount = 0 ;
extern bool CheckVideo ;
2008-08-06 03:09:59 +02:00
void
update_video ( int width , int height )
{
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
vwidth = width ;
vheight = height ;
2008-08-06 03:09:59 +02:00
# ifdef VIDEO_THREADING
2008-09-11 04:23:48 +02:00
// Ensure previous vb has complete
2008-08-24 01:15:58 +02:00
while ( ( LWP_ThreadIsSuspended ( vbthread ) = = 0 ) | | ( copynow = = GX_TRUE ) )
2008-08-06 03:09:59 +02:00
# else
2008-08-24 01:15:58 +02:00
while ( copynow = = GX_TRUE )
2008-08-06 03:09:59 +02:00
# endif
2008-08-24 01:15:58 +02:00
{
usleep ( 50 ) ;
}
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
whichfb ^ = 1 ;
2008-09-09 23:26:12 +02:00
if ( oldvheight ! = vheight | | oldvwidth ! = vwidth ) // if rendered width/height changes, update scaling
CheckVideo = 1 ;
2008-09-10 19:33:35 +02:00
2008-09-09 23:26:12 +02:00
if ( CheckVideo & & ( IPPU . RenderedFramesCount ! = prevRenderedFrameCount ) ) // if we get back from the menu, and have rendered at least 1 frame
2008-08-24 01:15:58 +02:00
{
2008-09-28 04:13:19 +02:00
int xscale , yscale ;
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
ResetVideo_Emu ( ) ; // reset video to emulator rendering settings
2008-09-10 19:33:35 +02:00
2008-08-06 03:09:59 +02:00
/** Update scaling **/
2008-09-11 04:23:48 +02:00
if ( GCSettings . render = = 0 ) // original render mode
2008-08-24 01:15:58 +02:00
{
xscale = vwidth / 2 ;
yscale = vheight / 2 ;
2008-09-11 04:23:48 +02:00
} else { // unfiltered and filtered mode
xscale = vmode - > fbWidth / 2 ;
yscale = vmode - > efbHeight / 2 ;
2008-08-24 01:15:58 +02:00
}
2008-09-10 19:33:35 +02:00
2008-08-25 07:57:43 +02:00
// aspect ratio scaling (change width scale)
// yes its pretty cheap and ugly, but its easy!
2008-09-11 04:23:48 +02:00
if ( GCSettings . widescreen )
2008-08-25 07:57:43 +02:00
xscale - = ( 4.0 * yscale ) / 9 ;
2008-09-27 09:13:52 +02:00
2008-09-23 05:49:57 +02:00
xscale * = zoom_level ;
yscale * = zoom_level ;
2008-09-10 19:33:35 +02:00
2008-09-28 04:13:19 +02:00
square [ 6 ] = square [ 3 ] = xscale + GCSettings . xshift ;
square [ 0 ] = square [ 9 ] = - xscale + GCSettings . xshift ;
2008-09-30 08:43:34 +02:00
square [ 4 ] = square [ 1 ] = yscale - GCSettings . yshift ;
square [ 7 ] = square [ 10 ] = - yscale - GCSettings . yshift ;
2008-09-11 06:41:58 +02:00
2008-09-11 04:23:48 +02:00
GX_InvVtxCache ( ) ; // update vertex cache
2008-08-24 01:15:58 +02:00
2008-09-11 04:23:48 +02:00
GX_InitTexObj ( & texobj , texturemem , vwidth , vheight , GX_TF_RGB565 , GX_CLAMP , GX_CLAMP , GX_FALSE ) ; // initialize the texture obj we are going to use
2008-09-10 19:33:35 +02:00
2008-09-11 04:23:48 +02:00
if ( GCSettings . render = = 0 | | GCSettings . render = = 2 )
GX_InitTexObjLOD ( & texobj , GX_NEAR , GX_NEAR_MIP_NEAR , 2.5 , 9.0 , 0.0 , GX_FALSE , GX_FALSE , GX_ANISO_1 ) ; // original/unfiltered video mode: force texture filtering OFF
2008-09-11 06:41:58 +02:00
2008-09-11 04:23:48 +02:00
GX_LoadTexObj ( & texobj , GX_TEXMAP0 ) ; // load texture object so its ready to use
2008-09-10 19:33:35 +02:00
2008-09-23 05:49:57 +02:00
# ifdef _DEBUG_VIDEO
// log stuff
fprintf ( debughandle , " \n xscale: %d, yscale: %d " , xscale , yscale ) ;
# endif
2008-09-10 19:33:35 +02:00
2008-08-24 01:15:58 +02:00
oldvwidth = vwidth ;
oldvheight = vheight ;
2008-08-25 07:57:43 +02:00
CheckVideo = 0 ;
2008-08-24 01:15:58 +02:00
}
2008-09-11 06:41:58 +02:00
2008-09-11 04:23:48 +02:00
MakeTexture ( ( char * ) GFX . Screen , ( char * ) texturemem , vwidth , vheight ) ; // convert image to texture
2008-08-06 03:09:59 +02:00
2008-09-11 04:23:48 +02:00
DCFlushRange ( texturemem , TEX_WIDTH * TEX_HEIGHT * 2 ) ; // update the texture memory
GX_InvalidateTexAll ( ) ;
2008-08-06 03:09:59 +02:00
2008-09-11 04:23:48 +02:00
draw_square ( view ) ; // draw the quad
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
GX_DrawDone ( ) ;
VIDEO_SetNextFramebuffer ( xfb [ whichfb ] ) ;
VIDEO_Flush ( ) ;
copynow = GX_TRUE ;
2008-08-06 04:31:44 +02:00
2008-08-24 01:15:58 +02:00
# ifdef VIDEO_THREADING
2008-09-11 04:23:48 +02:00
// Return to caller, don't waste time waiting for vb
2008-08-24 01:15:58 +02:00
LWP_ResumeThread ( vbthread ) ;
# endif
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
}
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
/****************************************************************************
* Zoom Functions
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-24 01:15:58 +02:00
void
zoom ( float speed )
{
2008-09-23 05:49:57 +02:00
if ( zoom_level > 1 )
zoom_level + = ( speed / - 100.0 ) ;
else
zoom_level + = ( speed / - 200.0 ) ;
2008-09-27 09:13:52 +02:00
2008-09-23 05:49:57 +02:00
if ( zoom_level < 0.5 ) zoom_level = 0.5 ;
else if ( zoom_level > 10.0 ) zoom_level = 10.0 ;
2008-09-27 09:13:52 +02:00
2008-08-24 01:15:58 +02:00
oldvheight = 0 ; // update video
}
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
void
zoom_reset ( )
{
2008-09-23 05:49:57 +02:00
zoom_level = 1.0 ;
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
oldvheight = 0 ; // update video
2008-08-06 03:09:59 +02:00
}
2008-08-24 01:15:58 +02:00
/****************************************************************************
* Drawing screen
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-06 03:09:59 +02:00
void
2008-08-24 01:15:58 +02:00
clearscreen ( int colour )
2008-08-06 03:09:59 +02:00
{
2008-08-24 01:15:58 +02:00
whichfb ^ = 1 ;
VIDEO_ClearFrameBuffer ( vmode , xfb [ whichfb ] , colour ) ;
# ifdef HW_RVL
// on wii copy from memory
memcpy ( ( char * ) xfb [ whichfb ] , ( char * ) backdrop , 640 * screenheight * 2 ) ;
# else
// on gc copy from aram
ARAMFetch ( ( char * ) xfb [ whichfb ] , ( char * ) AR_BACKDROP , 640 * screenheight * 2 ) ;
# endif
}
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
void
showscreen ( )
{
copynow = GX_FALSE ;
VIDEO_SetNextFramebuffer ( xfb [ whichfb ] ) ;
VIDEO_Flush ( ) ;
VIDEO_WaitVSync ( ) ;
}
2008-08-06 03:09:59 +02:00
2008-08-24 01:15:58 +02:00
/****************************************************************************
* setGFX
*
* Setup the global GFX information for Snes9x
2008-09-12 07:28:40 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-24 01:15:58 +02:00
void
setGFX ( )
{
GFX . Screen = ( unsigned short * ) snes9xgfx ;
GFX . Pitch = 1024 ;
2008-08-06 03:09:59 +02:00
}